1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 #include "arm.h" 6 7 static int dummy; 8 static char* shtype[4] = 9 { 10 "<<", 11 ">>", 12 "->", 13 "@>", 14 }; 15 static char* cond[16] = 16 { 17 ".EQ", ".NE", ".HS", ".LO", 18 ".MI", ".PL", ".VS", ".VC", 19 ".HI", ".LS", ".GE", ".LT", 20 ".GT", ".LE", "", ".NO", 21 }; 22 23 void Idp0(ulong); 24 void Idp1(ulong); 25 void Idp2(ulong); 26 void Idp3(ulong); 27 28 void Imul(ulong); 29 void Imula(ulong); 30 void Imull(ulong); 31 32 void Iswap(ulong); 33 void Imem1(ulong); 34 void Imem2(ulong); 35 void Ilsm(ulong inst); 36 37 void Ib(ulong); 38 void Ibl(ulong); 39 40 void Ssyscall(ulong); 41 42 Inst itab[] = 43 { 44 { Idp0, "AND", Iarith }, /* 00 - r,r,r */ 45 { Idp0, "EOR", Iarith }, /* 01 */ 46 { Idp0, "SUB", Iarith }, /* 02 */ 47 { Idp0, "RSB", Iarith }, /* 03 */ 48 { Idp0, "ADD", Iarith }, /* 04 */ 49 { Idp0, "ADC", Iarith }, /* 05 */ 50 { Idp0, "SBC", Iarith }, /* 06 */ 51 { Idp0, "RSC", Iarith }, /* 07 */ 52 { Idp0, "TST", Iarith }, /* 08 */ 53 { Idp0, "TEQ", Iarith }, /* 09 */ 54 55 { Idp0, "CMP", Iarith }, /* 10 */ 56 { Idp0, "CMN", Iarith }, /* 11 */ 57 { Idp0, "ORR", Iarith }, /* 12 */ 58 { Idp0, "MOV", Iarith }, /* 13 */ 59 { Idp0, "BIC", Iarith }, /* 14 */ 60 { Idp0, "MVN", Iarith }, /* 15 */ 61 { Idp1, "AND", Iarith }, /* 16 */ 62 { Idp1, "EOR", Iarith }, /* 17 */ 63 { Idp1, "SUB", Iarith }, /* 18 */ 64 { Idp1, "RSB", Iarith }, /* 19 */ 65 66 { Idp1, "ADD", Iarith }, /* 20 */ 67 { Idp1, "ADC", Iarith }, /* 21 */ 68 { Idp1, "SBC", Iarith }, /* 22 */ 69 { Idp1, "RSC", Iarith }, /* 23 */ 70 { Idp1, "TST", Iarith }, /* 24 */ 71 { Idp1, "TEQ", Iarith }, /* 25 */ 72 { Idp1, "CMP", Iarith }, /* 26 */ 73 { Idp1, "CMN", Iarith }, /* 27 */ 74 { Idp1, "ORR", Iarith }, /* 28 */ 75 { Idp1, "MOV", Iarith }, /* 29 */ 76 77 { Idp1, "BIC", Iarith }, /* 30 */ 78 { Idp1, "MVN", Iarith }, /* 31 */ 79 { Idp2, "AND", Iarith }, /* 32 */ 80 { Idp2, "EOR", Iarith }, /* 33 */ 81 { Idp2, "SUB", Iarith }, /* 34 */ 82 { Idp2, "RSB", Iarith }, /* 35 */ 83 { Idp2, "ADD", Iarith }, /* 36 */ 84 { Idp2, "ADC", Iarith }, /* 37 */ 85 { Idp2, "SBC", Iarith }, /* 38 */ 86 { Idp2, "RSC", Iarith }, /* 39 */ 87 88 { Idp2, "TST", Iarith }, /* 40 */ 89 { Idp2, "TEQ", Iarith }, /* 41 */ 90 { Idp2, "CMP", Iarith }, /* 42 */ 91 { Idp2, "CMN", Iarith }, /* 43 */ 92 { Idp2, "ORR", Iarith }, /* 44 */ 93 { Idp2, "MOV", Iarith }, /* 45 */ 94 { Idp2, "BIC", Iarith }, /* 46 */ 95 { Idp2, "MVN", Iarith }, /* 47 */ 96 { Idp3, "AND", Iarith }, /* 48 - i,r,r */ 97 { Idp3, "EOR", Iarith }, /* 49 */ 98 99 { Idp3, "SUB", Iarith }, /* 50 */ 100 { Idp3, "RSB", Iarith }, /* 51 */ 101 { Idp3, "ADD", Iarith }, /* 52 */ 102 { Idp3, "ADC", Iarith }, /* 53 */ 103 { Idp3, "SBC", Iarith }, /* 54 */ 104 { Idp3, "RSC", Iarith }, /* 55 */ 105 { Idp3, "TST", Iarith }, /* 56 */ 106 { Idp3, "TEQ", Iarith }, /* 57 */ 107 { Idp3, "CMP", Iarith }, /* 58 */ 108 { Idp3, "CMN", Iarith }, /* 59 */ 109 110 { Idp3, "ORR", Iarith }, /* 60 */ 111 { Idp3, "MOV", Iarith }, /* 61 */ 112 { Idp3, "BIC", Iarith }, /* 62 */ 113 { Idp3, "MVN", Iarith }, /* 63 */ 114 { Imul, "MUL", Iarith }, /* 64 */ 115 { Imula, "MULA", Iarith }, /* 65 */ 116 117 { Iswap, "SWPW", Imem }, /* 66 */ 118 { Iswap, "SWPBU", Imem }, /* 67 */ 119 120 { Imem2, "MOV", Imem }, /* 68 load/store h/sb */ 121 { Imem2, "MOV", Imem }, /* 69 */ 122 { Imem2, "MOV", Imem }, /* 70 */ 123 { Imem2, "MOV", Imem }, /* 71 */ 124 125 { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */ 126 { Imem1, "MOVB", Imem }, /* 73 */ 127 { Imem1, "MOVW", Imem }, /* 74 */ 128 { Imem1, "MOVB", Imem }, /* 75 */ 129 { Imem1, "MOVW", Imem }, /* 76 load/store r,r */ 130 { Imem1, "MOVB", Imem }, /* 77 */ 131 { Imem1, "MOVW", Imem }, /* 78 */ 132 { Imem1, "MOVB", Imem }, /* 79 */ 133 134 { Ilsm, "LDM", Imem }, /* 80 block move r,r */ 135 { Ilsm, "STM", Imem }, /* 81 */ 136 { Ib, "B", Ibranch }, /* 82 branch */ 137 { Ibl, "BL", Ibranch }, /* 83 */ 138 { Ssyscall, "SWI", Isyscall }, /* 84 co processor */ 139 { undef, "undef" }, /* 85 */ 140 { undef, "undef" }, /* 86 */ 141 { undef, "undef" }, /* 87 */ 142 { Imull, "MULLU", Iarith }, /* 88 */ 143 { Imull, "MULALU", Iarith }, /* 89 */ 144 { Imull, "MULL", Iarith }, /* 90 */ 145 { Imull, "MULAL", Iarith }, /* 91 */ 146 { undef, "undef" }, /* 92 */ 147 148 { 0 } 149 }; 150 151 int 152 runcmp(void) 153 { 154 switch(reg.cond) { 155 case 0x0: /* eq */ return (reg.cc1 == reg.cc2); 156 case 0x1: /* ne */ return (reg.cc1 != reg.cc2); 157 case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2); 158 case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2); 159 case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0); 160 case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0); 161 case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2); 162 case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2); 163 case 0xa: /* ge */ return (reg.cc1 >= reg.cc2); 164 case 0xb: /* lt */ return (reg.cc1 < reg.cc2); 165 case 0xc: /* gt */ return (reg.cc1 > reg.cc2); 166 case 0xd: /* le */ return (reg.cc1 <= reg.cc2); 167 case 0xe: /* al */ return 1; 168 case 0xf: /* nv */ return 0; 169 default: 170 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", 171 reg.cond, reg.cc1, reg.cc2); 172 undef(reg.ir); 173 return 0; 174 } 175 } 176 177 int 178 runteq(void) 179 { 180 long res = reg.cc1 ^ reg.cc2; 181 switch(reg.cond) { 182 case 0x0: /* eq */ return res == 0; 183 case 0x1: /* ne */ return res != 0; 184 case 0x4: /* mi */ return (res & SIGNBIT) != 0; 185 case 0x5: /* pl */ return (res & SIGNBIT) == 0; 186 case 0xe: /* al */ return 1; 187 case 0xf: /* nv */ return 0; 188 default: 189 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", 190 reg.cond, reg.cc1, reg.cc2); 191 undef(reg.ir); 192 return 0; 193 } 194 } 195 196 int 197 runtst(void) 198 { 199 long res = reg.cc1 & reg.cc2; 200 switch(reg.cond) { 201 case 0x0: /* eq */ return res == 0; 202 case 0x1: /* ne */ return res != 0; 203 case 0x4: /* mi */ return (res & SIGNBIT) != 0; 204 case 0x5: /* pl */ return (res & SIGNBIT) == 0; 205 case 0xe: /* al */ return 1; 206 case 0xf: /* nv */ return 0; 207 default: 208 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", 209 reg.cond, reg.cc1, reg.cc2); 210 undef(reg.ir); 211 return 0; 212 } 213 } 214 215 void 216 run(void) 217 { 218 int execute; 219 220 do { 221 if(trace) 222 Bflush(bioout); 223 reg.ar = reg.r[REGPC]; 224 reg.ir = ifetch(reg.ar); 225 reg.class = armclass(reg.ir); 226 reg.ip = &itab[reg.class]; 227 reg.cond = (reg.ir>>28) & 0xf; 228 switch(reg.compare_op) { 229 case CCcmp: 230 execute = runcmp(); 231 break; 232 case CCteq: 233 execute = runteq(); 234 break; 235 case CCtst: 236 execute = runtst(); 237 break; 238 default: 239 Bprint(bioout, "unimplemented compare operation %x\n", 240 reg.compare_op); 241 return; 242 } 243 244 if(execute) { 245 reg.ip->count++; 246 (*reg.ip->func)(reg.ir); 247 } else { 248 if(trace) 249 itrace("%s%s IGNORED", 250 reg.ip->name, cond[reg.cond]); 251 } 252 reg.r[REGPC] += 4; 253 if(bplist) 254 brkchk(reg.r[REGPC], Instruction); 255 } while(--count); 256 } 257 258 void 259 undef(ulong inst) 260 { 261 Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n", 262 reg.r[REGPC], inst, reg.class); 263 longjmp(errjmp, 0); 264 } 265 266 long 267 shift(long v, int st, int sc, int isreg) 268 { 269 if(sc == 0) { 270 switch(st) { 271 case 0: /* logical left */ 272 reg.cout = reg.cbit; 273 break; 274 case 1: /* logical right */ 275 reg.cout = (v >> 31) & 1; 276 break; 277 case 2: /* arith right */ 278 reg.cout = reg.cbit; 279 break; 280 case 3: /* rotate right */ 281 if(isreg) { 282 reg.cout = reg.cbit; 283 } 284 else { 285 reg.cout = v & 1; 286 v = ((ulong)v >> 1) | (reg.cbit << 31); 287 } 288 } 289 } 290 else { 291 switch(st) { 292 case 0: /* logical left */ 293 reg.cout = (v >> (32 - sc)) & 1; 294 v = v << sc; 295 break; 296 case 1: /* logical right */ 297 reg.cout = (v >> (sc - 1)) & 1; 298 v = (ulong)v >> sc; 299 break; 300 case 2: /* arith right */ 301 if(sc >= 32) { 302 reg.cout = (v >> 31) & 1; 303 if(reg.cout) 304 v = 0xFFFFFFFF; 305 else 306 v = 0; 307 } 308 else { 309 reg.cout = (v >> (sc - 1)) & 1; 310 v = (long)v >> sc; 311 } 312 break; 313 case 3: /* rotate right */ 314 reg.cout = (v >> (sc - 1)) & 1; 315 v = (v << (32-sc)) | ((ulong)v >> sc); 316 break; 317 } 318 } 319 return v; 320 } 321 322 void 323 dpex(long inst, long o1, long o2, int rd) 324 { 325 int cbit; 326 327 cbit = 0; 328 switch((inst>>21) & 0xf) { 329 case 0: /* and */ 330 reg.r[rd] = o1 & o2; 331 cbit = 1; 332 break; 333 case 1: /* eor */ 334 reg.r[rd] = o1 ^ o2; 335 cbit = 1; 336 break; 337 case 2: /* sub */ 338 reg.r[rd] = o1 - o2; 339 case 10: /* cmp */ 340 if(inst & Sbit) { 341 reg.cc1 = o1; 342 reg.cc2 = o2; 343 reg.compare_op = CCcmp; 344 } 345 return; 346 case 3: /* rsb */ 347 reg.r[rd] = o2 - o1; 348 if(inst & Sbit) { 349 reg.cc1 = o2; 350 reg.cc2 = o1; 351 reg.compare_op = CCcmp; 352 } 353 return; 354 case 4: /* add */ 355 if(calltree && rd == REGPC && o2 == 0) { 356 Symbol s; 357 358 findsym(o1 + o2, CTEXT, &s); 359 Bprint(bioout, "%8lux return to %lux %s r0=%lux\n", 360 reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]); 361 } 362 reg.r[rd] = o1 + o2; 363 if(inst & Sbit) { 364 if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32)) 365 reg.cbit = 1; 366 else 367 reg.cbit = 0; 368 reg.cc1 = o2; 369 reg.cc2 = -o1; 370 reg.compare_op = CCcmp; 371 } 372 return; 373 case 5: /* adc */ 374 case 6: /* sbc */ 375 case 7: /* rsc */ 376 undef(inst); 377 case 8: /* tst */ 378 if(inst & Sbit) { 379 reg.cc1 = o1; 380 reg.cc2 = o2; 381 reg.compare_op = CCtst; 382 } 383 return; 384 case 9: /* teq */ 385 if(inst & Sbit) { 386 reg.cc1 = o1; 387 reg.cc2 = o2; 388 reg.compare_op = CCteq; 389 } 390 return; 391 case 11: /* cmn */ 392 if(inst & Sbit) { 393 reg.cc1 = o1; 394 reg.cc2 = -o2; 395 reg.compare_op = CCcmp; 396 } 397 return; 398 case 12: /* orr */ 399 reg.r[rd] = o1 | o2; 400 cbit = 1; 401 break; 402 case 13: /* mov */ 403 reg.r[rd] = o2; 404 cbit = 1; 405 break; 406 case 14: /* bic */ 407 reg.r[rd] = o1 & ~o2; 408 cbit = 1; 409 break; 410 case 15: /* mvn */ 411 reg.r[rd] = ~o2; 412 cbit = 1; 413 break; 414 } 415 if(inst & Sbit) { 416 if(cbit) 417 reg.cbit = reg.cout; 418 reg.cc1 = reg.r[rd]; 419 reg.cc2 = 0; 420 reg.compare_op = CCcmp; 421 } 422 } 423 424 /* 425 * data processing instruction R,R,R 426 */ 427 void 428 Idp0(ulong inst) 429 { 430 int rn, rd, rm; 431 long o1, o2; 432 433 rn = (inst>>16) & 0xf; 434 rd = (inst>>12) & 0xf; 435 rm = inst & 0xf; 436 o1 = reg.r[rn]; 437 if(rn == REGPC) 438 o1 += 8; 439 o2 = reg.r[rm]; 440 if(rm == REGPC) 441 o2 += 8; 442 443 dpex(inst, o1, o2, rd); 444 if(trace) 445 itrace("%s%s\tR%d,R%d,R%d =#%x", 446 reg.ip->name, cond[reg.cond], 447 rm, rn, rd, 448 reg.r[rd]); 449 if(rd == REGPC) 450 reg.r[rd] -= 4; 451 } 452 453 /* 454 * data processing instruction (R<>#),R,R 455 */ 456 void 457 Idp1(ulong inst) 458 { 459 int rn, rd, rm, st, sc; 460 long o1, o2; 461 462 rn = (inst>>16) & 0xf; 463 rd = (inst>>12) & 0xf; 464 rm = inst & 0xf; 465 st = (inst>>5) & 0x3; 466 sc = (inst>>7) & 0x1f; 467 o1 = reg.r[rn]; 468 if(rn == REGPC) 469 o1 += 8; 470 o2 = reg.r[rm]; 471 if(rm == REGPC) 472 o2 += 8; 473 o2 = shift(o2, st, sc, 0); 474 dpex(inst, o1, o2, rd); 475 if(trace) 476 itrace("%s%s\tR%d%s%d,R%d,R%d =#%x", 477 reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd, 478 reg.r[rd]); 479 if(rd == REGPC) 480 reg.r[rd] -= 4; 481 } 482 483 /* 484 * data processing instruction (R<>R),R,R 485 */ 486 void 487 Idp2(ulong inst) 488 { 489 int rn, rd, rm, rs, st; 490 long o1, o2, o3; 491 492 rn = (inst>>16) & 0xf; 493 rd = (inst>>12) & 0xf; 494 rm = inst & 0xf; 495 st = (inst>>5) & 0x3; 496 rs = (inst>>8) & 0xf; 497 o1 = reg.r[rn]; 498 if(rn == REGPC) 499 o1 += 8; 500 o2 = reg.r[rm]; 501 if(rm == REGPC) 502 o2 += 8; 503 o3 = reg.r[rs]; 504 if(rs == REGPC) 505 o3 += 8; 506 o2 = shift(o2, st, o3, 1); 507 dpex(inst, o1, o2, rd); 508 if(trace) 509 itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x", 510 reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd, 511 reg.r[rd]); 512 if(rd == REGPC) 513 reg.r[rd] -= 4; 514 } 515 516 /* 517 * data processing instruction #<>#,R,R 518 */ 519 void 520 Idp3(ulong inst) 521 { 522 int rn, rd, sc; 523 long o1, o2; 524 525 rn = (inst>>16) & 0xf; 526 rd = (inst>>12) & 0xf; 527 o1 = reg.r[rn]; 528 if(rn == REGPC) 529 o1 += 8; 530 o2 = inst & 0xff; 531 sc = (inst>>7) & 0x1e; 532 o2 = (o2 >> sc) | (o2 << (32 - sc)); 533 534 dpex(inst, o1, o2, rd); 535 if(trace) 536 itrace("%s%s\t#%x,R%d,R%d =#%x", 537 reg.ip->name, cond[reg.cond], o2, rn, rd, 538 reg.r[rd]); 539 if(rd == REGPC) 540 reg.r[rd] -= 4; 541 } 542 543 void 544 Imul(ulong inst) 545 { 546 int rs, rd, rm; 547 548 rd = (inst>>16) & 0xf; 549 rs = (inst>>8) & 0xf; 550 rm = inst & 0xf; 551 552 if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm) 553 undef(inst); 554 555 reg.r[rd] = reg.r[rm]*reg.r[rs]; 556 557 if(trace) 558 itrace("%s%s\tR%d,R%d,R%d =#%x", 559 reg.ip->name, cond[reg.cond], rs, rm, rd, 560 reg.r[rd]); 561 } 562 563 void 564 Imull(ulong inst) 565 { 566 vlong v; 567 int rs, rd, rm, rn; 568 569 rd = (inst>>16) & 0xf; 570 rn = (inst>>12) & 0xf; 571 rs = (inst>>8) & 0xf; 572 rm = inst & 0xf; 573 574 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC 575 || rd == rm || rn == rm || rd == rn) 576 undef(inst); 577 578 if(inst & (1<<22)){ 579 v = (vlong)reg.r[rm] * (vlong)reg.r[rs]; 580 if(inst & (1 << 21)) 581 v += reg.r[rn]; 582 }else{ 583 v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs]; 584 if(inst & (1 << 21)) 585 v += (ulong)reg.r[rn]; 586 } 587 reg.r[rd] = v >> 32; 588 reg.r[rn] = v; 589 590 if(trace) 591 itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx", 592 reg.ip->name, cond[reg.cond], rs, rm, rn, rd, 593 v); 594 } 595 596 void 597 Imula(ulong inst) 598 { 599 int rs, rd, rm, rn; 600 601 rd = (inst>>16) & 0xf; 602 rn = (inst>>12) & 0xf; 603 rs = (inst>>8) & 0xf; 604 rm = inst & 0xf; 605 606 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm) 607 undef(inst); 608 609 reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn]; 610 611 if(trace) 612 itrace("%s%s\tR%d,R%d,R%d,R%d =#%x", 613 reg.ip->name, cond[reg.cond], rs, rm, rn, rd, 614 reg.r[rd]); 615 } 616 617 void 618 Iswap(ulong inst) 619 { 620 int rn, rd, rm; 621 ulong address, value, bbit; 622 623 bbit = inst & (1<<22); 624 rn = (inst>>16) & 0xf; 625 rd = (inst>>12) & 0xf; 626 rm = (inst>>0) & 0xf; 627 628 address = reg.r[rn]; 629 if(bbit) { 630 value = getmem_b(address); 631 putmem_b(address, reg.r[rm]); 632 } else { 633 value = getmem_w(address); 634 putmem_w(address, reg.r[rm]); 635 } 636 reg.r[rd] = value; 637 638 if(trace) { 639 char *bw, *dotc; 640 641 bw = ""; 642 if(bbit) 643 bw = "B"; 644 dotc = cond[reg.cond]; 645 646 itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x", 647 bw, dotc, 648 rn, rd, 649 address, value); 650 } 651 } 652 653 /* 654 * load/store word/byte 655 */ 656 void 657 Imem1(ulong inst) 658 { 659 int rn, rd, off, rm, sc, st; 660 ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25; 661 662 bit25 = inst & (1<<25); 663 pbit = inst & (1<<24); 664 ubit = inst & (1<<23); 665 bbit = inst & (1<<22); 666 wbit = inst & (1<<21); 667 lbit = inst & (1<<20); 668 rn = (inst>>16) & 0xf; 669 rd = (inst>>12) & 0xf; 670 671 SET(st); 672 SET(sc); 673 SET(rm); 674 if(bit25) { 675 rm = inst & 0xf; 676 st = (inst>>5) & 0x3; 677 sc = (inst>>7) & 0x1f; 678 off = reg.r[rm]; 679 if(rm == REGPC) 680 off += 8; 681 off = shift(off, st, sc, 0); 682 } else { 683 off = inst & 0xfff; 684 } 685 if(!ubit) 686 off = -off; 687 if(rn == REGPC) 688 off += 8; 689 690 address = reg.r[rn]; 691 if(pbit) 692 address += off; 693 694 if(lbit) { 695 if(bbit) 696 value = getmem_b(address); 697 else 698 value = getmem_w(address); 699 if(rd == REGPC) 700 value -= 4; 701 reg.r[rd] = value; 702 } else { 703 value = reg.r[rd]; 704 if(rd == REGPC) 705 value -= 4; 706 if(bbit) 707 putmem_b(address, value); 708 else 709 putmem_w(address, value); 710 } 711 if(!(pbit && !wbit)) 712 reg.r[rn] += off; 713 714 if(trace) { 715 char *bw, *dotp, *dotc; 716 717 bw = "W"; 718 if(bbit) 719 bw = "BU"; 720 dotp = ""; 721 if(!pbit) 722 dotp = ".P"; 723 dotc = cond[reg.cond]; 724 725 if(lbit) { 726 if(!bit25) 727 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x", 728 bw, dotp, dotc, 729 off, rn, rd, 730 address, value); 731 else 732 itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x", 733 bw, dotp, dotc, 734 rm, shtype[st], sc, rn, rd, 735 address, value); 736 } else { 737 if(!bit25) 738 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x", 739 bw, dotp, dotc, 740 rd, off, rn, 741 address, value); 742 else 743 itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x", 744 bw, dotp, dotc, 745 rd, rm, shtype[st], sc, rn, 746 address, value); 747 } 748 } 749 } 750 751 /* 752 * load/store unsigned byte/half word 753 */ 754 void 755 Imem2(ulong inst) 756 { 757 int rn, rd, off, rm; 758 ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22; 759 760 pbit = inst & (1<<24); 761 ubit = inst & (1<<23); 762 bit22 = inst & (1<<22); 763 wbit = inst & (1<<21); 764 lbit = inst & (1<<20); 765 sbit = inst & (1<<6); 766 hbit = inst & (1<<5); 767 rn = (inst>>16) & 0xf; 768 rd = (inst>>12) & 0xf; 769 770 SET(rm); 771 if(bit22) { 772 off = ((inst>>4) & 0xf0) | (inst & 0xf); 773 } else { 774 rm = inst & 0xf; 775 off = reg.r[rm]; 776 if(rm == REGPC) 777 off += 8; 778 } 779 if(!ubit) 780 off = -off; 781 if(rn == REGPC) 782 off += 8; 783 784 address = reg.r[rn]; 785 if(pbit) 786 address += off; 787 788 if(lbit) { 789 if(hbit) { 790 value = getmem_h(address); 791 if(sbit && (value & 0x8000)) 792 value |= 0xffff0000; 793 } else { 794 value = getmem_b(address); 795 if(value & 0x80) 796 value |= 0xffffff00; 797 } 798 if(rd == REGPC) 799 value -= 4; 800 reg.r[rd] = value; 801 } else { 802 value = reg.r[rd]; 803 if(rd == REGPC) 804 value -= 4; 805 if(hbit) { 806 putmem_h(address, value); 807 } else { 808 putmem_b(address, value); 809 } 810 } 811 if(!(pbit && !wbit)) 812 reg.r[rn] += off; 813 814 if(trace) { 815 char *hb, *dotp, *dotc; 816 817 hb = "B"; 818 if(hbit) 819 hb = "H"; 820 dotp = ""; 821 if(!pbit) 822 dotp = ".P"; 823 dotc = cond[reg.cond]; 824 825 if(lbit) { 826 if(bit22) 827 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x", 828 hb, dotp, dotc, 829 off, rn, rd, 830 address, value); 831 else 832 itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x", 833 hb, dotp, dotc, 834 rm, rn, rd, 835 address, value); 836 } else { 837 if(bit22) 838 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x", 839 hb, dotp, dotc, 840 rd, off, rn, 841 address, value); 842 else 843 itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x", 844 hb, dotp, dotc, 845 rd, rm, rn, 846 address, value); 847 } 848 } 849 } 850 851 void 852 Ilsm(ulong inst) 853 { 854 char pbit, ubit, sbit, wbit, lbit; 855 int i, rn, reglist; 856 ulong address, predelta, postdelta; 857 858 pbit = (inst>>24) & 0x1; 859 ubit = (inst>>23) & 0x1; 860 sbit = (inst>>22) & 0x1; 861 wbit = (inst>>21) & 0x1; 862 lbit = (inst>>20) & 0x1; 863 rn = (inst>>16) & 0xf; 864 reglist = inst & 0xffff; 865 866 if(reglist & 0x8000) 867 undef(reg.ir); 868 if(sbit) 869 undef(reg.ir); 870 871 address = reg.r[rn]; 872 873 if(pbit) { 874 predelta = 4; 875 postdelta = 0; 876 } else { 877 predelta = 0; 878 postdelta = 4; 879 } 880 if(ubit) { 881 for (i = 0; i < 16; ++i) { 882 if(!(reglist & (1 << i))) 883 continue; 884 address += predelta; 885 if(lbit) 886 reg.r[i] = getmem_w(address); 887 else 888 putmem_w(address, reg.r[i]); 889 address += postdelta; 890 } 891 } else { 892 for (i = 15; 0 <= i; --i) { 893 if(!(reglist & (1 << i))) 894 continue; 895 address -= predelta; 896 if(lbit) 897 reg.r[i] = getmem_w(address); 898 else 899 putmem_w(address, reg.r[i]); 900 address -= postdelta; 901 } 902 } 903 if(wbit) { 904 reg.r[rn] = address; 905 } 906 907 if(trace) { 908 itrace("%s.%c%c\tR%d=%lux%s, <%lux>", 909 (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'), 910 rn, reg.r[rn], (wbit ? "!" : ""), reglist); 911 } 912 } 913 914 void 915 Ib(ulong inst) 916 { 917 long v; 918 919 v = inst & 0xffffff; 920 v = reg.r[REGPC] + 8 + ((v << 8) >> 6); 921 if(trace) 922 itrace("B%s\t#%lux", cond[reg.cond], v); 923 reg.r[REGPC] = v - 4; 924 } 925 926 void 927 Ibl(ulong inst) 928 { 929 long v; 930 Symbol s; 931 932 v = inst & 0xffffff; 933 v = reg.r[REGPC] + 8 + ((v << 8) >> 6); 934 if(trace) 935 itrace("BL%s\t#%lux", cond[reg.cond], v); 936 937 if(calltree) { 938 findsym(v, CTEXT, &s); 939 Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name); 940 printparams(&s, reg.r[13]); 941 Bprint(bioout, "from "); 942 printsource(reg.r[REGPC]); 943 Bputc(bioout, '\n'); 944 } 945 946 reg.r[REGLINK] = reg.r[REGPC] + 4; 947 reg.r[REGPC] = v - 4; 948 } 949