2 #include "../port/lib.h"
8 #include "../port/error.h"
24 static int fpunimp(ulong);
25 static ulong branch(Ureg*, ulong);
32 if((up->fpsave.fpstatus&(1<<17)) == 0)
35 if(ur->cause & (1<<31))
36 iw = *(ulong*)(ur->pc+4);
43 if(ur->cause & (1<<31)){
44 npc = branch(ur, up->fpsave.fpstatus);
52 up->fpsave.fpstatus &= ~(1<<17);
56 unpack(FPsave *f, int fmt, int reg, int *sign, int *exp)
59 if(f->reg[reg] & 0x80000000)
64 *exp = ((f->reg[reg]>>23)&0xFF) - ((1<<7)-2);
67 if(reg & 1) /* shouldn't happen */
69 *exp = ((f->reg[reg]>>20)&0x7FF) - ((1<<10)-2);
75 zeroreg(FPsave *f, int fmt, int reg, int sign)
90 memset(&f->reg[reg], 0, size);
92 f->reg[reg] |= 0x80000000;
101 ulong op, fmt, ft, fs, fd;
105 op = iw & ((1<<6)-1);
106 fmt = (iw>>21) & ((1<<4)-1);
107 ft = (iw>>16) & ((1<<5)-1);
108 fs = (iw>>11) & ((1<<5)-1);
109 fd = (iw>>6) & ((1<<5)-1);
110 unpack(&up->fpsave, fmt, fs, &ss, &es);
111 unpack(&up->fpsave, fmt, ft, &st, &et);
127 up->fpsave.reg[fd] &= ~0x80000000;
131 up->fpsave.reg[fd] ^= 0x80000000;
137 if(es<-(maxe-maxm) && et<-(maxe-maxm))
157 fmt = 0; /* convert FROM double TO single */
163 default: /* probably a compare */
166 if(ed <= -(maxe-5)){ /* guess: underflow */
167 zeroreg(&up->fpsave, fmt, fd, sd);
168 /* Set underflow exception and sticky */
169 up->fpsave.fpstatus |= (1<<3)|(1<<13);
176 branch(Ureg *ur, ulong fcr31)
178 ulong iw, npc, rs, rt, rd, offset;
180 iw = *(ulong*)ur->pc;
181 rs = (iw>>21) & 0x1F;
184 rt = (iw>>16) & 0x1F;
187 offset = iw & ((1<<16)-1);
188 if(offset & (1<<15)) /* sign extend */
189 offset |= ~((1<<16)-1);
192 * Integer unit jumps first
195 case 0: /* SPECIAL: JR or JALR */
197 case 0x09: /* JALR */
198 rd = (iw>>11) & 0x1F;
200 *reg(ur, rd) = ur->pc+8;
208 switch((iw>>16) & 0x1F){
209 case 0x10: /* BLTZAL */
210 ur->r31 = ur->pc + 8;
212 case 0x00: /* BLTZ */
214 return ur->pc+4 + offset;
216 case 0x11: /* BGEZAL */
217 ur->r31 = ur->pc + 8;
219 case 0x01: /* BGEZ */
221 return ur->pc+4 + offset;
230 npc = iw & ((1<<26)-1);
232 return npc | (ur->pc&0xF0000000);
235 return ur->pc+4 + offset;
239 return ur->pc+4 + offset;
243 return ur->pc+4 + offset;
247 return ur->pc+4 + offset;
251 * Floating point unit jumps
253 if((iw>>26) == 0x11) /* COP1 */
254 switch((iw>>16) & 0x3C1){
255 case 0x101: /* BCT */
256 case 0x181: /* BCT */
258 return ur->pc+4 + offset;
260 case 0x100: /* BCF */
261 case 0x180: /* BCF */
262 if(!(fcr31 & (1<<23)))
263 return ur->pc+4 + offset;
266 /* shouldn't get here */