#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;
}
|