25 suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4);
29 evenaddr(u32int addr, u32int mask)
31 if((addr & mask) == 0)
33 suicide("unaligned access %8ux @ %8ux", addr, P->R[15] - 4);
42 if((instr & (1<<4)) && (instr & (1<<7)))
46 amount = P->R[(instr >> 8) & 15];
48 amount = (instr >> 7) & 31;
49 val = P->R[instr & 15];
50 switch((instr >> 5) & 3) {
56 return ((long) val) >> amount;
58 return (val >> amount) | (val << (32 - amount));
75 offset = doshift(instr);
77 offset = instr & ((1<<12) - 1);
80 Rn = P->R + ((instr >> 16) & 15);
81 Rd = P->R + ((instr >> 12) & 15);
82 if((instr & (fW | fP)) == fW)
94 addr = evenaddr(addr, 3);
95 targ = vaddr(addr, 4, &seg);
96 switch(instr & (fB | fL)) {
98 *(u32int*) targ = *Rd;
101 *(u8int*) targ = *Rd;
104 *Rd = *(u32int*) targ;
107 *Rd = *(u8int*) targ;
110 if(Rd == P->R + 15 && !(instr & fL)) {
114 *(u32int*) targ += 8;
119 if((instr & fW) || !(instr & fP))
126 u32int *Rm, *Rn, *Rd, *targ, addr, tmp;
129 Rm = P->R + (instr & 15);
130 Rd = P->R + ((instr >> 12) & 15);
131 Rn = P->R + ((instr >> 16) & 15);
132 if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15)
135 if((instr & fB) == 0)
136 addr = evenaddr(addr, 3);
137 targ = (u32int *) vaddr(addr, 4, &seg);
140 tmp = *(u8int*) targ;
141 *(u8int*) targ = *Rm;
153 add(u32int a, u32int b, u8int type, u8int *carry, u8int *overflow)
159 res2 = (u64int)a - b + *carry - 1;
161 if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
162 if(res2 & 0x100000000LL) *carry = 0;
165 res2 = (u64int)a + b + *carry;
167 if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
168 if(res2 & 0x100000000LL) *carry = 1;
177 u32int Rn, *Rd, operand, shift, result, op;
178 u8int carry, overflow;
180 Rn = P->R[(instr >> 16) & 15];
181 Rd = P->R + ((instr >> 12) & 15);
182 if(((instr >> 16) & 15) == 15) {
184 if(!(instr & fI) && (instr & (1<<4)))
187 if(Rd == P->R + 15 && (instr & fS))
190 operand = instr & 0xFF;
191 shift = ((instr >> 8) & 15) << 1;
192 operand = (operand >> shift) | (operand << (32 - shift));
194 operand = doshift(instr);
195 op = (instr >> 21) & 15;
197 if(op >= 8 && op <= 11 && !(instr & fS))
198 sysfatal("no PSR transfers plz");
199 if(op >= 5 && op < 8) {
203 if(op != 4 && op != 5 && op != 11)
208 case 0: case 8: result = Rn & operand; break;
209 case 1: case 9: result = Rn ^ operand; break;
210 case 2: case 6: case 10: result = add(Rn, operand, 1, &carry, &overflow); break;
211 case 3: case 7: result = add(operand, Rn, 1, &carry, &overflow); break;
212 case 4: case 5: case 11: result = add(operand, Rn, 0, &carry, &overflow); break;
213 case 12: result = Rn | operand; break;
214 case 13: result = operand; break;
215 case 14: result = Rn & ~operand; break;
216 case 15: result = ~operand; break;
217 default: result = 0; /* never happens */
225 if(carry && op > 1 && op < 12)
230 if(op < 8 || op >= 12)
239 offset = instr & ((1<<24) - 1);
241 offset |= ~((1 << 24) - 1);
245 P->R[15] += offset + 4;
249 halfword(u32int instr)
251 u32int offset, target, *Rn, *Rd;
254 if(instr & (1<<22)) {
255 offset = (instr & 15) | ((instr >> 4) & 0xF0);
257 if((instr & 15) == 15)
259 offset = P->R[instr & 15];
263 if(!(instr & fP) && (instr & fW))
265 Rn = P->R + ((instr >> 16) & 15);
266 Rd = P->R + ((instr >> 12) & 15);
267 if(Rn == P->R + 15 || Rd == P->R + 15)
268 sysfatal("R15 in halfword");
273 target = evenaddr(target, 1);
274 switch(instr & (fSg | fH | fL)) {
275 case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break;
276 case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
277 case fH: case fSg | fH: *(u16int*) vaddr(target, 2, &seg) = *Rd; break;
278 case fH | fL: *Rd = *(u16int*) vaddr(target, 2, &seg); break;
279 case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
284 if(!(instr & fP) || (instr & fW))
297 Rn = P->R + ((instr >> 16) & 15);
298 if(Rn == P->R + 15 || instr & (1<<15))
299 sysfatal("R15 block");
300 targ = evenaddr(*Rn, 3);
302 for(i = 0; i < 16; i++) {
303 if(!(instr & (1<<i)))
308 P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
310 *(u32int*) vaddr(targ, 4, &seg) = P->R[i];
316 for(i = 15; i >= 0; i--) {
317 if(!(instr & (1<<i)))
322 P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
324 *(u32int*) vaddr(targ, 4, &seg) = P->R[i];
335 multiply(u32int instr)
337 u32int *Rd, *Rn, *Rs, *Rm, res;
339 Rm = P->R + (instr & 15);
340 Rs = P->R + ((instr >> 8) & 15);
341 Rn = P->R + ((instr >> 12) & 15);
342 Rd = P->R + ((instr >> 16) & 15);
343 if(Rd == Rm || Rm == P->R + 15 || Rs == P->R + 15 || Rn == P->R + 15 || Rd == P->R + 15)
349 if(instr & (1<<20)) {
350 P->CPSR &= ~(flN | flZ);
359 multiplylong(u32int instr)
361 u32int *RdH, *RdL, *Rs, *Rm;
364 Rm = P->R + (instr & 15);
365 Rs = P->R + ((instr >> 8) & 15);
366 RdL = P->R + ((instr >> 12) & 15);
367 RdH = P->R + ((instr >> 16) & 15);
368 if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == P->R + 15 || Rs == P->R + 15 || RdL == P->R + 15 || RdH == P->R + 15)
370 if(instr & (1<<22)) {
374 res = ((vlong)*(int*)Rs) * *(int*)Rm;
375 if(instr & (1<<21)) {
377 res += ((uvlong)*RdH) << 32;
381 if(instr & (1<<20)) {
391 singleex(u32int instr)
393 u32int *Rn, *Rd, *Rm, *targ, addr;
396 Rd = P->R + ((instr >> 12) & 15);
397 Rn = P->R + ((instr >> 16) & 15);
398 if(Rd == P->R + 15 || Rn == P->R + 15)
400 addr = evenaddr(*Rn, 3);
402 targ = vaddr(addr, 4, &seg);
407 Rm = P->R + (instr & 15);
410 targ = vaddr(addr, 4, &seg);
411 if(canlock(&seg->lock)) {
428 instr = *(u32int*) vaddr(P->R[15], 4, &seg);
431 print("%d ", P->pid);
436 if(findsym(P->R[15], CTEXT, &s) >= 0)
437 print("%s ", s.name);
438 if(fileline(buf, 512, P->R[15]) >= 0)
441 print("%.8ux %.8ux %c%c%c%c\n", P->R[15], instr,
442 (P->CPSR & flZ) ? 'Z' : ' ',
443 (P->CPSR & flC) ? 'C' : ' ',
444 (P->CPSR & flN) ? 'N' : ' ',
445 (P->CPSR & flV) ? 'V' : ' '
449 switch(instr >> 28) {
450 case 0x0: if(!(P->CPSR & flZ)) return; break;
451 case 0x1: if(P->CPSR & flZ) return; break;
452 case 0x2: if(!(P->CPSR & flC)) return; break;
453 case 0x3: if(P->CPSR & flC) return; break;
454 case 0x4: if(!(P->CPSR & flN)) return; break;
455 case 0x5: if(P->CPSR & flN) return; break;
456 case 0x6: if(!(P->CPSR & flV)) return; break;
457 case 0x7: if(P->CPSR & flV) return; break;
458 case 0x8: if(!(P->CPSR & flC) || (P->CPSR & flZ)) return; break;
459 case 0x9: if((P->CPSR & flC) && !(P->CPSR & flZ)) return; break;
460 case 0xA: if(!(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
461 case 0xB: if(!(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
462 case 0xC: if((P->CPSR & flZ) || !(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
463 case 0xD: if(!(P->CPSR & flZ) && !(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
465 default: sysfatal("condition code %x not implemented", instr >> 28);
467 if((instr & 0x0FB00FF0) == 0x01000090)
469 else if((instr & 0x0FE000F0) == 0x01800090)
471 else if((instr & 0x0FC000F0) == 0x90)
473 else if((instr & 0x0F8000F0) == 0x800090)
475 else if((instr & ((1<<26) | (1<<27))) == (1 << 26))
477 else if((instr & 0x0E000090) == 0x90 && (instr & 0x60))
479 else if((instr & ((1<<26) | (1<<27))) == 0)
481 else if((instr & (7<<25)) == (5 << 25))
483 else if((instr & (15<<24)) == (15 << 24))
485 else if((instr & (7<<25)) == (4 << 25))
487 else if((instr & 0x0E000F00) == 0x0C000100)
489 else if((instr & 0x0E000F10) == 0x0E000100)
491 else if((instr & 0x0E000F10) == 0x0E000110)
492 fparegtransfer(instr);
493 else if(vfp && ((instr & 0x0F000A10) == 0x0E000A00))
495 else if(vfp && ((instr & 0x0F000F10) == 0x0E000A10))
496 vfpregtransfer(instr);
497 else if(vfp && ((instr & 0x0F000A00) == 0x0D000A00))
498 vfprmtransfer(instr);