summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ki/run.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/ki/run.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ki/run.c')
-rwxr-xr-xsys/src/cmd/ki/run.c1411
1 files changed, 1411 insertions, 0 deletions
diff --git a/sys/src/cmd/ki/run.c b/sys/src/cmd/ki/run.c
new file mode 100755
index 000000000..269eaa44c
--- /dev/null
+++ b/sys/src/cmd/ki/run.c
@@ -0,0 +1,1411 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+#define Extern extern
+#include "sparc.h"
+
+void add(ulong);
+void and(ulong);
+void or(ulong);
+void xor(ulong);
+void sub(ulong);
+void andn(ulong);
+void xnor(ulong);
+void subcc(ulong);
+void sll(ulong);
+void srl(ulong);
+void sra(ulong);
+void jmpl(ulong);
+void andcc(ulong);
+void xorcc(ulong);
+void andncc(ulong);
+void wry(ulong);
+void rdy(ulong);
+void mulscc(ulong);
+void fcmp(ulong);
+void farith(ulong);
+void addcc(ulong);
+void addx(ulong);
+void addxcc(ulong);
+void orcc(ulong);
+void orncc(ulong);
+void xnorcc(ulong);
+void orn(ulong);
+
+Inst op2[] = {
+ { add, "add", Iarith },
+ { and, "and", Iarith },
+ { or, "or", Iarith },
+ { xor, "xor", Iarith },
+ { sub, "sub", Iarith },
+ { andn, "andn", Iarith },
+ { orn, "orn", Inop },
+ { xnor, "xnor", Iarith },
+ { addx, "addx", Iarith },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { addcc, "addcc", Iarith },
+ { andcc, "andcc", Iarith },
+ { orcc, "orcc", Iarith },
+ { xorcc, "xorcc", Iarith },
+ { subcc, "subcc", Iarith },
+ { andncc, "andncc",Iarith },
+ { orncc, "orncc", Iarith },
+ { xnorcc, "xnorcc",Iarith },
+ { addxcc, "addxcc",Iarith },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { mulscc, "mulscc", Iarith },
+ { sll, "sll", Iarith },
+ { srl, "srl", Iarith },
+ { sra, "sra", Iarith },
+ { rdy, "rdy", Ireg },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { wry, "wry", Ireg },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { farith, "farith", Ifloat },
+ { fcmp, "fcmp", Ifloat },
+ { undef, "" },
+ { undef, "" },
+ { jmpl, "jmpl", Ibranch },
+ { undef, "" },
+ { ta, "ta", Isyscall },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { 0 }
+};
+
+void st(ulong);
+void stb(ulong);
+void sth(ulong);
+void ld(ulong);
+void ldub(ulong);
+void ldsb(ulong);
+void lduh(ulong);
+void stf(ulong);
+void ldf(ulong);
+void ldsh(ulong);
+void std(ulong);
+void ldd(ulong);
+void ldstub(ulong);
+void swap(ulong);
+void lddf(ulong);
+void stdf(ulong);
+
+Inst op3[] = {
+ { ld, "ld", Iload },
+ { ldub, "ldub", Iload },
+ { lduh, "lduh", Iload },
+ { ldd, "ldd", Iload },
+ { st, "st", Istore },
+ { stb, "stb", Istore },
+ { sth, "sth", Istore },
+ { std, "std", Istore },
+ { undef, "" },
+ { ldsb, "ldsb", Iload },
+ { ldsh, "ldsh", Iload },
+ { undef, "" },
+ { undef, "" },
+ { ldstub, "ldstub", Iload },
+ { undef, "" },
+ { swap, "swap", Iload },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { ldf, "ldf", Ifloat },
+ { undef, "" },
+ { undef, "" },
+ { lddf, "lddf", Ifloat },
+ { stf, "stf", Ifloat },
+ { undef, "" },
+ { undef, "" },
+ { stdf, "stdf", Ifloat },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { undef, "" },
+ { 0 }
+};
+
+void sethi(ulong);
+void bicc(ulong);
+void fbcc(ulong);
+void call(ulong);
+
+Inst op0[] = {
+ { undef, "" },
+ { undef, "" },
+ { bicc, "bicc", Ibranch },
+ { undef, "" },
+ { sethi, "sethi",Iarith },
+ { undef, "" },
+ { fbcc, "fbcc", Ibranch },
+ { undef, "" },
+ /* This is a fake and connot be reached by op0 decode */
+ { call, "call", Ibranch },
+ { 0 }
+};
+
+void call(ulong);
+
+void
+run(void)
+{
+ do {
+ reg.r[0] = 0;
+ reg.ir = ifetch(reg.pc);
+ switch(reg.ir>>30) {
+ case 0:
+ ci = &op0[(reg.ir>>22)&0x07];
+ ci->count++;
+ (*ci->func)(reg.ir);
+ break;
+ case 1:
+ ci = &op0[8];
+ ci->count++;
+ call(reg.ir);
+ break;
+ case 2:
+ ci = &op2[(reg.ir>>19)&0x3f];
+ ci->count++;
+ (*ci->func)(reg.ir);
+ break;
+ case 3:
+ ci = &op3[(reg.ir>>19)&0x3f];
+ ci->count++;
+ (*ci->func)(reg.ir);
+ break;
+ }
+ reg.pc += 4;
+ if(bplist)
+ brkchk(reg.pc, Instruction);
+ }while(--count);
+}
+
+void
+ilock(int rd)
+{
+ ulong ir;
+
+ ir = getmem_4(reg.pc+4);
+ switch(ir>>30) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if(((ir>>20)&0x1f) == 0x1a) /* floating point */
+ break;
+ case 3:
+ if(rd == ((ir>>14)&0x1f)) {
+ loadlock++;
+ break;
+ }
+ if(ir&IMMBIT)
+ break;
+ if(rd == (ir&0x1f))
+ loadlock++;
+ break;
+ }
+}
+
+void
+delay(ulong npc)
+{
+ ulong opc;
+
+ reg.r[0] = 0;
+ if(reg.ir != NOP)
+ ci->useddelay++;
+ switch(reg.ir>>30) {
+ case 0:
+ ci = &op0[(reg.ir>>22)&0x07];
+ ci->count++;
+ (*ci->func)(reg.ir);
+ break;
+ case 1:
+ ci = &op0[8];
+ ci->count++;
+ call(reg.ir);
+ break;
+ case 2:
+ ci = &op2[(reg.ir>>19)&0x3f];
+ ci->count++;
+ opc = reg.pc;
+ reg.pc = npc-4;
+ (*ci->func)(reg.ir);
+ reg.pc = opc;
+ break;
+ case 3:
+ ci = &op3[(reg.ir>>19)&0x3f];
+ ci->count++;
+ opc = reg.pc;
+ reg.pc = npc-4;
+ (*ci->func)(reg.ir);
+ reg.pc = opc;
+ break;
+ }
+}
+
+void
+undef(ulong ir)
+{
+/* Bprint(bioout, "op=%d op2=%d op3=%d\n", ir>>30, (ir>>21)&0x7, (ir>>19)&0x3f); */
+ Bprint(bioout, "illegal_instruction IR #%.8lux\n", ir);
+ longjmp(errjmp, 0);
+}
+
+void
+sub(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("sub\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("sub\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] - v;
+}
+
+void
+sll(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("sll\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2]&0x1F;
+ if(trace)
+ itrace("sll\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] << v;
+}
+
+void
+srl(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("srl\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("srl\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = (ulong)reg.r[rs1] >> v;
+}
+
+void
+sra(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("sra\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("sra\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ if(reg.r[rs1]&SIGNBIT)
+ reg.r[rd] = reg.r[rs1]>>v | ~((1<<(32-v))-1);
+ else
+ reg.r[rd] = reg.r[rs1]>>v;
+}
+
+void
+subcc(ulong ir)
+{
+ long v;
+ int b31rs1, b31op2, b31res, r, rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("subcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("subcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] - v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ b31rs1 = reg.r[rs1]>>31;
+ b31op2 = v>>31;
+ b31res = r>>31;
+
+ if((b31rs1 & ~b31op2 & ~b31res)|(~b31rs1 & b31op2 & b31res))
+ reg.psr |= PSR_v;
+
+ if((~b31rs1 & b31op2)|(b31res & (~b31rs1|b31op2)))
+ reg.psr |= PSR_c;
+
+ reg.r[rd] = r;
+
+}
+
+void
+add(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("add\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("add\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] + v;
+}
+
+void
+addcc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2, b31rs1, b31op2, b31r;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("addcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("addcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] + v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ b31rs1 = reg.r[rs1]>>31;
+ b31op2 = v>>31;
+ b31r = r>>31;
+ if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r))
+ reg.psr |= PSR_v;
+ if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2)))
+ reg.psr |= PSR_c;
+
+ reg.r[rd] = r;
+}
+
+void
+addx(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("addx\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("addx\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ if(reg.psr&PSR_c)
+ v++;
+ reg.r[rd] = reg.r[rs1] + v;
+}
+
+void
+addxcc(ulong ir)
+{
+ long r, v;
+ int rd, rs1, rs2, b31rs1, b31op2, b31r;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("addxcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("addxcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ if(reg.psr&PSR_c)
+ v++;
+
+ r = reg.r[rs1] + v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ b31rs1 = reg.r[rs1]>>31;
+ b31op2 = v>>31;
+ b31r = r>>31;
+ if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r))
+ reg.psr |= PSR_v;
+ if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2)))
+ reg.psr |= PSR_c;
+
+ reg.r[rd] = r;
+}
+
+void
+wry(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(rd != 0)
+ undef(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("wry\tr%d,#0x%x,Y", rs1, v);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("wry\tr%d,r%d,Y", rs1, rs2);
+ }
+ reg.Y = reg.r[rs1] + v;
+}
+
+void
+rdy(ulong ir)
+{
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ USED(rs2);
+ if(rs1 != 0)
+ undef(ir);
+
+ if(trace)
+ itrace("rdy\tY,r%d", rd);
+
+ reg.r[rd] = reg.Y;
+}
+
+void
+and(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("and\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("and\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] & v;
+}
+
+void
+andcc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("andcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("andcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] & v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+orcc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("orcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("orcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] | v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+mulscc(ulong ir)
+{
+ int b, n, v, rd, rs1, rs2;
+ long o1, o2, r, b31o1, b31o2, b31r;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(o2, ir);
+ if(trace)
+ itrace("mulscc\tr%d,#0x%x,r%d", rs1, o2, rd);
+ }
+ else {
+ o2 = reg.r[rs2];
+ if(trace)
+ itrace("mulscc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ o1 = reg.r[rs1]>>1;
+ n = reg.psr&PSR_n ? 1 : 0;
+ v = reg.psr&PSR_v ? 1 : 0;
+
+ o1 |= (n ^ v)<<31;
+ if((reg.Y&1) == 0)
+ o2 = 0;
+
+ r = o1 + o2;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ b31o1 = o1>>31;
+ b31o2 = o2>>31;
+ b31r = r>>31;
+ if((b31o1 & b31o2 & ~b31r) | (~b31o1 & ~b31o2 & b31r))
+ reg.psr |= PSR_v;
+ if((b31o1 & b31o2) | (~b31r & (b31o1 | b31o2)))
+ reg.psr |= PSR_c;
+
+ b = reg.r[rs1]&1;
+ reg.Y = (reg.Y>>1)|(b<<31);
+ reg.r[rd] = r;
+}
+
+void
+or(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("or\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("or\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] | v;
+}
+
+void
+xor(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("xor\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("xor\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] ^ v;
+}
+
+void
+xorcc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("xorcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("xorcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] ^ v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+andn(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("andn\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("andn\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] & ~v;
+}
+
+void
+andncc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("andncc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("andncc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] & ~v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+orn(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(rd == 0 && rs1 == 0) /* ken used orn r0,r0,r0 as nop */
+ nopcount++;
+
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("orn\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("orn\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] | ~v;
+}
+
+void
+orncc(ulong ir)
+{
+ long r, v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("orncc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("orncc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] | ~v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+xnor(ulong ir)
+{
+ long v;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("xnor\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("xnor\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ reg.r[rd] = reg.r[rs1] ^ ~v;
+}
+
+void
+xnorcc(ulong ir)
+{
+ long v, r;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(v, ir);
+ if(trace)
+ itrace("xnorcc\tr%d,#0x%x,r%d", rs1, v, rd);
+ }
+ else {
+ v = reg.r[rs2];
+ if(trace)
+ itrace("xnorcc\tr%d,r%d,r%d", rs1, rs2, rd);
+ }
+ r = reg.r[rs1] ^ ~v;
+ reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v);
+ if(r == 0)
+ reg.psr |= PSR_z;
+ if(r < 0)
+ reg.psr |= PSR_n;
+
+ reg.r[rd] = r;
+}
+
+void
+st(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("st\tr%d,0x%lux(r%d) %lux=%lux",
+ rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("st\tr%d,[r%d+r%d] %lux=%lux",
+ rd, rs1, rs2, ea, reg.r[rd]);
+ }
+
+ putmem_w(ea, reg.r[rd]);
+}
+
+void
+std(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("std\tr%d,0x%lux(r%d) %lux=%lux",
+ rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("std\tr%d,[r%d+r%d] %lux=%lux",
+ rd, rs1, rs2, ea, reg.r[rd]);
+ }
+
+ putmem_w(ea, reg.r[rd]);
+ putmem_w(ea+4, reg.r[rd+1]);
+}
+
+void
+stb(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("stb\tr%d,0x%lux(r%d) %lux=%lux",
+ rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xff);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("stb\tr%d,[r%d+r%d] %lux=%lux",
+ rd, rs1, rs2, ea, reg.r[rd]&0xff);
+ }
+
+ putmem_b(ea, reg.r[rd]);
+}
+
+void
+sth(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("sth\tr%d,0x%lux(r%d) %lux=%lux",
+ rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xffff);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("sth\tr%d,[r%d+r%d] %lux=%lux",
+ rd, rs1, rs2, ea, reg.r[rd]&0xffff);
+ }
+
+ putmem_h(ea, reg.r[rd]);
+}
+
+void
+ld(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ld\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ld\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = getmem_w(ea);
+ ilock(rd);
+}
+
+void
+swap(ulong ir)
+{
+ ulong t, ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("swap\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("swap\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ t = reg.r[rd];
+ reg.r[rd] = getmem_w(ea);
+ putmem_w(ea, t);
+}
+
+void
+ldd(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ldd\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ldd\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = getmem_w(ea);
+ reg.r[rd+1] = getmem_w(ea+4);
+}
+
+void
+ldub(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ldub\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ldub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = getmem_b(ea) & 0xff;
+ ilock(rd);
+}
+
+void
+ldstub(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ldstub\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ldstub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = getmem_b(ea) & 0xff;
+ putmem_b(ea, 0xff);
+}
+
+void
+ldsb(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ldsb\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ldsb\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = (schar)getmem_b(ea);
+ ilock(rd);
+}
+
+void
+lduh(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("lduh\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("lduh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = getmem_h(ea) & 0xffff;
+ ilock(rd);
+}
+
+void
+ldsh(ulong ir)
+{
+ ulong ea;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ if(trace)
+ itrace("ldsh\tr%d,0x%lux(r%d) ea=%lux",
+ rd, ea, rs1, ea+reg.r[rs1]);
+ ea += reg.r[rs1];
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("ldsh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
+ }
+
+ reg.r[rd] = (short)getmem_h(ea);
+ ilock(rd);
+}
+
+void
+sethi(ulong ir)
+{
+ int rd;
+ ulong v;
+
+ rd = (ir>>25)&0x1f;
+ v = (ir&0x3FFFFF)<<10;
+
+ if(rd == 0)
+ nopcount++;
+
+ if(trace)
+ itrace("sethi\t0x%lux,r%d", v, rd);
+
+ reg.r[rd] = v;
+}
+
+void
+call(ulong ir)
+{
+ Symbol s;
+ ulong npc;
+
+ npc = (ir<<2) + reg.pc;
+ if(trace)
+ itrace("call\t%lux", npc);
+
+ ci->taken++;
+ reg.r[15] = reg.pc;
+ reg.ir = ifetch(reg.pc+4);
+ delay(npc);
+
+ if(calltree) {
+ findsym(npc, CTEXT, &s);
+ Bprint(bioout, "%8lux %s(", reg.pc, s.name);
+ printparams(&s, reg.r[1]);
+ Bprint(bioout, "from ");
+ printsource(reg.pc);
+ Bputc(bioout, '\n');
+ }
+ npc -= 4;
+ reg.pc = npc;
+}
+
+void
+jmpl(ulong ir)
+{
+ ulong ea, o;
+ Symbol s;
+ int rd, rs1, rs2;
+
+ getrop23(ir);
+ if(ir&IMMBIT) {
+ ximm(ea, ir);
+ o = ea;
+ if(trace)
+ itrace("jmpl\t0x%lux(r%d),r%d", ea, rs1, rd);
+
+ ea += reg.r[rs1];
+ if(calltree && rd == 0 && o == 8) {
+ findsym(ea-4, CTEXT, &s);
+ Bprint(bioout, "%8lux return to %lux %s r7=%lux\n",
+ reg.pc, ea-4, s.name, reg.r[7]);
+ }
+ }
+ else {
+ ea = reg.r[rs1] + reg.r[rs2];
+ if(trace)
+ itrace("jmpl\t[r%d+r%d],r%d", rs1, rs2, rd);
+ }
+
+ ci->taken++;
+ reg.r[rd] = reg.pc;
+ reg.ir = ifetch(reg.pc+4);
+ delay(ea);
+ reg.pc = ea-4;
+}
+
+void
+bicc(ulong ir)
+{
+ char *op;
+ ulong npc, anul, ba;
+ int takeit, z, v, n, c;
+
+ SET(op, takeit);
+ ba = 0;
+ switch((ir>>25)&0x0F) {
+ case 0:
+ op = "bn";
+ takeit = 0;
+ break;
+ case 1:
+ op = "be";
+ takeit = reg.psr&PSR_z;
+ break;
+ case 2:
+ op = "ble";
+ z = reg.psr&PSR_z ? 1 : 0;
+ v = reg.psr&PSR_v ? 1 : 0;
+ n = reg.psr&PSR_n ? 1 : 0;
+ takeit = z | (n ^ v);
+ break;
+ case 3:
+ op = "bl";
+ v = reg.psr&PSR_v ? 1 : 0;
+ n = reg.psr&PSR_n ? 1 : 0;
+ takeit = n ^ v;
+ break;
+ case 4:
+ op = "bleu";
+ z = reg.psr&PSR_z ? 1 : 0;
+ c = reg.psr&PSR_c ? 1 : 0;
+ takeit = c | z;
+ break;
+ case 5:
+ op = "bcs";
+ takeit = reg.psr&PSR_c;
+ break;
+ case 6:
+ op = "bneg";
+ takeit = reg.psr&PSR_n;
+ break;
+ case 7:
+ op = "bvs";
+ takeit = reg.psr&PSR_v;
+ break;
+ case 8:
+ op = "ba";
+ ba = 1;
+ takeit = 1;
+ break;
+ case 9:
+ op = "bne";
+ takeit = !(reg.psr&PSR_z);
+ break;
+ case 10:
+ op = "bg";
+ z = reg.psr&PSR_z ? 1 : 0;
+ v = reg.psr&PSR_v ? 1 : 0;
+ n = reg.psr&PSR_n ? 1 : 0;
+ takeit = !(z | (n ^ v));
+ break;
+ case 11:
+ op = "bge";
+ v = reg.psr&PSR_v ? 1 : 0;
+ n = reg.psr&PSR_n ? 1 : 0;
+ takeit = !(n ^ v);
+ break;
+ case 12:
+ op = "bgu";
+ z = reg.psr&PSR_z ? 1 : 0;
+ c = reg.psr&PSR_c ? 1 : 0;
+ takeit = !(c | z);
+ break;
+ case 13:
+ op = "bcc";
+ takeit = !(reg.psr&PSR_c);
+ break;
+ case 14:
+ op = "bpos";
+ takeit = !(reg.psr&PSR_n);
+ break;
+ case 15:
+ op = "bvc";
+ takeit = !(reg.psr&PSR_v);
+ break;
+ }
+
+ npc = ir & 0x3FFFFF;
+ if(npc & (1<<21))
+ npc |= ~((1<<22)-1);
+ npc = (npc<<2) + reg.pc;
+
+ anul = ir&ANUL;
+ if(trace) {
+ if(anul)
+ itrace("%s,a\t%lux", op, npc);
+ else
+ itrace("%s\t%lux", op, npc);
+ }
+
+ if(takeit == 0) {
+ reg.pc += 4;
+ if(anul == 0) {
+ reg.ir = ifetch(reg.pc);
+ delay(reg.pc+4);
+ }
+ else
+ anulled++;
+ return;
+ }
+
+ ci->taken++;
+ if(ba && anul) {
+ anulled++;
+ reg.pc = npc-4;
+ return;
+ }
+ reg.ir = ifetch(reg.pc+4);
+ delay(npc);
+ reg.pc = npc-4;
+}