123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <mach.h>
- #include "arm.h"
- static int dummy;
- static char* shtype[4] =
- {
- "<<",
- ">>",
- "->",
- "@>",
- };
- static char* cond[16] =
- {
- ".EQ", ".NE", ".HS", ".LO",
- ".MI", ".PL", ".VS", ".VC",
- ".HI", ".LS", ".GE", ".LT",
- ".GT", ".LE", "", ".NO",
- };
- void Idp0(ulong);
- void Idp1(ulong);
- void Idp2(ulong);
- void Idp3(ulong);
- void Imul(ulong);
- void Imula(ulong);
- void Imull(ulong);
- void Iswap(ulong);
- void Imem1(ulong);
- void Imem2(ulong);
- void Ilsm(ulong inst);
- void Ib(ulong);
- void Ibl(ulong);
- void Ssyscall(ulong);
- Inst itab[] =
- {
- { Idp0, "AND", Iarith }, /* 00 - r,r,r */
- { Idp0, "EOR", Iarith }, /* 01 */
- { Idp0, "SUB", Iarith }, /* 02 */
- { Idp0, "RSB", Iarith }, /* 03 */
- { Idp0, "ADD", Iarith }, /* 04 */
- { Idp0, "ADC", Iarith }, /* 05 */
- { Idp0, "SBC", Iarith }, /* 06 */
- { Idp0, "RSC", Iarith }, /* 07 */
- { Idp0, "TST", Iarith }, /* 08 */
- { Idp0, "TEQ", Iarith }, /* 09 */
- { Idp0, "CMP", Iarith }, /* 10 */
- { Idp0, "CMN", Iarith }, /* 11 */
- { Idp0, "ORR", Iarith }, /* 12 */
- { Idp0, "MOV", Iarith }, /* 13 */
- { Idp0, "BIC", Iarith }, /* 14 */
- { Idp0, "MVN", Iarith }, /* 15 */
- { Idp1, "AND", Iarith }, /* 16 */
- { Idp1, "EOR", Iarith }, /* 17 */
- { Idp1, "SUB", Iarith }, /* 18 */
- { Idp1, "RSB", Iarith }, /* 19 */
- { Idp1, "ADD", Iarith }, /* 20 */
- { Idp1, "ADC", Iarith }, /* 21 */
- { Idp1, "SBC", Iarith }, /* 22 */
- { Idp1, "RSC", Iarith }, /* 23 */
- { Idp1, "TST", Iarith }, /* 24 */
- { Idp1, "TEQ", Iarith }, /* 25 */
- { Idp1, "CMP", Iarith }, /* 26 */
- { Idp1, "CMN", Iarith }, /* 27 */
- { Idp1, "ORR", Iarith }, /* 28 */
- { Idp1, "MOV", Iarith }, /* 29 */
- { Idp1, "BIC", Iarith }, /* 30 */
- { Idp1, "MVN", Iarith }, /* 31 */
- { Idp2, "AND", Iarith }, /* 32 */
- { Idp2, "EOR", Iarith }, /* 33 */
- { Idp2, "SUB", Iarith }, /* 34 */
- { Idp2, "RSB", Iarith }, /* 35 */
- { Idp2, "ADD", Iarith }, /* 36 */
- { Idp2, "ADC", Iarith }, /* 37 */
- { Idp2, "SBC", Iarith }, /* 38 */
- { Idp2, "RSC", Iarith }, /* 39 */
- { Idp2, "TST", Iarith }, /* 40 */
- { Idp2, "TEQ", Iarith }, /* 41 */
- { Idp2, "CMP", Iarith }, /* 42 */
- { Idp2, "CMN", Iarith }, /* 43 */
- { Idp2, "ORR", Iarith }, /* 44 */
- { Idp2, "MOV", Iarith }, /* 45 */
- { Idp2, "BIC", Iarith }, /* 46 */
- { Idp2, "MVN", Iarith }, /* 47 */
- { Idp3, "AND", Iarith }, /* 48 - i,r,r */
- { Idp3, "EOR", Iarith }, /* 49 */
- { Idp3, "SUB", Iarith }, /* 50 */
- { Idp3, "RSB", Iarith }, /* 51 */
- { Idp3, "ADD", Iarith }, /* 52 */
- { Idp3, "ADC", Iarith }, /* 53 */
- { Idp3, "SBC", Iarith }, /* 54 */
- { Idp3, "RSC", Iarith }, /* 55 */
- { Idp3, "TST", Iarith }, /* 56 */
- { Idp3, "TEQ", Iarith }, /* 57 */
- { Idp3, "CMP", Iarith }, /* 58 */
- { Idp3, "CMN", Iarith }, /* 59 */
- { Idp3, "ORR", Iarith }, /* 60 */
- { Idp3, "MOV", Iarith }, /* 61 */
- { Idp3, "BIC", Iarith }, /* 62 */
- { Idp3, "MVN", Iarith }, /* 63 */
- { Imul, "MUL", Iarith }, /* 64 */
- { Imula, "MULA", Iarith }, /* 65 */
- { Iswap, "SWPW", Imem }, /* 66 */
- { Iswap, "SWPBU", Imem }, /* 67 */
- { Imem2, "MOV", Imem }, /* 68 load/store h/sb */
- { Imem2, "MOV", Imem }, /* 69 */
- { Imem2, "MOV", Imem }, /* 70 */
- { Imem2, "MOV", Imem }, /* 71 */
- { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */
- { Imem1, "MOVB", Imem }, /* 73 */
- { Imem1, "MOVW", Imem }, /* 74 */
- { Imem1, "MOVB", Imem }, /* 75 */
- { Imem1, "MOVW", Imem }, /* 76 load/store r,r */
- { Imem1, "MOVB", Imem }, /* 77 */
- { Imem1, "MOVW", Imem }, /* 78 */
- { Imem1, "MOVB", Imem }, /* 79 */
- { Ilsm, "LDM", Imem }, /* 80 block move r,r */
- { Ilsm, "STM", Imem }, /* 81 */
- { Ib, "B", Ibranch }, /* 82 branch */
- { Ibl, "BL", Ibranch }, /* 83 */
- { Ssyscall, "SWI", Isyscall }, /* 84 co processor */
- { undef, "undef" }, /* 85 */
- { undef, "undef" }, /* 86 */
- { undef, "undef" }, /* 87 */
- { Imull, "MULLU", Iarith }, /* 88 */
- { Imull, "MULALU", Iarith }, /* 89 */
- { Imull, "MULL", Iarith }, /* 90 */
- { Imull, "MULAL", Iarith }, /* 91 */
- { undef, "undef" }, /* 92 */
- { 0 }
- };
- int
- runcmp(void)
- {
- switch(reg.cond) {
- case 0x0: /* eq */ return (reg.cc1 == reg.cc2);
- case 0x1: /* ne */ return (reg.cc1 != reg.cc2);
- case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2);
- case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2);
- case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0);
- case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0);
- case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2);
- case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2);
- case 0xa: /* ge */ return (reg.cc1 >= reg.cc2);
- case 0xb: /* lt */ return (reg.cc1 < reg.cc2);
- case 0xc: /* gt */ return (reg.cc1 > reg.cc2);
- case 0xd: /* le */ return (reg.cc1 <= reg.cc2);
- case 0xe: /* al */ return 1;
- case 0xf: /* nv */ return 0;
- default:
- Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
- reg.cond, reg.cc1, reg.cc2);
- undef(reg.ir);
- return 0;
- }
- }
- int
- runteq(void)
- {
- long res = reg.cc1 ^ reg.cc2;
- switch(reg.cond) {
- case 0x0: /* eq */ return res == 0;
- case 0x1: /* ne */ return res != 0;
- case 0x4: /* mi */ return (res & SIGNBIT) != 0;
- case 0x5: /* pl */ return (res & SIGNBIT) == 0;
- case 0xe: /* al */ return 1;
- case 0xf: /* nv */ return 0;
- default:
- Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
- reg.cond, reg.cc1, reg.cc2);
- undef(reg.ir);
- return 0;
- }
- }
- int
- runtst(void)
- {
- long res = reg.cc1 & reg.cc2;
- switch(reg.cond) {
- case 0x0: /* eq */ return res == 0;
- case 0x1: /* ne */ return res != 0;
- case 0x4: /* mi */ return (res & SIGNBIT) != 0;
- case 0x5: /* pl */ return (res & SIGNBIT) == 0;
- case 0xe: /* al */ return 1;
- case 0xf: /* nv */ return 0;
- default:
- Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
- reg.cond, reg.cc1, reg.cc2);
- undef(reg.ir);
- return 0;
- }
- }
- void
- run(void)
- {
- int execute;
- do {
- if(trace)
- Bflush(bioout);
- reg.ar = reg.r[REGPC];
- reg.ir = ifetch(reg.ar);
- reg.class = armclass(reg.ir);
- reg.ip = &itab[reg.class];
- reg.cond = (reg.ir>>28) & 0xf;
- switch(reg.compare_op) {
- case CCcmp:
- execute = runcmp();
- break;
- case CCteq:
- execute = runteq();
- break;
- case CCtst:
- execute = runtst();
- break;
- default:
- Bprint(bioout, "unimplemented compare operation %x\n",
- reg.compare_op);
- return;
- }
- if(execute) {
- reg.ip->count++;
- (*reg.ip->func)(reg.ir);
- } else {
- if(trace)
- itrace("%s%s IGNORED",
- reg.ip->name, cond[reg.cond]);
- }
- reg.r[REGPC] += 4;
- if(bplist)
- brkchk(reg.r[REGPC], Instruction);
- } while(--count);
- }
- void
- undef(ulong inst)
- {
- Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
- reg.r[REGPC], inst, reg.class);
- longjmp(errjmp, 0);
- }
- long
- shift(long v, int st, int sc, int isreg)
- {
- if(sc == 0) {
- switch(st) {
- case 0: /* logical left */
- reg.cout = reg.cbit;
- break;
- case 1: /* logical right */
- reg.cout = (v >> 31) & 1;
- break;
- case 2: /* arith right */
- reg.cout = reg.cbit;
- break;
- case 3: /* rotate right */
- if(isreg) {
- reg.cout = reg.cbit;
- }
- else {
- reg.cout = v & 1;
- v = ((ulong)v >> 1) | (reg.cbit << 31);
- }
- }
- }
- else {
- switch(st) {
- case 0: /* logical left */
- reg.cout = (v >> (32 - sc)) & 1;
- v = v << sc;
- break;
- case 1: /* logical right */
- reg.cout = (v >> (sc - 1)) & 1;
- v = (ulong)v >> sc;
- break;
- case 2: /* arith right */
- if(sc >= 32) {
- reg.cout = (v >> 31) & 1;
- if(reg.cout)
- v = 0xFFFFFFFF;
- else
- v = 0;
- }
- else {
- reg.cout = (v >> (sc - 1)) & 1;
- v = (long)v >> sc;
- }
- break;
- case 3: /* rotate right */
- reg.cout = (v >> (sc - 1)) & 1;
- v = (v << (32-sc)) | ((ulong)v >> sc);
- break;
- }
- }
- return v;
- }
- void
- dpex(long inst, long o1, long o2, int rd)
- {
- int cbit;
- cbit = 0;
- switch((inst>>21) & 0xf) {
- case 0: /* and */
- reg.r[rd] = o1 & o2;
- cbit = 1;
- break;
- case 1: /* eor */
- reg.r[rd] = o1 ^ o2;
- cbit = 1;
- break;
- case 2: /* sub */
- reg.r[rd] = o1 - o2;
- case 10: /* cmp */
- if(inst & Sbit) {
- reg.cc1 = o1;
- reg.cc2 = o2;
- reg.compare_op = CCcmp;
- }
- return;
- case 3: /* rsb */
- reg.r[rd] = o2 - o1;
- if(inst & Sbit) {
- reg.cc1 = o2;
- reg.cc2 = o1;
- reg.compare_op = CCcmp;
- }
- return;
- case 4: /* add */
- if(calltree && rd == REGPC && o2 == 0) {
- Symbol s;
- findsym(o1 + o2, CTEXT, &s);
- Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
- reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
- }
- reg.r[rd] = o1 + o2;
- if(inst & Sbit) {
- if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
- reg.cbit = 1;
- else
- reg.cbit = 0;
- reg.cc1 = o2;
- reg.cc2 = -o1;
- reg.compare_op = CCcmp;
- }
- return;
- case 5: /* adc */
- case 6: /* sbc */
- case 7: /* rsc */
- undef(inst);
- case 8: /* tst */
- if(inst & Sbit) {
- reg.cc1 = o1;
- reg.cc2 = o2;
- reg.compare_op = CCtst;
- }
- return;
- case 9: /* teq */
- if(inst & Sbit) {
- reg.cc1 = o1;
- reg.cc2 = o2;
- reg.compare_op = CCteq;
- }
- return;
- case 11: /* cmn */
- if(inst & Sbit) {
- reg.cc1 = o1;
- reg.cc2 = -o2;
- reg.compare_op = CCcmp;
- }
- return;
- case 12: /* orr */
- reg.r[rd] = o1 | o2;
- cbit = 1;
- break;
- case 13: /* mov */
- reg.r[rd] = o2;
- cbit = 1;
- break;
- case 14: /* bic */
- reg.r[rd] = o1 & ~o2;
- cbit = 1;
- break;
- case 15: /* mvn */
- reg.r[rd] = ~o2;
- cbit = 1;
- break;
- }
- if(inst & Sbit) {
- if(cbit)
- reg.cbit = reg.cout;
- reg.cc1 = reg.r[rd];
- reg.cc2 = 0;
- reg.compare_op = CCcmp;
- }
- }
- /*
- * data processing instruction R,R,R
- */
- void
- Idp0(ulong inst)
- {
- int rn, rd, rm;
- long o1, o2;
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- rm = inst & 0xf;
- o1 = reg.r[rn];
- if(rn == REGPC)
- o1 += 8;
- o2 = reg.r[rm];
- if(rm == REGPC)
- o2 += 8;
- dpex(inst, o1, o2, rd);
- if(trace)
- itrace("%s%s\tR%d,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond],
- rm, rn, rd,
- reg.r[rd]);
- if(rd == REGPC)
- reg.r[rd] -= 4;
- }
- /*
- * data processing instruction (R<>#),R,R
- */
- void
- Idp1(ulong inst)
- {
- int rn, rd, rm, st, sc;
- long o1, o2;
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- rm = inst & 0xf;
- st = (inst>>5) & 0x3;
- sc = (inst>>7) & 0x1f;
- o1 = reg.r[rn];
- if(rn == REGPC)
- o1 += 8;
- o2 = reg.r[rm];
- if(rm == REGPC)
- o2 += 8;
- o2 = shift(o2, st, sc, 0);
- dpex(inst, o1, o2, rd);
- if(trace)
- itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
- reg.r[rd]);
- if(rd == REGPC)
- reg.r[rd] -= 4;
- }
- /*
- * data processing instruction (R<>R),R,R
- */
- void
- Idp2(ulong inst)
- {
- int rn, rd, rm, rs, st;
- long o1, o2, o3;
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- rm = inst & 0xf;
- st = (inst>>5) & 0x3;
- rs = (inst>>8) & 0xf;
- o1 = reg.r[rn];
- if(rn == REGPC)
- o1 += 8;
- o2 = reg.r[rm];
- if(rm == REGPC)
- o2 += 8;
- o3 = reg.r[rs];
- if(rs == REGPC)
- o3 += 8;
- o2 = shift(o2, st, o3, 1);
- dpex(inst, o1, o2, rd);
- if(trace)
- itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
- reg.r[rd]);
- if(rd == REGPC)
- reg.r[rd] -= 4;
- }
- /*
- * data processing instruction #<>#,R,R
- */
- void
- Idp3(ulong inst)
- {
- int rn, rd, sc;
- long o1, o2;
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- o1 = reg.r[rn];
- if(rn == REGPC)
- o1 += 8;
- o2 = inst & 0xff;
- sc = (inst>>7) & 0x1e;
- o2 = (o2 >> sc) | (o2 << (32 - sc));
- dpex(inst, o1, o2, rd);
- if(trace)
- itrace("%s%s\t#%x,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond], o2, rn, rd,
- reg.r[rd]);
- if(rd == REGPC)
- reg.r[rd] -= 4;
- }
- void
- Imul(ulong inst)
- {
- int rs, rd, rm;
- rd = (inst>>16) & 0xf;
- rs = (inst>>8) & 0xf;
- rm = inst & 0xf;
- if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
- undef(inst);
- reg.r[rd] = reg.r[rm]*reg.r[rs];
- if(trace)
- itrace("%s%s\tR%d,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond], rs, rm, rd,
- reg.r[rd]);
- }
- void
- Imull(ulong inst)
- {
- vlong v;
- int rs, rd, rm, rn;
- rd = (inst>>16) & 0xf;
- rn = (inst>>12) & 0xf;
- rs = (inst>>8) & 0xf;
- rm = inst & 0xf;
- if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
- || rd == rm || rn == rm || rd == rn)
- undef(inst);
- if(inst & (1<<22)){
- v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
- if(inst & (1 << 21))
- v += reg.r[rn];
- }else{
- v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
- if(inst & (1 << 21))
- v += (ulong)reg.r[rn];
- }
- reg.r[rd] = v >> 32;
- reg.r[rn] = v;
- if(trace)
- itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
- reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
- v);
- }
- void
- Imula(ulong inst)
- {
- int rs, rd, rm, rn;
- rd = (inst>>16) & 0xf;
- rn = (inst>>12) & 0xf;
- rs = (inst>>8) & 0xf;
- rm = inst & 0xf;
- if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
- undef(inst);
- reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
- if(trace)
- itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
- reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
- reg.r[rd]);
- }
- void
- Iswap(ulong inst)
- {
- int rn, rd, rm;
- ulong address, value, bbit;
- bbit = inst & (1<<22);
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- rm = (inst>>0) & 0xf;
- address = reg.r[rn];
- if(bbit) {
- value = getmem_b(address);
- putmem_b(address, reg.r[rm]);
- } else {
- value = getmem_w(address);
- putmem_w(address, reg.r[rm]);
- }
- reg.r[rd] = value;
- if(trace) {
- char *bw, *dotc;
- bw = "";
- if(bbit)
- bw = "B";
- dotc = cond[reg.cond];
- itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
- bw, dotc,
- rn, rd,
- address, value);
- }
- }
- /*
- * load/store word/byte
- */
- void
- Imem1(ulong inst)
- {
- int rn, rd, off, rm, sc, st;
- ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
- bit25 = inst & (1<<25);
- pbit = inst & (1<<24);
- ubit = inst & (1<<23);
- bbit = inst & (1<<22);
- wbit = inst & (1<<21);
- lbit = inst & (1<<20);
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- SET(st);
- SET(sc);
- SET(rm);
- if(bit25) {
- rm = inst & 0xf;
- st = (inst>>5) & 0x3;
- sc = (inst>>7) & 0x1f;
- off = reg.r[rm];
- if(rm == REGPC)
- off += 8;
- off = shift(off, st, sc, 0);
- } else {
- off = inst & 0xfff;
- }
- if(!ubit)
- off = -off;
- if(rn == REGPC)
- off += 8;
- address = reg.r[rn];
- if(pbit)
- address += off;
- if(lbit) {
- if(bbit)
- value = getmem_b(address);
- else
- value = getmem_w(address);
- if(rd == REGPC)
- value -= 4;
- reg.r[rd] = value;
- } else {
- value = reg.r[rd];
- if(rd == REGPC)
- value -= 4;
- if(bbit)
- putmem_b(address, value);
- else
- putmem_w(address, value);
- }
- if(!(pbit && !wbit))
- reg.r[rn] += off;
- if(trace) {
- char *bw, *dotp, *dotc;
- bw = "W";
- if(bbit)
- bw = "BU";
- dotp = "";
- if(!pbit)
- dotp = ".P";
- dotc = cond[reg.cond];
- if(lbit) {
- if(!bit25)
- itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
- bw, dotp, dotc,
- off, rn, rd,
- address, value);
- else
- itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x",
- bw, dotp, dotc,
- rm, shtype[st], sc, rn, rd,
- address, value);
- } else {
- if(!bit25)
- itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
- bw, dotp, dotc,
- rd, off, rn,
- address, value);
- else
- itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
- bw, dotp, dotc,
- rd, rm, shtype[st], sc, rn,
- address, value);
- }
- }
- }
- /*
- * load/store unsigned byte/half word
- */
- void
- Imem2(ulong inst)
- {
- int rn, rd, off, rm;
- ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
- pbit = inst & (1<<24);
- ubit = inst & (1<<23);
- bit22 = inst & (1<<22);
- wbit = inst & (1<<21);
- lbit = inst & (1<<20);
- sbit = inst & (1<<6);
- hbit = inst & (1<<5);
- rn = (inst>>16) & 0xf;
- rd = (inst>>12) & 0xf;
- SET(rm);
- if(bit22) {
- off = ((inst>>4) & 0xf0) | (inst & 0xf);
- } else {
- rm = inst & 0xf;
- off = reg.r[rm];
- if(rm == REGPC)
- off += 8;
- }
- if(!ubit)
- off = -off;
- if(rn == REGPC)
- off += 8;
- address = reg.r[rn];
- if(pbit)
- address += off;
- if(lbit) {
- if(hbit) {
- value = getmem_h(address);
- if(sbit && (value & 0x8000))
- value |= 0xffff0000;
- } else {
- value = getmem_b(address);
- if(value & 0x80)
- value |= 0xffffff00;
- }
- if(rd == REGPC)
- value -= 4;
- reg.r[rd] = value;
- } else {
- value = reg.r[rd];
- if(rd == REGPC)
- value -= 4;
- if(hbit) {
- putmem_h(address, value);
- } else {
- putmem_b(address, value);
- }
- }
- if(!(pbit && !wbit))
- reg.r[rn] += off;
- if(trace) {
- char *hb, *dotp, *dotc;
- hb = "B";
- if(hbit)
- hb = "H";
- dotp = "";
- if(!pbit)
- dotp = ".P";
- dotc = cond[reg.cond];
- if(lbit) {
- if(bit22)
- itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
- hb, dotp, dotc,
- off, rn, rd,
- address, value);
- else
- itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x",
- hb, dotp, dotc,
- rm, rn, rd,
- address, value);
- } else {
- if(bit22)
- itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
- hb, dotp, dotc,
- rd, off, rn,
- address, value);
- else
- itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
- hb, dotp, dotc,
- rd, rm, rn,
- address, value);
- }
- }
- }
- void
- Ilsm(ulong inst)
- {
- char pbit, ubit, sbit, wbit, lbit;
- int i, rn, reglist;
- ulong address, predelta, postdelta;
- pbit = (inst>>24) & 0x1;
- ubit = (inst>>23) & 0x1;
- sbit = (inst>>22) & 0x1;
- wbit = (inst>>21) & 0x1;
- lbit = (inst>>20) & 0x1;
- rn = (inst>>16) & 0xf;
- reglist = inst & 0xffff;
- if(reglist & 0x8000)
- undef(reg.ir);
- if(sbit)
- undef(reg.ir);
- address = reg.r[rn];
- if(pbit) {
- predelta = 4;
- postdelta = 0;
- } else {
- predelta = 0;
- postdelta = 4;
- }
- if(ubit) {
- for (i = 0; i < 16; ++i) {
- if(!(reglist & (1 << i)))
- continue;
- address += predelta;
- if(lbit)
- reg.r[i] = getmem_w(address);
- else
- putmem_w(address, reg.r[i]);
- address += postdelta;
- }
- } else {
- for (i = 15; 0 <= i; --i) {
- if(!(reglist & (1 << i)))
- continue;
- address -= predelta;
- if(lbit)
- reg.r[i] = getmem_w(address);
- else
- putmem_w(address, reg.r[i]);
- address -= postdelta;
- }
- }
- if(wbit) {
- reg.r[rn] = address;
- }
- if(trace) {
- itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
- (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
- rn, reg.r[rn], (wbit ? "!" : ""), reglist);
- }
- }
- void
- Ib(ulong inst)
- {
- long v;
- v = inst & 0xffffff;
- v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
- if(trace)
- itrace("B%s\t#%lux", cond[reg.cond], v);
- reg.r[REGPC] = v - 4;
- }
- void
- Ibl(ulong inst)
- {
- long v;
- Symbol s;
- v = inst & 0xffffff;
- v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
- if(trace)
- itrace("BL%s\t#%lux", cond[reg.cond], v);
- if(calltree) {
- findsym(v, CTEXT, &s);
- Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
- printparams(&s, reg.r[13]);
- Bprint(bioout, "from ");
- printsource(reg.r[REGPC]);
- Bputc(bioout, '\n');
- }
- reg.r[REGLINK] = reg.r[REGPC] + 4;
- reg.r[REGPC] = v - 4;
- }
|