|
@@ -0,0 +1,2027 @@
|
|
|
+#include <u.h>
|
|
|
+#include <libc.h>
|
|
|
+#include <bio.h>
|
|
|
+#include <mach.h>
|
|
|
+#define Extern extern
|
|
|
+#include "power.h"
|
|
|
+
|
|
|
+void add(ulong);
|
|
|
+void addc(ulong);
|
|
|
+void adde(ulong);
|
|
|
+void addme(ulong);
|
|
|
+void addze(ulong);
|
|
|
+void and(ulong);
|
|
|
+void andc(ulong);
|
|
|
+void cmp(ulong);
|
|
|
+void cmpl(ulong);
|
|
|
+void cntlzw(ulong);
|
|
|
+void dcbf(ulong);
|
|
|
+void dcbi(ulong);
|
|
|
+void dcbst(ulong);
|
|
|
+void dcbt(ulong);
|
|
|
+void dcbtst(ulong);
|
|
|
+void dcbz(ulong);
|
|
|
+void divw(ulong);
|
|
|
+void divwu(ulong);
|
|
|
+void eciwx(ulong);
|
|
|
+void ecowx(ulong);
|
|
|
+void eieio(ulong);
|
|
|
+void eqv(ulong);
|
|
|
+void extsb(ulong);
|
|
|
+void extsh(ulong);
|
|
|
+void icbi(ulong);
|
|
|
+void lbzx(ulong);
|
|
|
+void lfdx(ulong);
|
|
|
+void lfsx(ulong);
|
|
|
+void lhax(ulong);
|
|
|
+void lhbrx(ulong);
|
|
|
+void lhzx(ulong);
|
|
|
+void lswi(ulong);
|
|
|
+void lswx(ulong);
|
|
|
+void lwarx(ulong);
|
|
|
+void lwbrx(ulong);
|
|
|
+void lwzx(ulong);
|
|
|
+void mcrxr(ulong);
|
|
|
+void mfcr(ulong);
|
|
|
+void mfmsr(ulong);
|
|
|
+void mfpmr(ulong);
|
|
|
+void mfspr(ulong);
|
|
|
+void mfsr(ulong);
|
|
|
+void mfsrin(ulong);
|
|
|
+void mftb(ulong);
|
|
|
+void mftbu(ulong);
|
|
|
+void mspr(ulong);
|
|
|
+void mtcrf(ulong);
|
|
|
+void mtmsr(ulong);
|
|
|
+void mtpmr(ulong);
|
|
|
+void mtspr(ulong);
|
|
|
+void mtsr(ulong);
|
|
|
+void mtsrin(ulong);
|
|
|
+void mttb(ulong);
|
|
|
+void mttbu(ulong);
|
|
|
+void mulhw(ulong);
|
|
|
+void mulhwu(ulong);
|
|
|
+void mullw(ulong);
|
|
|
+void nand(ulong);
|
|
|
+void neg(ulong);
|
|
|
+void nor(ulong);
|
|
|
+void or(ulong);
|
|
|
+void orc(ulong);
|
|
|
+void slbia(ulong);
|
|
|
+void slbia(ulong);
|
|
|
+void slw(ulong);
|
|
|
+void sraw(ulong);
|
|
|
+void srawi(ulong);
|
|
|
+void srw(ulong);
|
|
|
+void stbx(ulong);
|
|
|
+void stfdx(ulong);
|
|
|
+void stfiwx(ulong);
|
|
|
+void stfsx(ulong);
|
|
|
+void sthbrx(ulong);
|
|
|
+void sthx(ulong);
|
|
|
+void stswi(ulong);
|
|
|
+void stswx(ulong);
|
|
|
+void stwbrx(ulong);
|
|
|
+void stwcx(ulong);
|
|
|
+void stwx(ulong);
|
|
|
+void subf(ulong);
|
|
|
+void subfc(ulong);
|
|
|
+void subfe(ulong);
|
|
|
+void subfme(ulong);
|
|
|
+void subfze(ulong);
|
|
|
+void sync(ulong);
|
|
|
+void tlbie(ulong);
|
|
|
+void tw(ulong);
|
|
|
+void xor(ulong);
|
|
|
+
|
|
|
+Inst op31[] = {
|
|
|
+[0] {cmp, "cmp", Iarith},
|
|
|
+[4] {tw, "tw", Iarith},
|
|
|
+[8] {subfc, "subfc", Iarith},
|
|
|
+[10] {addc, "addc", Iarith},
|
|
|
+[11] {mulhwu, "mulhwu", Iarith},
|
|
|
+[19] {mfcr, "mfcr", Iarith},
|
|
|
+[20] {lwarx, "lwarx", Iload},
|
|
|
+[23] {lwzx, "lwzx", Iload},
|
|
|
+[24] {slw, "slw", Ilog},
|
|
|
+[26] {cntlzw, "cntlzw", Ilog},
|
|
|
+[28] {and, "and", Ilog},
|
|
|
+[32] {cmpl, "cmpl", Iarith},
|
|
|
+[40] {subf, "subf", Iarith},
|
|
|
+[54] {dcbst, "dcbst", Icontrol},
|
|
|
+[55] {lwzx, "lwzux", Iload},
|
|
|
+[60] {andc, "andc", Ilog},
|
|
|
+[75] {mulhw, "mulhw", Iarith},
|
|
|
+[83] {0, "mfmsr", Icontrol},
|
|
|
+[86] {dcbf, "dcbf", Icontrol},
|
|
|
+[87] {lbzx, "lbzx", Iload},
|
|
|
+[104] {neg, "neg", Iarith},
|
|
|
+[115] {0, "mfpmr", Iarith},
|
|
|
+[119] {lbzx, "lbzux", Iload},
|
|
|
+[124] {nor, "nor", Iarith},
|
|
|
+[136] {subfe, "subfe", Iarith},
|
|
|
+[138] {adde, "adde", Iarith},
|
|
|
+[144] {mtcrf, "mtcrf", Ireg},
|
|
|
+[146] {0, "mtmsr", Icontrol},
|
|
|
+[150] {stwcx, "stwcx.", Istore},
|
|
|
+[151] {stwx, "stwx", Istore},
|
|
|
+[178] {0, "mtpmr", Icontrol},
|
|
|
+[183] {stwx, "stwux", Istore},
|
|
|
+[200] {subfze, "subfze", Iarith},
|
|
|
+[202] {addze, "addze", Iarith},
|
|
|
+[210] {0, "mtsr", Ireg},
|
|
|
+[215] {stbx, "stbx", Istore},
|
|
|
+[232] {subfme, "subfme", Iarith},
|
|
|
+[234] {addme, "addme", Iarith},
|
|
|
+[235] {mullw, "mullw", Iarith},
|
|
|
+[242] {0, "mtsrin", Ireg},
|
|
|
+[246] {dcbtst, "dcbtst", Icontrol},
|
|
|
+[247] {stbx, "stbux", Istore},
|
|
|
+[266] {add, "add", Iarith},
|
|
|
+[275] {0, "mftb", Icontrol},
|
|
|
+[278] {dcbt, "dcbt", Icontrol},
|
|
|
+[279] {lhzx, "lhzx", Iload},
|
|
|
+[284] {eqv, "eqv", Ilog},
|
|
|
+[306] {0, "tlbie", Icontrol},
|
|
|
+[307] {0, "mftbu", Icontrol},
|
|
|
+[310] {0, "eciwx", Icontrol},
|
|
|
+[311] {lhzx, "lhzux", Iload},
|
|
|
+[316] {xor, "xor", Ilog},
|
|
|
+[339] {mspr, "mfspr", Ireg},
|
|
|
+[343] {lhax, "lhax", Iload},
|
|
|
+[375] {lhax, "lhaux", Iload},
|
|
|
+[403] {0, "mttb", Icontrol},
|
|
|
+[407] {sthx, "sthx", Istore},
|
|
|
+[412] {orc, "orc", Ilog},
|
|
|
+[434] {0, "slbia", Iarith},
|
|
|
+[435] {0, "mttbu", Icontrol},
|
|
|
+[438] {0, "ecowx", Icontrol},
|
|
|
+[439] {sthx, "sthux", Istore},
|
|
|
+[444] {or, "or", Ilog},
|
|
|
+[459] {divwu, "divwu", Iarith},
|
|
|
+[467] {mspr, "mtspr", Ireg},
|
|
|
+[470] {0, "dcbi", Icontrol},
|
|
|
+[476] {nand, "nand", Ilog},
|
|
|
+[491] {divw, "divw", Iarith},
|
|
|
+[498] {0, "slbia", Icontrol},
|
|
|
+[512] {mcrxr, "mcrxr", Ireg},
|
|
|
+[533] {lswx, "lswx", Iload},
|
|
|
+[534] {lwbrx, "lwbrx", Iload},
|
|
|
+[535] {lfsx, "lfsx", Ifloat},
|
|
|
+[536] {srw, "srw", Ilog},
|
|
|
+[567] {lfsx, "lfsux", Ifloat},
|
|
|
+[595] {0, "mfsr", Iarith},
|
|
|
+[597] {lswi, "lswi", Iarith},
|
|
|
+[598] {sync, "sync", Iarith},
|
|
|
+[599] {lfdx, "lfdx", Ifloat},
|
|
|
+[631] {lfdx, "lfdux", Ifloat},
|
|
|
+[659] {0, "mfsrin", Ireg},
|
|
|
+[661] {stswx, "stswx", Istore},
|
|
|
+[662] {stwbrx, "stwbrx", Istore},
|
|
|
+[663] {stfsx, "stfsx", Istore},
|
|
|
+[695] {stfsx, "stfsux", Istore},
|
|
|
+[725] {stswi, "stswi", Istore},
|
|
|
+[727] {stfdx, "stfdx", Istore},
|
|
|
+[759] {stfdx, "stfdux", Istore},
|
|
|
+[790] {lhbrx, "lhbrx", Iload},
|
|
|
+[792] {sraw, "sraw", Ilog},
|
|
|
+[824] {srawi, "srawi", Ilog},
|
|
|
+[854] {0, "eieio", Icontrol},
|
|
|
+[918] {sthbrx, "sthbrx", Istore},
|
|
|
+[922] {extsh, "extsh", Iarith},
|
|
|
+[954] {extsb, "extsb", Iarith},
|
|
|
+[982] {icbi, "icbi", Icontrol},
|
|
|
+[983] {unimp, "stfiwx", Istore},
|
|
|
+[1014] {dcbz, "dcbz", Icontrol},
|
|
|
+};
|
|
|
+
|
|
|
+Inset ops31 = {op31, nelem(op31)};
|
|
|
+
|
|
|
+void
|
|
|
+mspr(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong *d;
|
|
|
+ char *n;
|
|
|
+ char buf[20];
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ switch((rb<<5) | ra) {
|
|
|
+ case 0:
|
|
|
+ undef(ir); /* was mq */
|
|
|
+ return;
|
|
|
+ case 1:
|
|
|
+ d = ®.xer; n = "xer";
|
|
|
+ break;
|
|
|
+ case 268:
|
|
|
+ case 284:
|
|
|
+ d = ®.tbl; n = "tbl";
|
|
|
+ break;
|
|
|
+ case 269:
|
|
|
+ case 285:
|
|
|
+ d = ®.tbu; n = "tbu";
|
|
|
+ break;
|
|
|
+ case 22:
|
|
|
+ d = ®.dec; n = "dec";
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ d = ®.lr; n = "lr";
|
|
|
+ break;
|
|
|
+ case 9:
|
|
|
+ d = ®.ctr; n = "ctr";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ d = 0; sprint(n = buf, "spr%d", rd);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(getxo(ir) == 339) {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%s", ci->name, rd, n);
|
|
|
+ reg.r[rd] = *d;
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\t%s,r%d", ci->name, n, rd);
|
|
|
+ *d = reg.r[rd];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+setcr(int d, long r)
|
|
|
+{
|
|
|
+ int c;
|
|
|
+
|
|
|
+ c = 0;
|
|
|
+ if(reg.xer & XER_SO)
|
|
|
+ c |= 1;
|
|
|
+ if(r == 0)
|
|
|
+ c |= 2;
|
|
|
+ else if(r > 0)
|
|
|
+ c |= 4;
|
|
|
+ else
|
|
|
+ c |= 8;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(d, 0xF)) | mkCR(d, c);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addi(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ if(trace) {
|
|
|
+ if(ra)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
|
|
|
+ else
|
|
|
+ itrace("li\tr%d,$0x%lux", rd, imm);
|
|
|
+ }
|
|
|
+ if(ra)
|
|
|
+ imm += reg.r[ra];
|
|
|
+ reg.r[rd] = imm;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addis(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ if(trace) {
|
|
|
+ if(ra)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
|
|
|
+ else
|
|
|
+ itrace("lis\tr%d,$0x%lux", rd, imm);
|
|
|
+ }
|
|
|
+ imm <<= 16;
|
|
|
+ if(ra)
|
|
|
+ imm += reg.r[ra];
|
|
|
+ reg.r[rd] = imm;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+and(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] & reg.r[rb];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+andc(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] & ~reg.r[rb];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+andicc(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] & imm;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+andiscc(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] & (imm<<16);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+cmpli(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ ulong c;
|
|
|
+ ulong imm, v;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ imm &= 0xFFFF;
|
|
|
+ if(rd & 3)
|
|
|
+ undef(ir);
|
|
|
+ rd >>= 2;
|
|
|
+ v = reg.r[ra];
|
|
|
+ c = 0;
|
|
|
+ if(reg.xer & XER_SO)
|
|
|
+ c |= CRSO;
|
|
|
+ if(v < imm)
|
|
|
+ c |= CRLT;
|
|
|
+ else if(v == imm)
|
|
|
+ c |= CREQ;
|
|
|
+ else
|
|
|
+ c |= CRGT;
|
|
|
+ c >>= 28;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+cmp(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong c;
|
|
|
+ long va, vb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rd & 3)
|
|
|
+ undef(ir);
|
|
|
+ rd >>= 2;
|
|
|
+ c = 0;
|
|
|
+ if(reg.xer & XER_SO)
|
|
|
+ c |= CRSO;
|
|
|
+ va = reg.r[ra];
|
|
|
+ vb = reg.r[rb];
|
|
|
+ if(va < vb)
|
|
|
+ c |= CRLT;
|
|
|
+ else if(va == vb)
|
|
|
+ c |= CREQ;
|
|
|
+ else
|
|
|
+ c |= CRGT;
|
|
|
+ c >>= 28;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+cmpi(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ ulong c;
|
|
|
+ long imm, v;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ if(rd & 3)
|
|
|
+ undef(ir);
|
|
|
+ rd >>= 2;
|
|
|
+ v = reg.r[ra];
|
|
|
+ c = 0;
|
|
|
+ if(reg.xer & XER_SO)
|
|
|
+ c |= CRSO;
|
|
|
+ if(v < imm)
|
|
|
+ c |= CRLT;
|
|
|
+ else if(v == imm)
|
|
|
+ c |= CREQ;
|
|
|
+ else
|
|
|
+ c |= CRGT;
|
|
|
+ c >>= 28;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+cmpl(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong c;
|
|
|
+ ulong va, vb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rd & 3)
|
|
|
+ undef(ir);
|
|
|
+ rd >>= 2;
|
|
|
+ c = 0;
|
|
|
+ if(reg.xer & XER_SO)
|
|
|
+ c |= CRSO;
|
|
|
+ va = reg.r[ra];
|
|
|
+ vb = reg.r[rb];
|
|
|
+ if(va < vb)
|
|
|
+ c |= CRLT;
|
|
|
+ else if(va == vb)
|
|
|
+ c |= CREQ;
|
|
|
+ else
|
|
|
+ c |= CRGT;
|
|
|
+ c >>= 28;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+cntlzw(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb, n;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ for(n=0; n<32 && (reg.r[rs] & (1L<<(31-n))) == 0; n++)
|
|
|
+ ;
|
|
|
+ reg.r[ra] = n;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+eqv(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = ~(reg.r[rs] ^ reg.r[rb]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+extsb(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ reg.r[ra] = (schar)reg.r[rs];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+extsh(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ reg.r[ra] = (short)reg.r[rs];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+add(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + reg.r[rb];
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(r >> 16)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addc(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + reg.r[rb];
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+adde(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + reg.r[rb] + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addic(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + imm;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addiccc(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + imm;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addme(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + 0xFFFFFFFF + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addze(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ r = (uvlong)(ulong)reg.r[ra] + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+divw(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(reg.r[rb] != 0 && ((ulong)reg.r[ra] != 0x80000000 || reg.r[rb] != -1))
|
|
|
+ reg.r[rd] = reg.r[ra]/reg.r[rb];
|
|
|
+ else if(ir & OE)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+divwu(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(reg.r[rb] != 0)
|
|
|
+ reg.r[rd] = (ulong)reg.r[ra]/(ulong)reg.r[rb];
|
|
|
+ else if(ir & OE)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mcrxr(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rd & 3 || ra != 0 || rb != 0 || ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ rd >>= 2;
|
|
|
+ reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, reg.xer>>28);
|
|
|
+ reg.xer &= ~(0xF<<28);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mtcrf(ulong ir)
|
|
|
+{
|
|
|
+ int rs, crm, i;
|
|
|
+ ulong m;
|
|
|
+
|
|
|
+ if(ir & ((1<<20)|(1<<11)|Rc))
|
|
|
+ undef(ir);
|
|
|
+ rs = (ir>>21)&0x1F;
|
|
|
+ crm = (ir>>12)&0xFF;
|
|
|
+ m = 0;
|
|
|
+ for(i = 0x80; i; i >>= 1) {
|
|
|
+ m <<= 4;
|
|
|
+ if(crm & i)
|
|
|
+ m |= 0xF;
|
|
|
+ }
|
|
|
+ reg.cr = (reg.cr & ~m) | (reg.r[rs] & m);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mfcr(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ra != 0 || rb != 0 || ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ reg.r[rd] = reg.cr;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mulhw(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ reg.r[rd] = ((vlong)(long)reg.r[ra]*(long)reg.r[rb])>>32;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
|
|
|
+ /* BUG: doesn't set OV */
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mulhwu(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ reg.r[rd] = ((uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb])>>32;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]); /* not sure whether CR setting is signed or unsigned */
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
|
|
|
+ /* BUG: doesn't set OV */
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mullw(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb];
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
|
|
|
+ /* BUG: doesn't set OV */
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+mulli(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)imm;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+nand(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = ~(reg.r[rs] & reg.r[rb]);
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+neg(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ if(ir & OE)
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if((ulong)reg.r[ra] == 0x80000000) {
|
|
|
+ if(ir & OE)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ reg.r[rd] = reg.r[ra];
|
|
|
+ } else
|
|
|
+ reg.r[rd] = -reg.r[ra];
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+nor(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = ~(reg.r[rs] | reg.r[rb]);
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+or(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] | reg.r[rb];
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace) {
|
|
|
+ if(rs == rb)
|
|
|
+ itrace("mr%s\tr%d,r%d", ir&1?".":"", ra, rs);
|
|
|
+ else
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+orc(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] | ~reg.r[rb];
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ori(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] | imm;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+oris(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] | (imm<<16);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+}
|
|
|
+
|
|
|
+static ulong
|
|
|
+mkmask(int mb, int me)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ ulong v;
|
|
|
+
|
|
|
+ if(mb > me)
|
|
|
+ return mkmask(0, me) | mkmask(mb, 31);
|
|
|
+ v = 0;
|
|
|
+ for(i=mb; i<=me; i++)
|
|
|
+ v |= 1L << (31-i); /* don't need a loop, but i'm lazy */
|
|
|
+ return v;
|
|
|
+}
|
|
|
+
|
|
|
+static ulong
|
|
|
+rotl(ulong v, int sh)
|
|
|
+{
|
|
|
+ if(sh == 0)
|
|
|
+ return v;
|
|
|
+ return (v<<sh) | (v>>(32-sh));
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+rlwimi(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb, sh;
|
|
|
+ ulong m;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ sh = rb;
|
|
|
+ m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
|
|
|
+ reg.r[ra] = (reg.r[ra] & ~m) | (rotl(reg.r[rs], sh) & m);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,%d,#%lux", ci->name, ra, rs, sh, m);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+rlwinm(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb, sh;
|
|
|
+ ulong m;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ sh = rb;
|
|
|
+ m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
|
|
|
+ reg.r[ra] = rotl(reg.r[rs], sh) & m;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,%d,#%lux", ci->name, ir&Rc?".":"", ra, rs, sh, m);
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+rlwnm(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb, sh;
|
|
|
+ ulong m;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ sh = reg.r[rb] & 0x1F;
|
|
|
+ m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
|
|
|
+ reg.r[ra] = rotl(reg.r[rs], sh) & m;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,r%d,#%lux", ci->name, ra, rs, rb, m);
|
|
|
+ if(ir & 1)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+slw(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+ long v;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ v = reg.r[rb];
|
|
|
+ if((v & 0x20) == 0) {
|
|
|
+ v &= 0x1F;
|
|
|
+ reg.r[ra] = (ulong)reg.r[rs] << v;
|
|
|
+ } else
|
|
|
+ reg.r[ra] = 0;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sraw(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+ long v;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ v = reg.r[rb];
|
|
|
+ if((v & 0x20) == 0) {
|
|
|
+ v &= 0x1F;
|
|
|
+ if(reg.r[rs]&SIGNBIT && v)
|
|
|
+ reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
|
|
|
+ else
|
|
|
+ reg.r[ra] = reg.r[rs]>>v;
|
|
|
+ } else
|
|
|
+ reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+srawi(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+ long v;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ v = rb;
|
|
|
+ if((v & 0x20) == 0) {
|
|
|
+ v &= 0x1F;
|
|
|
+ if(reg.r[rs]&SIGNBIT && v)
|
|
|
+ reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
|
|
|
+ else
|
|
|
+ reg.r[ra] = reg.r[rs]>>v;
|
|
|
+ } else
|
|
|
+ reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,$%d", ci->name, ir&1?".":"", ra, rs, v);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+srw(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+ long v;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ v = reg.r[rb];
|
|
|
+ if((v & 0x20) == 0)
|
|
|
+ reg.r[ra] = (ulong)reg.r[rs] >> (v&0x1F);
|
|
|
+ else
|
|
|
+ reg.r[ra] = 0;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[ra]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subf(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + 1;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(r >> 16)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subfc(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + 1;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subfe(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subfic(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long imm;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + imm + 1;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subfme(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + 0xFFFFFFFF + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+subfze(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ ulong v;
|
|
|
+ uvlong r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(rb)
|
|
|
+ undef(ir);
|
|
|
+ r = (uvlong)((ulong)~reg.r[ra]) + (reg.xer&XER_CA)!=0;
|
|
|
+ v = r>>32;
|
|
|
+ reg.xer &= ~XER_CA;
|
|
|
+ if(v)
|
|
|
+ reg.xer |= XER_CA;
|
|
|
+ if(ir & OE) {
|
|
|
+ reg.xer &= ~XER_OV;
|
|
|
+ if(v>>1)
|
|
|
+ reg.xer |= XER_SO | XER_OV;
|
|
|
+ }
|
|
|
+ reg.r[rd] = (ulong)r;
|
|
|
+ if(ir & Rc)
|
|
|
+ setcr(0, reg.r[rd]);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+xor(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra, rb;
|
|
|
+
|
|
|
+ getlrrr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] ^ reg.r[rb];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,r%d", ci->name, ra, rs, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+xori(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] ^ imm;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+xoris(ulong ir)
|
|
|
+{
|
|
|
+ int rs, ra;
|
|
|
+ ulong imm;
|
|
|
+
|
|
|
+ getlirr(ir);
|
|
|
+ reg.r[ra] = reg.r[rs] ^ (imm<<16);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lwz(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_w(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lwzx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, upd;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==55;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_w(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lwarx(ulong ir)
|
|
|
+{
|
|
|
+ lwzx(ir);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lbz(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_b(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lbzx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, upd;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==119;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_b(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stw(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, imm, ra, ea, reg.r[rd], reg.r[rd]);
|
|
|
+ putmem_w(ea, reg.r[rd]);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stwx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd, rb;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==183;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
|
|
|
+ }
|
|
|
+ putmem_w(ea, reg.r[rd]);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stwcx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, rb;
|
|
|
+
|
|
|
+ if((ir & Rc) == 0)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
|
|
|
+ }
|
|
|
+ putmem_w(ea, reg.r[rd]); /* assume a reservation exists; store succeeded */
|
|
|
+ setcr(0, 0);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stb(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd, v;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ v = reg.r[rd] & 0xFF;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, imm, ra, ea, v, v);
|
|
|
+ putmem_b(ea, v);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stbx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd, rb, v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==247;
|
|
|
+ v = reg.r[rd] & 0xFF;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, ra, rb, ea, v, v);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, rb, ea, v, v);
|
|
|
+ }
|
|
|
+ putmem_b(ea, v);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lhz(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int imm, ra, rd, upd;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_h(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lhzx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, upd;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==311;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+
|
|
|
+ reg.r[rd] = getmem_h(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lha(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int imm, ra, rd, upd;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ reg.r[rd] = (short)getmem_h(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lhax(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, upd;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==311;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+
|
|
|
+ reg.r[rd] = (short)getmem_h(ea);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lhbrx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd;
|
|
|
+ ulong v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+ v = getmem_h(ea);
|
|
|
+
|
|
|
+ reg.r[rd] = ((v&0xFF)<<8)|(v&0xFF);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sth(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int imm, ra, rd, upd, v;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ upd = (ir&(1L<<26))!=0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ }
|
|
|
+ v = reg.r[rd] & 0xFFFF;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, imm, ra, ea, v, v);
|
|
|
+ putmem_h(ea, v);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sthx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, upd, rb, v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ upd = getxo(ir)==247;
|
|
|
+ v = reg.r[rd] & 0xFFFF;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(upd)
|
|
|
+ reg.r[ra] = ea;
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, ra, rb, ea, v, v);
|
|
|
+ } else {
|
|
|
+ if(upd)
|
|
|
+ undef(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, rb, ea, v, v);
|
|
|
+ }
|
|
|
+ putmem_h(ea, v);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sthbrx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, rb;
|
|
|
+ ulong v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ v = reg.r[rd];
|
|
|
+ v = ((v&0xFF)<<8)|(v&0xFF);
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, ra, rb, ea, v, v);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
|
|
|
+ ci->name, rd, rb, ea, v, v);
|
|
|
+ }
|
|
|
+ putmem_h(ea, v);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lwbrx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, i;
|
|
|
+ ulong v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+ v = 0;
|
|
|
+ for(i = 0; i < 4; i++)
|
|
|
+ v = v>>8 | getmem_b(ea++); /* assume unaligned load is allowed */
|
|
|
+ reg.r[rd] = v;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stwbrx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, i;
|
|
|
+ ulong v;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
|
|
|
+ }
|
|
|
+ v = 0;
|
|
|
+ for(i = 0; i < 4; i++) {
|
|
|
+ putmem_b(ea++, v & 0xFF); /* assume unaligned store is allowed */
|
|
|
+ v >>= 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lswi(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, n, i, r, b;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ n = rb;
|
|
|
+ if(n == 0)
|
|
|
+ n = 32;
|
|
|
+ ea = 0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
|
|
|
+ }
|
|
|
+ i = -1;
|
|
|
+ r = rd-1;
|
|
|
+ while(--n >= 0) {
|
|
|
+ if(i < 0) {
|
|
|
+ r = (r+1)&0x1F;
|
|
|
+ if(ra == 0 || r != ra)
|
|
|
+ reg.r[r] = 0;
|
|
|
+ i = 24;
|
|
|
+ }
|
|
|
+ b = getmem_b(ea++);
|
|
|
+ if(ra == 0 || r != ra)
|
|
|
+ reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
|
|
|
+ i -= 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lswx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, n, i, r, b;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ n = reg.xer & 0x7F;
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
|
|
|
+ }
|
|
|
+ i = -1;
|
|
|
+ r = rd-1;
|
|
|
+ while(--n >= 0) {
|
|
|
+ if(i < 0) {
|
|
|
+ r = (r+1)&0x1F;
|
|
|
+ if((ra == 0 || r != ra) && r != rb)
|
|
|
+ reg.r[r] = 0;
|
|
|
+ i = 24;
|
|
|
+ }
|
|
|
+ b = getmem_b(ea++);
|
|
|
+ if((ra == 0 || r != ra) && r != rb)
|
|
|
+ reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
|
|
|
+ i -= 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stswx(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, n, i, r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ n = reg.xer & 0x7F;
|
|
|
+ ea = reg.r[rb];
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
|
|
|
+ }
|
|
|
+ i = -1;
|
|
|
+ r = rd-1;
|
|
|
+ while(--n >= 0) {
|
|
|
+ if(i < 0) {
|
|
|
+ r = (r+1)&0x1F;
|
|
|
+ i = 24;
|
|
|
+ }
|
|
|
+ putmem_b(ea++, (reg.r[r]>>i)&0xFF);
|
|
|
+ i -= 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stswi(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int rb, ra, rd, n, i, r;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ n = rb;
|
|
|
+ if(n == 0)
|
|
|
+ n = 32;
|
|
|
+ ea = 0;
|
|
|
+ if(ra) {
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
|
|
|
+ } else {
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
|
|
|
+ }
|
|
|
+ i = -1;
|
|
|
+ r = rd-1;
|
|
|
+ while(--n >= 0) {
|
|
|
+ if(i < 0) {
|
|
|
+ r = (r+1)&0x1F;
|
|
|
+ i = 24;
|
|
|
+ }
|
|
|
+ putmem_b(ea++, (reg.r[r]>>i)&0xFF);
|
|
|
+ i -= 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+lmw(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, r;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ if(ra)
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ for(r = rd; r <= 31; r++) {
|
|
|
+ if(r != 0 && r != rd)
|
|
|
+ reg.r[rd] = getmem_w(ea);
|
|
|
+ ea += 4;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+stmw(ulong ir)
|
|
|
+{
|
|
|
+ ulong ea;
|
|
|
+ int ra, rd, r;
|
|
|
+ long imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ ea = imm;
|
|
|
+ if(ra)
|
|
|
+ ea += reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
|
|
|
+
|
|
|
+ for(r = rd; r <= 31; r++) {
|
|
|
+ putmem_w(ea, reg.r[rd]);
|
|
|
+ ea += 4;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+twi(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra;
|
|
|
+ long a, imm;
|
|
|
+
|
|
|
+ getairr(ir);
|
|
|
+ a = reg.r[ra];
|
|
|
+ if(trace)
|
|
|
+ itrace("twi\t#%.2x,r%d,$0x%lux (%ld)", rd, ra, imm, imm);
|
|
|
+ if(a < imm && rd&0x10 ||
|
|
|
+ a > imm && rd&0x08 ||
|
|
|
+ a == imm && rd&0x04 ||
|
|
|
+ (ulong)a < imm && rd&0x02 ||
|
|
|
+ (ulong)a > imm && rd&0x01) {
|
|
|
+ Bprint(bioout, "program_exception (trap type)\n");
|
|
|
+ longjmp(errjmp, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+tw(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+ long a, b;
|
|
|
+
|
|
|
+ getarrr(ir);
|
|
|
+ a = reg.r[ra];
|
|
|
+ b = reg.r[rb];
|
|
|
+ if(trace)
|
|
|
+ itrace("tw\t#%.2x,r%d,r%d", rd, ra, rb);
|
|
|
+ if(a < b && rd&0x10 ||
|
|
|
+ a > b && rd&0x08 ||
|
|
|
+ a == b && rd&0x04 ||
|
|
|
+ (ulong)a < b && rd&0x02 ||
|
|
|
+ (ulong)a > b && rd&0x01) {
|
|
|
+ Bprint(bioout, "program_exception (trap type)\n");
|
|
|
+ longjmp(errjmp, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sync(ulong ir)
|
|
|
+{
|
|
|
+ USED(ir);
|
|
|
+ if(trace)
|
|
|
+ itrace("sync");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+icbi(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+dcbf(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+dcbst(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+dcbt(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+dcbtst(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+dcbz(ulong ir)
|
|
|
+{
|
|
|
+ int rd, ra, rb;
|
|
|
+
|
|
|
+ if(ir & Rc)
|
|
|
+ undef(ir);
|
|
|
+ getarrr(ir);
|
|
|
+ USED(rd);
|
|
|
+ if(trace)
|
|
|
+ itrace("%s\tr%d,r%d", ci->name, ra, rb);
|
|
|
+}
|