#include "core.h" // Reset a Bedrock instance. void br_reset(Bedrock *br) { br->ip = 0; br->wst.p = 0; br->rst.p = 0; dev_reset(&br->dev); } // Load a new program into a Bedrock instance. void br_load(Bedrock *br, u8 bytecode[], int length) { br_reset(br); memcpy(&br->mem, bytecode, MIN(length, 65536)); br->alive = true; br->awake = true; } // Attempt to wake a Bedrock instance. // TODO: Redo this. void br_rouse(Bedrock *br) { if (TEST(br->dev.system.sleep, 0x0400)) { // SCREEN if (br->dev.screen.wake) { br->dev.screen.wake = false; br->dev.system.wake = 0x5; br->awake = true; return; } } if (TEST(br->dev.system.sleep, 0x0800)) { // INPUT if (br->dev.input.wake) { br->dev.input.wake = false; br->dev.system.wake = 0x4; br->awake = true; return; } } if (TEST(br->dev.system.sleep, 0x1000)) { // CLOCK if (clock_check_timers(&br->dev.clock)) { br->dev.system.wake = 0x3; br->awake = true; return; } } // System device is always chosen last. if (TEST(br->dev.system.sleep, 0x8000)) { // SYSTEM br->dev.system.wake = 0x0; br->awake = true; return; } } // Write a double to a device bus. Signal dev_write_double(DeviceBus *d, u8 port, u8 h, u8 l) { Signal s1 = dev_write(d, port, h); Signal s2 = dev_write(d, port+1, l); return s1 ? s1 : s2; } // Evaluate a Bedrock instance until a signal is emitted. Signal br_eval(Bedrock *br, int count) { #define SIGNAL(s) if (s) { return s; } else { continue; }; // Helpers. #define WST br->wst #define RST br->rst #define MEM br->mem #define IP br->ip #define WSTV(i) WST.mem[WST.p+(i)] #define RSTV(i) RST.mem[RST.p+(i)] // Push values to a stack. #define WPSH1(x) WST.mem[WST.p++] = (x); #define RPSH1(x) RST.mem[RST.p++] = (x); #define WPSH2(x,y) WPSH1(x); WPSH1(y); #define RPSH2(x,y) RPSH1(x); RPSH1(y); #define WPSHD(d) WPSH1(HIGH((d))); WPSH1(LOW((d))); #define RPSHD(d) RPSH1(HIGH((d))); RPSH1(LOW((d))); #define WPSHB(b) WPSH1(BOOL(b)); #define RPSHB(b) RPSH1(BOOL(b)); // Pop values from a stack. #define WPOP1(x) (x) = WST.mem[--WST.p]; #define RPOP1(x) (x) = RST.mem[--RST.p]; #define WPOP2(x,y) WPOP1(y); WPOP1(x); #define RPOP2(x,y) RPOP1(y); RPOP1(x); #define WPOPD(d) d = DOUBLE(WSTV(-2), WSTV(-1)); WST.p-=2; #define RPOPD(d) d = DOUBLE(RSTV(-2), RSTV(-1)); RST.p-=2; // Pop values without affecting the stack pointer. #define WGET1(x) x = WSTV(-1); #define RGET1(x) x = RSTV(-1); #define WGET2(x,y) x = WSTV(-2); y = WSTV(-1); #define RGET2(x,y) x = RSTV(-2); y = RSTV(-1); #define WGETD(x) x = DOUBLE(WSTV(-2), WSTV(-1)); #define RGETD(x) x = DOUBLE(RSTV(-2), RSTV(-1)); // Read the next value in memory. #define MPOP1(x) (x) = MEM[IP++]; #define MPOP2(x,y) MPOP1(x); MPOP1(y); #define MPOPD(d) d = DOUBLE(MEM[IP], MEM[IP+1]); IP+=2; // Read from a device port. #define DGET1(p) dev_read(&br->dev, p) #define DSET2(p,h,l) dev_write_double(&br->dev, p, h, l) register u16 u, v, w, x, y, z; register Signal sig; while (count--) { MPOP1(x); switch (x) { /* HLT */ case 0x00: return SIG_HALT; /* PSH */ case 0x01: RPOP1(x); WPSH1(x); continue; /* POP */ case 0x02: WST.p-=1; continue; /* CPY */ case 0x03: RGET1(x); WPSH1(x); continue; /* DUP */ case 0x04: WGET1(x); WPSH1(x); continue; /* OVR */ case 0x05: WPOP1(y); WGET1(x); WPSH1(y); WPSH1(x); continue; /* SWP */ case 0x06: WPOP1(y); WPOP1(x); WPSH1(y); WPSH1(x); continue; /* ROT */ case 0x07: WPOP1(z); WPOP1(y); WPOP1(x); WPSH1(y); WPSH1(z); WPSH1(x); continue; /* JMP */ case 0x08: WPOPD(x); IP=x; continue; /* JMS */ case 0x09: WPOPD(x); RPSHD(IP); IP=x; continue; /* JCN */ case 0x0A: WPOPD(y); WPOP1(x); if(x) IP=y; continue; /* JCS */ case 0x0B: WPOPD(y); WPOP1(x); if(x) { RPSHD(IP); IP=y; } continue; /* LDA */ case 0x0C: WPOPD(x); WPSH1(MEM[x]); continue; /* STA */ case 0x0D: WPOPD(y); WPOP1(x); MEM[y]=x; continue; /* LDD */ case 0x0E: WPOP1(x); WPSH1(dev_read(&br->dev,x)); continue; /* STD */ case 0x0F: WPOP1(y); WPOP1(x); sig=dev_write(&br->dev,y,x); SIGNAL(sig); /* ADD */ case 0x10: WPOP1(x); WSTV(-1)+=x; continue; /* SUB */ case 0x11: WPOP1(x); WSTV(-1)-=x; continue; /* INC */ case 0x12: WSTV(-1)+=1; continue; /* DEC */ case 0x13: WSTV(-1)-=1; continue; /* LTH */ case 0x14: WPOP1(y); WPOP1(x); WPSHB(xy); continue; /* EQU */ case 0x16: WPOP1(y); WPOP1(x); WPSHB(x==y); continue; /* NQK */ case 0x17: y=WSTV(-1); x=WSTV(-2); WPSHB(x!=y); continue; /* SHL */ case 0x18: WPOP1(y); WPOP1(x); WPSH1(x<>y); continue; /* ROL */ case 0x1A: WPOP1(y); WPOP1(x); WPSH1(ROL1(x,y)); continue; /* ROR */ case 0x1B: WPOP1(y); WPOP1(x); WPSH1(ROR1(x,y)); continue; /* IOR */ case 0x1C: WPOP1(x); WSTV(-1)|=x; continue; /* XOR */ case 0x1D: WPOP1(x); WSTV(-1)^=x; continue; /* AND */ case 0x1E: WPOP1(x); WSTV(-1)&=x; continue; /* NOT */ case 0x1F: WSTV(-1)=~WSTV(-1); continue; /* NOP */ case 0x20: continue; /* PSH: */ case 0x21: MPOP1(x); WPSH1(x); continue; /* POP: */ case 0x22: IP+=1; continue; /* CPY: */ case 0x23: MPOP1(x); RPSH1(x); WPSH1(x); continue; /* DUP: */ case 0x24: MPOP1(x); WPSH1(x); WPSH1(x); continue; /* OVR: */ case 0x25: MPOP1(y); WGET1(x); WPSH1(y); WPSH1(x); continue; /* SWP: */ case 0x26: MPOP1(y); WPOP1(x); WPSH1(y); WPSH1(x); continue; /* ROT: */ case 0x27: MPOP1(z); WPOP1(y); WPOP1(x); WPSH1(y); WPSH1(z); WPSH1(x); continue; /* JMP: */ case 0x28: MPOPD(x); IP=x; continue; /* JMS: */ case 0x29: MPOPD(x); RPSHD(IP); IP=x; continue; /* JCN: */ case 0x2A: MPOPD(y); WPOP1(x); if(x) IP=y; continue; /* JCS: */ case 0x2B: MPOPD(y); WPOP1(x); if(x) { RPSHD(IP); IP=y; } continue; /* LDA: */ case 0x2C: MPOPD(x); WPSH1(MEM[x]); continue; /* STA: */ case 0x2D: MPOPD(y); WPOP1(x); MEM[y]=x; continue; /* LDD: */ case 0x2E: MPOP1(x); WPSH1(dev_read(&br->dev,x)); continue; /* STD: */ case 0x2F: MPOP1(y); WPOP1(x); sig=dev_write(&br->dev,y,x); SIGNAL(sig); /* ADD: */ case 0x30: MPOP1(x); WSTV(-1)+=x; continue; /* SUB: */ case 0x31: MPOP1(x); WSTV(-1)-=x; continue; /* INC: */ case 0x32: MPOP1(x); WPSH1(x+1); continue; /* DEC: */ case 0x33: MPOP1(x); WPSH1(x-1); continue; /* LTH: */ case 0x34: MPOP1(y); WPOP1(x); WPSHB(xy); continue; /* EQU: */ case 0x36: MPOP1(y); WPOP1(x); WPSHB(x==y); continue; /* NQK: */ case 0x37: MPOP1(y); WGET1(x); WPSH1(y); WPSHB(x!=y); continue; /* SHL: */ case 0x38: MPOP1(y); WPOP1(x); WPSH1(x<>y); continue; /* ROL: */ case 0x3A: MPOP1(y); WPOP1(x); WPSH1(ROL1(x,y)); continue; /* ROR: */ case 0x3B: MPOP1(y); WPOP1(x); WPSH1(ROR1(x,y)); continue; /* IOR: */ case 0x3C: MPOP1(x); WSTV(-1)|=x; continue; /* XOR: */ case 0x3D: MPOP1(x); WSTV(-1)^=x; continue; /* AND: */ case 0x3E: MPOP1(x); WSTV(-1)&=x; continue; /* NOT: */ case 0x3F: MPOP1(x); WPSH1(~x); continue; /* DB1 */ case 0x40: return SIG_DB1; /* PSH* */ case 0x41: RPOP2(x,y); WPSH2(x,y); continue; /* POP* */ case 0x42: WST.p-=2; continue; /* CPY* */ case 0x43: RGET2(x,y); WPSH2(x,y); continue; /* DUP* */ case 0x44: WGET2(x,y); WPSH2(x,y); continue; /* OVR* */ case 0x45: WPOP2(y,z); WGET2(w,x); WPSH2(y,z); WPSH2(w,x); continue; /* SWP* */ case 0x46: WPOP2(y,z); WPOP2(w,x); WPSH2(y,z); WPSH2(w,x); continue; /* ROT* */ case 0x47: WPOP2(y,z); WPOP2(w,x); WPOP2(u,v); WPSH2(w,x); WPSH2(y,z); WPSH2(u,v); continue; /* JMP* */ case 0x48: WPOPD(x); IP=x; continue; /* JMS* */ case 0x49: WPOPD(x); RPSHD(IP); IP=x; continue; /* JCN* */ case 0x4A: WPOPD(y); WPOPD(x); if(x) IP=y; continue; /* JCS* */ case 0x4B: WPOPD(y); WPOPD(x); if(x) { RPSHD(IP); IP=y; } continue; /* LDA* */ case 0x4C: WPOPD(x); WPSH2(MEM[x], MEM[x+1]); continue; /* STA* */ case 0x4D: WPOPD(z); WPOP2(x,y); MEM[z]=x; MEM[z+1]=y; continue; /* LDD* */ case 0x4E: WPOP1(x); WPSH1(DGET1(x)); WPSH1(DGET1(x+1)); continue; /* STD* */ case 0x4F: WPOP1(z); WPOP2(x,y); sig=DSET2(z,x,y); SIGNAL(sig); /* ADD* */ case 0x50: WPOPD(y); WPOPD(x); WPSHD(x+y); continue; /* SUB* */ case 0x51: WPOPD(y); WPOPD(x); WPSHD(x-y); continue; /* INC* */ case 0x52: WPOPD(x); WPSHD(x+1); continue; /* DEC* */ case 0x53: WPOPD(x); WPSHD(x-1); continue; /* LTH* */ case 0x54: WPOPD(y); WPOPD(x); WPSHB(xy); continue; /* EQU* */ case 0x56: WPOP2(y,z); WPOP2(w,x); WPSHB(w==y && x==z); continue; /* NQK* */ case 0x57: z=WSTV(-1); y=WSTV(-2); x=WSTV(-3); w=WSTV(-4); WPSHB(w!=y || x!=z); continue; /* SHL* */ case 0x58: WPOP1(y); WPOPD(x); WPSHD(x<>y); continue; /* ROL* */ case 0x5A: WPOP1(y); WPOPD(x); WPSHD(ROLD(x,y)); continue; /* ROR* */ case 0x5B: WPOP1(y); WPOPD(x); WPSHD(RORD(x,y)); continue; /* IOR* */ case 0x5C: WPOP2(x,y); WSTV(-1)|=y; WSTV(-2)|=x; continue; /* XOR* */ case 0x5D: WPOP2(x,y); WSTV(-1)^=y; WSTV(-2)^=x; continue; /* AND* */ case 0x5E: WPOP2(x,y); WSTV(-1)&=y; WSTV(-2)&=x; continue; /* NOT* */ case 0x5F: WSTV(-1)=~WSTV(-1); WSTV(-2)=~WSTV(-2); continue; /* DB2 */ case 0x60: return SIG_DB2; /* PSH*: */ case 0x61: MPOP2(x,y); WPSH2(x,y); continue; /* POP*: */ case 0x62: IP+=2; continue; /* CPY*: */ case 0x63: MPOP2(x,y); RPSH2(x,y); WPSH2(x,y); continue; /* DUP*: */ case 0x64: MPOP2(x,y); WPSH2(x,y); WPSH2(x,y); continue; /* OVR*: */ case 0x65: MPOP2(y,z); WGET2(w,x); WPSH2(y,z); WPSH2(w,x); continue; /* SWP*: */ case 0x66: MPOP2(y,z); WPOP2(w,x); WPSH2(y,z); WPSH2(w,x); continue; /* ROT*: */ case 0x67: MPOP2(y,z); WPOP2(w,x); WPOP2(u,v); WPSH2(w,x); WPSH2(y,z); WPSH2(u,v); continue; /* JMP*: */ case 0x68: MPOPD(x); IP=x; continue; /* JMS*: */ case 0x69: MPOPD(x); RPSHD(IP); IP=x; continue; /* JCN*: */ case 0x6A: MPOPD(y); WPOPD(x); if(x) IP=y; continue; /* JCS*: */ case 0x6B: MPOPD(y); WPOPD(x); if(x) { RPSHD(IP); IP=y; } continue; /* LDA*: */ case 0x6C: MPOPD(x); WPSH2(MEM[x], MEM[x+1]); continue; /* STA*: */ case 0x6D: MPOPD(z); WPOP2(x,y); MEM[z]=x; MEM[z+1]=y; continue; /* LDD*: */ case 0x6E: MPOP1(x); WPSH1(DGET1(x)); WPSH1(DGET1(x+1)); continue; /* STD*: */ case 0x6F: MPOP1(z); WPOP2(x,y); sig=DSET2(z,x,y); SIGNAL(sig); /* ADD*: */ case 0x70: MPOPD(y); WPOPD(x); WPSHD(x+y); continue; /* SUB*: */ case 0x71: MPOPD(y); WPOPD(x); WPSHD(x-y); continue; /* INC*: */ case 0x72: MPOPD(x); WPSHD(x+1); continue; /* DEC*: */ case 0x73: MPOPD(x); WPSHD(x-1); continue; /* LTH*: */ case 0x74: MPOPD(y); WPOPD(x); WPSHB(xy); continue; /* EQU*: */ case 0x76: MPOP2(y,z); WPOP2(w,x); WPSHB(w==y && x==z); continue; /* NQK*: */ case 0x77: MPOP2(y,z); WGET2(w,x); WPSH2(y,z); WPSHB(w!=y || x!=z); continue; /* SHL*: */ case 0x78: MPOP1(y); WPOPD(x); WPSHD(x<>y); continue; /* ROL*: */ case 0x7A: MPOP1(y); WPOPD(x); WPSHD(ROLD(x,y)); continue; /* ROR*: */ case 0x7B: MPOP1(y); WPOPD(x); WPSHD(RORD(x,y)); continue; /* IOR*: */ case 0x7C: MPOP2(x,y); WSTV(-1)|=y; WSTV(-2)|=x; continue; /* XOR*: */ case 0x7D: MPOP2(x,y); WSTV(-1)^=y; WSTV(-2)^=x; continue; /* AND*: */ case 0x7E: MPOP2(x,y); WSTV(-1)&=y; WSTV(-2)&=x; continue; /* NOT*: */ case 0x7F: MPOP2(x,y); WPSH2(~x,~y); continue; /* DB3 */ case 0x80: return SIG_DB3; /* PSHr */ case 0x81: WPOP1(x); RPSH1(x); continue; /* POPr */ case 0x82: RST.p-=1; continue; /* CPYr */ case 0x83: WGET1(x); RPSH1(x); continue; /* DUPr */ case 0x84: RGET1(x); RPSH1(x); continue; /* OVRr */ case 0x85: RPOP1(y); RGET1(x); RPSH1(y); RPSH1(x); continue; /* SWPr */ case 0x86: RPOP1(y); RPOP1(x); RPSH1(y); RPSH1(x); continue; /* ROTr */ case 0x87: RPOP1(z); RPOP1(y); RPOP1(x); RPSH1(y); RPSH1(z); RPSH1(x); continue; /* JMPr */ case 0x88: RPOPD(x); IP=x; continue; /* JMSr */ case 0x89: RPOPD(x); WPSHD(IP); IP=x; continue; /* JCNr */ case 0x8A: RPOPD(y); RPOP1(x); if(x) IP=y; continue; /* JCSr */ case 0x8B: RPOPD(y); RPOP1(x); if(x) { WPSHD(IP); IP=y; } continue; /* LDAr */ case 0x8C: RPOPD(x); RPSH1(MEM[x]); continue; /* STAr */ case 0x8D: RPOPD(y); RPOP1(x); MEM[y]=x; continue; /* LDDr */ case 0x8E: RPOP1(x); RPSH1(dev_read(&br->dev,x)); continue; /* STDr */ case 0x8F: RPOP1(y); RPOP1(x); sig=dev_write(&br->dev,y,x); SIGNAL(sig); /* ADDr */ case 0x90: RPOP1(x); RSTV(-1)+=x; continue; /* SUBr */ case 0x91: RPOP1(x); RSTV(-1)-=x; continue; /* INCr */ case 0x92: RSTV(-1)+=1; continue; /* DECr */ case 0x93: RSTV(-1)-=1; continue; /* LTHr */ case 0x94: RPOP1(y); RPOP1(x); RPSHB(xy); continue; /* EQUr */ case 0x96: RPOP1(y); RPOP1(x); RPSHB(x==y); continue; /* NQKr */ case 0x97: y=RSTV(-1); x=RSTV(-2); RPSHB(x!=y); continue; /* SHLr */ case 0x98: RPOP1(y); RPOP1(x); RPSH1(x<>y); continue; /* ROLr */ case 0x9A: RPOP1(y); RPOP1(x); RPSH1(ROL1(x,y)); continue; /* RORr */ case 0x9B: RPOP1(y); RPOP1(x); RPSH1(ROR1(x,y)); continue; /* IORr */ case 0x9C: RPOP1(x); RSTV(-1)|=x; continue; /* XORr */ case 0x9D: RPOP1(x); RSTV(-1)^=x; continue; /* ANDr */ case 0x9E: RPOP1(x); RSTV(-1)&=x; continue; /* NOTr */ case 0x9F: RSTV(-1)=~RSTV(-1); continue; /* DB4 */ case 0xA0: return SIG_DB4; /* PSHr: */ case 0xA1: MPOP1(x); RPSH1(x); continue; /* POPr: */ case 0xA2: IP+=1; continue; /* CPYr: */ case 0xA3: MPOP1(x); WPSH1(x); RPSH1(x); continue; /* DUPr: */ case 0xA4: MPOP1(x); RPSH1(x); RPSH1(x); continue; /* OVRr: */ case 0xA5: MPOP1(y); RGET1(x); RPSH1(y); RPSH1(x); continue; /* SWPr: */ case 0xA6: MPOP1(y); RPOP1(x); RPSH1(y); RPSH1(x); continue; /* ROTr: */ case 0xA7: MPOP1(z); RPOP1(y); RPOP1(x); RPSH1(y); RPSH1(z); RPSH1(x); continue; /* JMPr: */ case 0xA8: MPOPD(x); IP=x; continue; /* JMSr: */ case 0xA9: MPOPD(x); WPSHD(IP); IP=x; continue; /* JCNr: */ case 0xAA: MPOPD(y); RPOP1(x); if(x) IP=y; continue; /* JCSr: */ case 0xAB: MPOPD(y); RPOP1(x); if(x) { WPSHD(IP); IP=y; } continue; /* LDAr: */ case 0xAC: MPOPD(x); RPSH1(MEM[x]); continue; /* STAr: */ case 0xAD: MPOPD(y); RPOP1(x); MEM[y]=x; continue; /* LDDr: */ case 0xAE: MPOP1(x); RPSH1(dev_read(&br->dev,x)); continue; /* STDr: */ case 0xAF: MPOP1(y); RPOP1(x); sig=dev_write(&br->dev,y,x); SIGNAL(sig); /* ADDr: */ case 0xB0: MPOP1(x); RSTV(-1)+=x; continue; /* SUBr: */ case 0xB1: MPOP1(x); RSTV(-1)-=x; continue; /* INCr: */ case 0xB2: MPOP1(x); RPSH1(x+1); continue; /* DECr: */ case 0xB3: MPOP1(x); RPSH1(x-1); continue; /* LTHr: */ case 0xB4: MPOP1(y); RPOP1(x); RPSHB(xy); continue; /* EQUr: */ case 0xB6: MPOP1(y); RPOP1(x); RPSHB(x==y); continue; /* NQKr: */ case 0xB7: MPOP1(y); RGET1(x); RPSH1(y); RPSHB(x!=y); continue; /* SHLr: */ case 0xB8: MPOP1(y); RPOP1(x); RPSH1(x<>y); continue; /* ROLr: */ case 0xBA: MPOP1(y); RPOP1(x); RPSH1(ROL1(x,y)); continue; /* RORr: */ case 0xBB: MPOP1(y); RPOP1(x); RPSH1(ROR1(x,y)); continue; /* IORr: */ case 0xBC: MPOP1(x); RSTV(-1)|=x; continue; /* XORr: */ case 0xBD: MPOP1(x); RSTV(-1)^=x; continue; /* ANDr: */ case 0xBE: MPOP1(x); RSTV(-1)&=x; continue; /* NOTr: */ case 0xBF: MPOP1(x); RPSH1(~x); continue; /* DB5 */ case 0xC0: return SIG_DB5; /* PSHr* */ case 0xC1: WPOP2(x,y); RPSH2(x,y); continue; /* POPr* */ case 0xC2: RST.p-=2; continue; /* CPYr* */ case 0xC3: WGET2(x,y); RPSH2(x,y); continue; /* DUPr* */ case 0xC4: RGET2(x,y); RPSH2(x,y); continue; /* OVRr* */ case 0xC5: RPOP2(y,z); RGET2(w,x); RPSH2(y,z); RPSH2(w,x); continue; /* SWPr* */ case 0xC6: RPOP2(y,z); RPOP2(w,x); RPSH2(y,z); RPSH2(w,x); continue; /* ROTr* */ case 0xC7: RPOP2(y,z); RPOP2(w,x); RPOP2(u,v); RPSH2(w,x); RPSH2(y,z); RPSH2(u,v); continue; /* JMPr* */ case 0xC8: RPOPD(x); IP=x; continue; /* JMSr* */ case 0xC9: RPOPD(x); WPSHD(IP); IP=x; continue; /* JCNr* */ case 0xCA: RPOPD(y); RPOPD(x); if(x) IP=y; continue; /* JCSr* */ case 0xCB: RPOPD(y); RPOPD(x); if(x) { WPSHD(IP); IP=y; } continue; /* LDAr* */ case 0xCC: RPOPD(x); RPSH2(MEM[x], MEM[x+1]); continue; /* STAr* */ case 0xCD: RPOPD(z); RPOP2(x,y); MEM[z]=x; MEM[z+1]=y; continue; /* LDDr* */ case 0xCE: RPOP1(x); RPSH1(DGET1(x)); RPSH1(DGET1(x+1)); continue; /* STDr* */ case 0xCF: RPOP1(z); RPOP2(x,y); sig=DSET2(z,x,y); SIGNAL(sig); /* ADDr* */ case 0xD0: RPOPD(y); RPOPD(x); RPSHD(x+y); continue; /* SUBr* */ case 0xD1: RPOPD(y); RPOPD(x); RPSHD(x-y); continue; /* INCr* */ case 0xD2: RPOPD(x); RPSHD(x+1); continue; /* DECr* */ case 0xD3: RPOPD(x); RPSHD(x-1); continue; /* LTHr* */ case 0xD4: RPOPD(y); RPOPD(x); RPSHB(xy); continue; /* EQUr* */ case 0xD6: RPOP2(y,z); RPOP2(w,x); RPSHB(w==y && x==z); continue; /* NQKr* */ case 0xD7: z=RSTV(-1); y=RSTV(-2); x=RSTV(-3); w=RSTV(-4); RPSHB(w!=y || x!=z); continue; /* SHLr* */ case 0xD8: RPOP1(y); RPOPD(x); RPSHD(x<>y); continue; /* ROLr* */ case 0xDA: RPOP1(y); RPOPD(x); RPSHD(ROLD(x,y)); continue; /* RORr* */ case 0xDB: RPOP1(y); RPOPD(x); RPSHD(RORD(x,y)); continue; /* IORr* */ case 0xDC: RPOP2(x,y); RSTV(-1)|=y; RSTV(-2)|=x; continue; /* XORr* */ case 0xDD: RPOP2(x,y); RSTV(-1)^=y; RSTV(-2)^=x; continue; /* ANDr* */ case 0xDE: RPOP2(x,y); RSTV(-1)&=y; RSTV(-2)&=x; continue; /* NOTr* */ case 0xDF: RSTV(-1)=~RSTV(-1); RSTV(-2)=~RSTV(-2); continue; /* DB6 */ case 0xE0: return SIG_DB6; /* PSHr*: */ case 0xE1: MPOP2(x,y); RPSH2(x,y); continue; /* POPr*: */ case 0xE2: IP+=2; continue; /* CPYr*: */ case 0xE3: MPOP2(x,y); WPSH2(x,y); RPSH2(x,y); continue; /* DUPr*: */ case 0xE4: MPOP2(x,y); RPSH2(x,y); RPSH2(x,y); continue; /* OVRr*: */ case 0xE5: MPOP2(y,z); RGET2(w,x); RPSH2(y,z); RPSH2(w,x); continue; /* SWPr*: */ case 0xE6: MPOP2(y,z); RPOP2(w,x); RPSH2(y,z); RPSH2(w,x); continue; /* ROTr*: */ case 0xE7: MPOP2(y,z); RPOP2(w,x); RPOP2(u,v); RPSH2(w,x); RPSH2(y,z); RPSH2(u,v); continue; /* JMPr*: */ case 0xE8: MPOPD(x); IP=x; continue; /* JMSr*: */ case 0xE9: MPOPD(x); WPSHD(IP); IP=x; continue; /* JCNr*: */ case 0xEA: MPOPD(y); RPOPD(x); if(x) IP=y; continue; /* JCSr*: */ case 0xEB: MPOPD(y); RPOPD(x); if(x) { WPSHD(IP); IP=y; } continue; /* LDAr*: */ case 0xEC: MPOPD(x); RPSH2(MEM[x], MEM[x+1]); continue; /* STAr*: */ case 0xED: MPOPD(z); RPOP2(x,y); MEM[z]=x; MEM[z+1]=y; continue; /* LDDr*: */ case 0xEE: MPOP1(x); RPSH1(DGET1(x)); RPSH1(DGET1(x+1)); continue; /* STDr*: */ case 0xEF: MPOP1(z); RPOP2(x,y); sig=DSET2(z,x,y); SIGNAL(sig); /* ADDr*: */ case 0xF0: MPOPD(y); RPOPD(x); RPSHD(x+y); continue; /* SUBr*: */ case 0xF1: MPOPD(y); RPOPD(x); RPSHD(x-y); continue; /* INCr*: */ case 0xF2: MPOPD(x); RPSHD(x+1); continue; /* DECr*: */ case 0xF3: MPOPD(x); RPSHD(x-1); continue; /* LTHr*: */ case 0xF4: MPOPD(y); RPOPD(x); RPSHB(xy); continue; /* EQUr*: */ case 0xF6: MPOP2(y,z); RPOP2(w,x); RPSHB(w==y && x==z); continue; /* NQKr*: */ case 0xF7: MPOP2(y,z); RGET2(w,x); RPSH2(y,z); RPSHB(w!=y || x!=z); continue; /* SHLr*: */ case 0xF8: MPOP1(y); RPOPD(x); RPSHD(x<>y); continue; /* ROLr*: */ case 0xFA: MPOP1(y); RPOPD(x); RPSHD(ROLD(x,y)); continue; /* RORr*: */ case 0xFB: MPOP1(y); RPOPD(x); RPSHD(RORD(x,y)); continue; /* IORr*: */ case 0xFC: MPOP2(x,y); RSTV(-1)|=y; RSTV(-2)|=x; continue; /* XORr*: */ case 0xFD: MPOP2(x,y); RSTV(-1)^=y; RSTV(-2)^=x; continue; /* ANDr*: */ case 0xFE: MPOP2(x,y); RSTV(-1)&=y; RSTV(-2)&=x; continue; /* NOTr*: */ case 0xFF: MPOP2(x,y); RPSH2(~x,~y); continue; } } return SIG_NONE; } // Print a stack to the debug console. void debug_print_stack(Stack *stack) { for (int i=0; ip; i++) { printf("%02x ", stack->mem[i]); } } // Print the state of a Bedrock instance to the debug console. void debug_print_state(Bedrock *br) { printf("\nP:0x%04x", br->ip); printf("\nW:"); debug_print_stack(&br->wst); printf("\nR:"); debug_print_stack(&br->rst); printf("\n"); } // Print the state of a Bedrock instance to the debug console. void debug_print_brief(Bedrock *br) { printf("[%02X %02X]", br->wst.p, br->rst.p); } // Assert the state of a Bedrock instance, print to the debug console.. void debug_print_assert(Bedrock *br) { if (br->wst.mem[0] == 0xff && br->wst.p == 1 && br->rst.p == 0) { printf("."); } else { printf("X"); } } // Run a Bedrock instance for a number of cycles. void br_run(Bedrock *br) { if (br->alive && br->awake) { switch (br_eval(br, 50000)) { case SIG_HALT: br->alive = false; ndsscreen_clear(br->dev.screen.nds); return; case SIG_SLEEP: br->awake = false; return; case SIG_DB1: debug_print_state(br); return; case SIG_DB2: debug_print_brief(br); return; case SIG_DB4: debug_print_assert(br); return; default: return; } } }