diff --git a/core/cpu.c b/core/cpu.c index 375dbb5..917a409 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -6,73 +6,89 @@ /********************************* Constants *********************************/ /* Operation IDs */ -#define CPU_HALTING 0 -#define CPU_FATAL 1 -#define CPU_FETCH 2 -#define CPU_ILLEGAL 3 -#define CPU_BITSTRING 4 -#define CPU_FLOATENDO 5 -#define CPU_DOWN 6 -#define CPU_BITWISE 7 -#define CPU_UP 8 -#define CPU_ADD 9 -#define CPU_ADDF_S 10 -#define CPU_ADDI 11 -#define CPU_AND 12 +#define CPU_EXCEPTION 0 +#define CPU_HALTING 1 +#define CPU_FATAL 2 +#define CPU_FETCH 3 +#define CPU_ILLEGAL 4 +#define CPU_BITSTRING 5 +#define CPU_FLOATENDO 6 +#define CPU_ADD_IMM 7 +#define CPU_ADD_REG 8 +#define CPU_ADDF_S 9 +#define CPU_ADDI 10 +#define CPU_AND 11 +#define CPU_ANDBSU 12 #define CPU_ANDI 13 -#define CPU_BCOND 14 -#define CPU_CAXI 15 -#define CPU_CLI 16 -#define CPU_CMP 17 -#define CPU_CMPF_S 18 -#define CPU_CVT_SW 19 -#define CPU_CVT_WS 20 -#define CPU_DIV 21 -#define CPU_DIVF_S 22 -#define CPU_DIVU 23 -#define CPU_HALT 24 -#define CPU_IN_B 25 -#define CPU_IN_H 26 -#define CPU_IN_W 27 -#define CPU_JAL 28 -#define CPU_JMP 29 -#define CPU_JR 30 -#define CPU_LD_B 31 -#define CPU_LD_H 32 -#define CPU_LD_W 33 -#define CPU_LDSR 34 -#define CPU_MOV 35 -#define CPU_MOVEA 36 -#define CPU_MOVHI 37 -#define CPU_MPYHW 38 -#define CPU_MUL 39 -#define CPU_MULF_S 40 -#define CPU_MULU 41 -#define CPU_NOT 42 -#define CPU_OR 43 -#define CPU_ORI 44 -#define CPU_OUT_B 45 -#define CPU_OUT_H 46 -#define CPU_OUT_W 47 -#define CPU_RETI 48 -#define CPU_REV 49 -#define CPU_SAR 50 -#define CPU_SEI 51 -#define CPU_SETF 52 -#define CPU_SHL 53 -#define CPU_SHR 54 -#define CPU_ST_B 55 -#define CPU_ST_H 56 -#define CPU_ST_W 57 -#define CPU_STSR 58 -#define CPU_SUB 59 -#define CPU_SUBF_S 60 -#define CPU_TRAP 61 -#define CPU_TRNC_SW 62 -#define CPU_XB 63 -#define CPU_XH 64 -#define CPU_XOR 65 -#define CPU_XORI 66 +#define CPU_ANDNBSU 14 +#define CPU_BCOND 15 +#define CPU_CAXI 16 +#define CPU_CLI 17 +#define CPU_CMP_IMM 18 +#define CPU_CMP_REG 19 +#define CPU_CMPF_S 20 +#define CPU_CVT_SW 21 +#define CPU_CVT_WS 22 +#define CPU_DIV 23 +#define CPU_DIVF_S 24 +#define CPU_DIVU 25 +#define CPU_HALT 26 +#define CPU_IN_B 27 +#define CPU_IN_H 28 +#define CPU_IN_W 29 +#define CPU_JAL 30 +#define CPU_JMP 31 +#define CPU_JR 32 +#define CPU_LD_B 33 +#define CPU_LD_H 34 +#define CPU_LD_W 35 +#define CPU_LDSR 36 +#define CPU_MOV_IMM 37 +#define CPU_MOV_REG 38 +#define CPU_MOVBSU 39 +#define CPU_MOVEA 40 +#define CPU_MOVHI 41 +#define CPU_MPYHW 42 +#define CPU_MUL 43 +#define CPU_MULF_S 44 +#define CPU_MULU 45 +#define CPU_NOT 46 +#define CPU_NOTBSU 47 +#define CPU_OR 48 +#define CPU_ORBSU 49 +#define CPU_ORI 50 +#define CPU_ORNBSU 51 +#define CPU_OUT_B 52 +#define CPU_OUT_H 53 +#define CPU_OUT_W 54 +#define CPU_RETI 55 +#define CPU_REV 56 +#define CPU_SAR_IMM 57 +#define CPU_SAR_REG 58 +#define CPU_SCH0BSD 59 +#define CPU_SCH0BSU 60 +#define CPU_SCH1BSD 61 +#define CPU_SCH1BSU 62 +#define CPU_SEI 63 +#define CPU_SETF 64 +#define CPU_SHL_IMM 65 +#define CPU_SHL_REG 66 +#define CPU_SHR_IMM 67 +#define CPU_SHR_REG 68 +#define CPU_ST_B 69 +#define CPU_ST_H 70 +#define CPU_ST_W 71 +#define CPU_STSR 72 +#define CPU_SUB 73 +#define CPU_SUBF_S 74 +#define CPU_TRAP 75 +#define CPU_TRNC_SW 76 +#define CPU_XB 77 +#define CPU_XH 78 +#define CPU_XOR 79 +#define CPU_XORBSU 80 +#define CPU_XORI 81 +#define CPU_XORNBSU 82 /* Abstract operand types */ #define CPU_IMP(x) -x-1 @@ -125,30 +141,30 @@ static const uint8_t INST_LENGTHS[] = { /* Opdefs by opcode */ static const uint8_t OPDEFS[] = { - CPU_MOV , CPU_ADD , CPU_SUB , CPU_CMP , /* 000000 */ - CPU_SHL , CPU_SHR , CPU_JMP , CPU_SAR , - CPU_MUL , CPU_DIV , CPU_MULU , CPU_DIVU , - CPU_OR , CPU_AND , CPU_XOR , CPU_NOT , - CPU_MOV , CPU_ADD , CPU_SETF , CPU_CMP , /* 010000 */ - CPU_SHL , CPU_SHR , CPU_CLI , CPU_SAR , - CPU_TRAP , CPU_RETI , CPU_HALT , CPU_ILLEGAL , - CPU_LDSR , CPU_STSR , CPU_SEI , CPU_BITSTRING, - CPU_BCOND, CPU_BCOND, CPU_BCOND , CPU_BCOND , /* 100000 */ - CPU_BCOND, CPU_BCOND, CPU_BCOND , CPU_BCOND , - CPU_MOVEA, CPU_ADDI , CPU_JR , CPU_JAL , - CPU_ORI , CPU_ANDI , CPU_XORI , CPU_MOVHI , - CPU_LD_B , CPU_LD_H , CPU_ILLEGAL , CPU_LD_W , /* 110000 */ - CPU_ST_B , CPU_ST_H , CPU_ILLEGAL , CPU_ST_W , - CPU_IN_B , CPU_IN_H , CPU_CAXI , CPU_IN_W , - CPU_OUT_B, CPU_OUT_H, CPU_FLOATENDO, CPU_OUT_W + CPU_MOV_REG, CPU_ADD_REG, CPU_SUB , CPU_CMP_REG , /* 000000 */ + CPU_SHL_REG, CPU_SHR_REG, CPU_JMP , CPU_SAR_REG , + CPU_MUL , CPU_DIV , CPU_MULU , CPU_DIVU , + CPU_OR , CPU_AND , CPU_XOR , CPU_NOT , + CPU_MOV_IMM, CPU_ADD_IMM, CPU_SETF , CPU_CMP_IMM , /* 010000 */ + CPU_SHL_IMM, CPU_SHR_IMM, CPU_CLI , CPU_SAR_IMM , + CPU_TRAP , CPU_RETI , CPU_HALT , CPU_ILLEGAL , + CPU_LDSR , CPU_STSR , CPU_SEI , CPU_BITSTRING, + CPU_BCOND , CPU_BCOND , CPU_BCOND , CPU_BCOND , /* 100000 */ + CPU_BCOND , CPU_BCOND , CPU_BCOND , CPU_BCOND , + CPU_MOVEA , CPU_ADDI , CPU_JR , CPU_JAL , + CPU_ORI , CPU_ANDI , CPU_XORI , CPU_MOVHI , + CPU_LD_B , CPU_LD_H , CPU_ILLEGAL , CPU_LD_W , /* 110000 */ + CPU_ST_B , CPU_ST_H , CPU_ILLEGAL , CPU_ST_W , + CPU_IN_B , CPU_IN_H , CPU_CAXI , CPU_IN_W , + CPU_OUT_B , CPU_OUT_H , CPU_FLOATENDO, CPU_OUT_W }; /* Opdefs by bit string sub-opcode */ static const uint8_t OPDEFS_BITSTRING[] = { - CPU_UP , CPU_DOWN , CPU_UP , CPU_DOWN , /* 00000 */ + CPU_SCH0BSU, CPU_SCH0BSD, CPU_SCH1BSU, CPU_SCH1BSD, /* 00000 */ CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, - CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, /* 01000 */ - CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, + CPU_ORBSU , CPU_ANDBSU , CPU_XORBSU , CPU_MOVBSU , /* 01000 */ + CPU_ORNBSU , CPU_ANDNBSU, CPU_XORNBSU, CPU_NOTBSU , CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 10000 */ CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 11000 */ @@ -350,6 +366,31 @@ static int cpuFetch(VB *sim) { /**************************** Instruction Helpers ****************************/ +/* Parse the immediate 4-bit condition value */ +static int32_t cpuGetCond(VB *sim) { + return sim->cpu.code[0] >> 9 & 15; +} + +/* Parse the 9-bit displacement value */ +static int32_t cpuGetDisp9(VB *sim) { + return SignExtend(sim->cpu.code[0], 9); +} + +/* Parse the 26-bit displacement value */ +static int32_t cpuGetDisp26(VB *sim) { + return SignExtend((int32_t) sim->cpu.code[0] << 16 | sim->cpu.code[1], 26); +} + +/* Parse the immediate 5-bit sign-extended value */ +static int32_t cpuGetImm5S(VB *sim) { + return SignExtend(sim->cpu.code[0], 5); +} + +/* Parse the immediate 5-bit zero-filled value */ +static int32_t cpuGetImm5U(VB *sim) { + return sim->cpu.code[0] & 31; +} + /* Parse the immediate 16-bit sign-extended value */ static int32_t cpuGetImm16S(VB *sim) { return SignExtend(sim->cpu.code[1], 16); @@ -365,6 +406,11 @@ static int32_t cpuGetReg1(VB *sim) { return sim->cpu.program[sim->cpu.code[0] & 31]; } +/* Resolve the operand value for reg2 */ +static int32_t cpuGetReg2(VB *sim) { + return sim->cpu.program[sim->cpu.code[0] >> 5 & 31]; +} + /* Supply an operand value for reg2 */ static void cpuSetReg2(VB *sim, int32_t value) { int reg2 = sim->cpu.code[0] >> 5 & 31; @@ -372,145 +418,12 @@ static void cpuSetReg2(VB *sim, int32_t value) { sim->cpu.program[reg2] = value; } -/* Memory access instruction */ -static int cpuLD_IN(VB *sim, int type) { - switch (sim->cpu.step) { - - case 0: - auxData.address = cpuGetReg1(sim) + cpuGetImm16S(sim); - /* Fallthrough */ - - case 1: - - /* Read the value from memory */ - if (cpuRead(sim, auxData.address, type, &auxData.value)) { - sim->cpu.step = 1; - return 1; - } - - /* Update state */ - sim->cpu.clocks += cpuClocks(1); - - /* Wait for clocks taken */ - sim->cpu.step = 2; - return 0; - - case 2: - cpuSetReg2(sim, auxData.value); - sim->cpu.operation = CPU_FETCH; - sim->cpu.nextPC += sim->cpu.pc + 4; - sim->cpu.step = 0; - } - return 0; -} - - - -/************************** Instruction Operations ***************************/ - -/* IN.B */ -static int cpuIN_B(VB *sim) { - return cpuLD_IN(sim, VB_U8); -} - -/* IN.H */ -static int cpuIN_H(VB *sim) { - return cpuLD_IN(sim, VB_U16); -} - -/* IN.W */ -static int cpuIN_W(VB *sim) { - return cpuLD_IN(sim, VB_S32); -} - -/* JMP */ -static int cpuJMP(VB *sim) { - sim->cpu.nextPC = cpuGetReg1(sim) & 0xFFFFFFFE; - sim->cpu.clocks += cpuClocks(3); +/* Advance to the next instruction */ +static void cpuAdvance(VB *sim, uint32_t clocks) { + sim->cpu.clocks += clocks; sim->cpu.operation = CPU_FETCH; - /* TODO: Clear prefetch buffer */ - return 0; -} - -/* LD.B */ -static int cpuLD_B(VB *sim) { - return cpuLD_IN(sim, VB_S8); -} - -/* LD.H */ -static int cpuLD_H(VB *sim) { - return cpuLD_IN(sim, VB_S16); -} - -/* LD.W */ -static int cpuLD_W(VB *sim) { - return cpuLD_IN(sim, VB_S32); -} - -/* MOVEA */ -static int cpuMOVEA(VB *sim) { - cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim)); - sim->cpu.clocks += cpuClocks(1); - sim->cpu.operation = CPU_FETCH; - sim->cpu.nextPC = sim->cpu.pc + 4; - return 0; -} - -/* MOVHI */ -static int cpuMOVHI(VB *sim) { - cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16)); - sim->cpu.clocks += cpuClocks(1); - sim->cpu.operation = CPU_FETCH; - sim->cpu.nextPC = sim->cpu.pc + 4; - return 0; -} - - - -/***************************** Library Functions *****************************/ - -/* Process component */ -static int cpuEmulate(VB *sim, uint32_t clocks) { - int brk; - - /* Process until there are clocks to wait */ - for (;;) { - - /* The next event is after the time remaining */ - if (sim->cpu.clocks > clocks) { - sim->cpu.clocks -= clocks; - return 0; - } - - /* Advance forward the CPU's number of clocks */ - if (sim->cpu.clocks != 0) { - clocks -= sim->cpu.clocks; - sim->cpu.clocks = 0; - } - - /* Processing by operation ID */ - switch (sim->cpu.operation) { - case CPU_FETCH: brk = cpuFetch(sim); break; - - case CPU_IN_B : brk = cpuIN_B (sim); break; - case CPU_IN_H : brk = cpuIN_H (sim); break; - case CPU_IN_W : brk = cpuIN_W (sim); break; - case CPU_JMP : brk = cpuJMP (sim); break; - case CPU_LD_B : brk = cpuLD_B (sim); break; - case CPU_LD_H : brk = cpuLD_H (sim); break; - case CPU_LD_W : brk = cpuLD_W (sim); break; - case CPU_MOVEA: brk = cpuMOVEA(sim); break; - case CPU_MOVHI: brk = cpuMOVHI(sim); break; - - default: return -1; /* TODO: Temporary for debugging */ - } - - /* A callback requested a break */ - if (brk) - return 1; - } - - return 0; + sim->cpu.nextPC = sim->cpu.pc + (sim->cpu.length << 1); + sim->cpu.step = 0; } /* Retrieve the value of a system register */ @@ -551,7 +464,8 @@ static uint32_t cpuGetSystemRegister(VB *sim, int index) { } /* Specify a new value for a system register */ -static uint32_t cpuSetSystemRegister(VB*sim,int index,uint32_t value,int debug){ +static uint32_t cpuSetSystemRegister(VB*sim, + int index, uint32_t value, int debug) { switch (index) { case VB_ADTRE: return sim->cpu.adtre = value & 0xFFFFFFFE; case VB_CHCW : @@ -597,6 +511,767 @@ static uint32_t cpuSetSystemRegister(VB*sim,int index,uint32_t value,int debug){ return 0x00000000; /* All others */ } +/* Addition common processing */ +static int32_t cpuAdd(VB *sim, int32_t b) { + int32_t a = cpuGetReg2(sim); + int32_t c = a + b; + sim->cpu.psw.cy = (uint32_t) c < (uint32_t) a; + sim->cpu.psw.ov = (~(a ^ b) & (a ^ c)) < 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Bitwise common processing */ +static int32_t cpuBitwise(VB *sim, int32_t c) { + sim->cpu.psw.ov = 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Test a condition */ +static int cpuCondition(VB *sim, int id) { + switch (id) { + case 0: return sim->cpu.psw.ov; + case 1: return sim->cpu.psw.cy; + case 2: return sim->cpu.psw.z; + case 3: return sim->cpu.psw.cy | sim->cpu.psw.z; + case 4: return sim->cpu.psw.s; + case 5: return 1; + case 6: return sim->cpu.psw.ov ^ sim->cpu.psw.s; + case 7: return (sim->cpu.psw.ov ^ sim->cpu.psw.s) | sim->cpu.psw.z; + } + return !cpuCondition(sim, id & 7); +} + +/* Jump and branch common processing */ +static void cpuJump(VB *sim, uint32_t address) { + sim->cpu.clocks += cpuClocks(3); + sim->cpu.operation = CPU_FETCH; + sim->cpu.nextPC = address & 0xFFFFFFFE; + sim->cpu.step = 0; + /* TODO: Clear prefetch buffer */ +} + +/* Arithmetic right shift common processing */ +static int32_t cpuShiftArithmetic(VB *sim, int32_t b) { + int32_t a = cpuGetReg2(sim); + #ifndef VB_SIGNED_PROPAGATE + int32_t c = b == 0 ? a : SignExtend(a >> b, 32 - b); + #else + int32_t c = a >> b; + #endif + sim->cpu.psw.cy = b == 0 ? 0 : a >> (b - 1) & 1; + sim->cpu.psw.ov = 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Left shift common processing */ +static int32_t cpuShiftLeft(VB *sim, int32_t b) { + int32_t a = cpuGetReg2(sim); + int32_t c = (uint32_t) a << b; + sim->cpu.psw.cy = b == 0 ? 0 : a >> (32 - b) & 1; + sim->cpu.psw.ov = 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Logical right shift common processing */ +static int32_t cpuShiftRight(VB *sim, int32_t b) { + int32_t a = cpuGetReg2(sim); + int32_t c = a >> b & (uint32_t) 0xFFFFFFFF << (32 - b); + sim->cpu.psw.cy = b == 0 ? 0 : a >> (b - 1) & 1; + sim->cpu.psw.ov = 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Subtraction common processing */ +static int32_t cpuSubtract(VB *sim, int32_t b) { + int32_t a = cpuGetReg2(sim); + int32_t c = a - b; + sim->cpu.psw.cy = (uint32_t) a < (uint32_t) b; + sim->cpu.psw.ov = ((a ^ b) & (a ^ c)) < 0; + sim->cpu.psw.s = c < 0; + sim->cpu.psw.z = c == 0; + return c; +} + +/* Memory load/input instruction */ +static int cpuLD_IN(VB *sim, int type) { + switch (sim->cpu.step) { + + case 0: + auxData.address = cpuGetReg1(sim) + cpuGetImm16S(sim); + /* Fallthrough */ + + case 1: + + /* Read the value from memory */ + if (cpuRead(sim, auxData.address, type, &auxData.value)) { + sim->cpu.step = 1; + return 1; + } + + /* Update state */ + sim->cpu.clocks += cpuClocks(1); + + /* Wait for clocks taken */ + sim->cpu.step = 2; + return 0; + + case 2: + cpuSetReg2(sim, auxData.value); + cpuAdvance(sim, cpuClocks(4)); /* TODO: Research */ + } + return 0; +} + +/* Memory store/output instruction */ +static int cpuST_OUT(VB *sim, int type) { + switch (sim->cpu.step) { + + case 0: + auxData.address = cpuGetReg1(sim) + cpuGetImm16S(sim); + /* Fallthrough */ + + case 1: + + /* Write the value to memory */ + if (cpuWrite(sim, auxData.address, type, cpuGetReg2(sim))) { + sim->cpu.step = 1; + return 1; + } + + /* Update state */ + sim->cpu.clocks += cpuClocks(1); + + /* Wait for clocks taken */ + sim->cpu.step = 2; + return 0; + + case 2: + cpuSetReg2(sim, auxData.value); + cpuAdvance(sim, cpuClocks(3)); /* TODO: Research */ + } + return 0; +} + + + +/************************** Instruction Operations ***************************/ + +/* ADD immediate */ +static int cpuADDImm(VB *sim) { + cpuSetReg2(sim, cpuAdd(sim, cpuGetImm5S(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* ADD register */ +static int cpuADDReg(VB *sim) { + cpuSetReg2(sim, cpuAdd(sim, cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* ADDI */ +static int cpuADDI(VB *sim) { + cpuSetReg2(sim, cpuAdd(sim, cpuGetImm16S(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* AND */ +static int cpuAND(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* ANDI */ +static int cpuANDI(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetImm16U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* BCOND */ +static int cpuBCOND(VB *sim) { + if (cpuCondition(sim, cpuGetCond(sim))) + cpuJump(sim, sim->cpu.pc + cpuGetDisp9(sim)); + else cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* CAXI */ +static int cpuCAXI(VB *sim) { + switch (sim->cpu.step) { + + case 0: + auxData.address = cpuGetReg1(sim) + cpuGetImm16S(sim); + /* Fallthrough */ + + case 1: + + /* Read the compare value */ + if (cpuRead(sim, auxData.address, VB_S32, &auxData.value)) { + sim->cpu.step = 1; + return 1; + } + + /* Update state */ + sim->cpu.clocks += cpuClocks(1); /* TODO: Research */ + cpuSubtract(sim, auxData.value); + if (sim->cpu.psw.z) + auxData.value = sim->cpu.program[30]; + + /* Wait for clocks taken */ + sim->cpu.step = 2; + return 0; + + case 2: + + /* Write the exchange value */ + if (cpuWrite(sim, auxData.address, VB_S32, auxData.value)) + return 1; + + /* Update state */ + cpuSetReg2(sim, auxData.value); + cpuAdvance(sim, cpuClocks(25)); /* TODO: Research */ + } + return 0; +} + +/* CLI */ +static int cpuCLI(VB *sim) { + sim->cpu.psw.id = 0; + cpuAdvance(sim, cpuClocks(12)); + return 0; +} + +/* CMP immediate */ +static int cpuCMPImm(VB *sim) { + cpuSubtract(sim, cpuGetImm5S(sim)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* CMP register */ +static int cpuCMPReg(VB *sim) { + cpuSubtract(sim, cpuGetReg1(sim)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* DIV */ +static int cpuDIV(VB *sim) { + int32_t a; /* Dividend */ + int32_t b; /* Divisor */ + int32_t c; /* Remainder */ + int32_t d; /* Quotient */ + #ifdef VB_DIV_GENERIC + int sa; /* Sign of a */ + int sb; /* Sign of b */ + #endif + + /* Zero division */ + b = cpuGetReg1(sim); + if (b == 0) { + sim->cpu.exception = 0xFF80; + sim->cpu.operation = CPU_EXCEPTION; + /* TODO: Research clocks */ + return 0; + } + + /* Compute results */ + a = cpuGetReg2(sim); + sim->cpu.psw.ov = (uint32_t) a == (uint32_t) 0x80000000 && b == -1; + #ifndef VB_DIV_GENERIC + c = a % b; + d = a / b; + #else + + /* Do not divide */ + if (sim->cpu.psw.ov) { + c = 0; + d = a; + } + + /* Perform division */ + else { + + /* Take signs and absolute values of operands */ + sa = a < 0; + if (sa) + a = -a; + sb = b < 0; + if (sb) + b = -b; + + /* Compute results */ + c = (uint32_t) a % (uint32_t) b; + if (sa) + c = -c; + d = (uint32_t) a / (uint32_t) b; + if (sa ^ sb) + d = -d; + } + + #endif + sim->cpu.program[30] = c; + cpuSetReg2(sim, d); + + /* Flags */ + sim->cpu.psw.s = d < 0; + sim->cpu.psw.z = d == 0; + cpuAdvance(sim, cpuClocks(38)); + return 0; +} + +/* DIVU */ +static int cpuDIVU(VB *sim) { + uint32_t a; /* Dividend */ + uint32_t b; /* Divisor */ + int32_t c; /* Remainder */ + int32_t d; /* Quotient */ + + /* Zero division */ + b = cpuGetReg1(sim); + if (b == 0) { + sim->cpu.exception = 0xFF80; + sim->cpu.operation = CPU_EXCEPTION; + /* TODO: Research clocks */ + return 0; + } + + /* Compute results */ + a = cpuGetReg2(sim); + c = a % b; + d = a / b; + sim->cpu.program[30] = c; + cpuSetReg2(sim, d); + + /* Flags */ + sim->cpu.psw.ov = 0; + sim->cpu.psw.s = d < 0; + sim->cpu.psw.z = d == 0; + cpuAdvance(sim, cpuClocks(36)); + return 0; +} + +/* HALT */ +static int cpuHALT(VB *sim) { + sim->cpu.operation = CPU_HALTING; + /* TODO: Research clocks */ + return 0; +} + +/* IN.B */ +static int cpuIN_B(VB *sim) { + return cpuLD_IN(sim, VB_U8); +} + +/* IN.H */ +static int cpuIN_H(VB *sim) { + return cpuLD_IN(sim, VB_U16); +} + +/* IN.W */ +static int cpuIN_W(VB *sim) { + return cpuLD_IN(sim, VB_S32); +} + +/* JAL */ +static int cpuJAL(VB *sim) { + sim->cpu.program[31] = sim->cpu.pc + 4; + cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim)); + return 0; +} + +/* JMP */ +static int cpuJMP(VB *sim) { + cpuJump(sim, cpuGetReg1(sim)); + return 0; +} + +/* JR */ +static int cpuJR(VB *sim) { + cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim)); + return 0; +} + +/* LD.B */ +static int cpuLD_B(VB *sim) { + return cpuLD_IN(sim, VB_S8); +} + +/* LD.H */ +static int cpuLD_H(VB *sim) { + return cpuLD_IN(sim, VB_S16); +} + +/* LD.W */ +static int cpuLD_W(VB *sim) { + return cpuLD_IN(sim, VB_S32); +} + +/* LDSR */ +static int cpuLDSR(VB *sim) { + cpuSetSystemRegister(sim, cpuGetImm5U(sim), cpuGetReg2(sim), 0); + cpuAdvance(sim, cpuClocks(8)); + return 0; +} + +/* MOV immediate */ +static int cpuMOVImm(VB *sim) { + cpuSetReg2(sim, cpuGetImm5S(sim)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* MOV register */ +static int cpuMOVReg(VB *sim) { + cpuSetReg2(sim, cpuGetReg1(sim)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* MOVEA */ +static int cpuMOVEA(VB *sim) { + cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* MOVHI */ +static int cpuMOVHI(VB *sim) { + cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* MPYHW */ +static int cpuMPYHW(VB *sim) { + cpuSetReg2(sim, cpuGetReg2(sim) * SignExtend(cpuGetReg1(sim), 17)); + return 0; +} + +/* MUL */ +static int cpuMUL(VB *sim) { + int64_t a = cpuGetReg2(sim); + int64_t b = cpuGetReg1(sim); + int64_t c = a * b; + int32_t d = c; + sim->cpu.program[30] = c >> 32; + cpuSetReg2(sim, d); + sim->cpu.psw.ov = d != c; + sim->cpu.psw.s = d < 0; + sim->cpu.psw.z = d == 0; + cpuAdvance(sim, 13); + return 0; +} + +/* MULU */ +static int cpuMULU(VB *sim) { + uint64_t a = cpuGetReg2(sim); + uint64_t b = cpuGetReg1(sim); + int64_t c = a * b; + int32_t d = c; + sim->cpu.program[30] = c >> 32; + cpuSetReg2(sim, d); + sim->cpu.psw.ov = d != c; + sim->cpu.psw.s = d < 0; + sim->cpu.psw.z = d == 0; + cpuAdvance(sim, 13); + return 0; +} + +/* NOT */ +static int cpuNOT(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, ~cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* OR */ +static int cpuOR(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* ORI */ +static int cpuORI(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetImm16U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* OUT.B */ +static int cpuOUT_B(VB *sim) { + return cpuST_OUT(sim, VB_U8); +} + +/* OUT.H */ +static int cpuOUT_H(VB *sim) { + return cpuST_OUT(sim, VB_U16); +} + +/* OUT.W */ +static int cpuOUT_W(VB *sim) { + return cpuST_OUT(sim, VB_S32); +} + +/* RETI */ +static int cpuRETI(VB *sim) { + if (sim->cpu.psw.np) { + sim->cpu.nextPC = sim->cpu.fepc; + cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fepsw, 0); + } else { + sim->cpu.nextPC = sim->cpu.eipc; + cpuSetSystemRegister(sim, VB_PSW, sim->cpu.eipsw, 0); + } + sim->cpu.clocks += cpuClocks(10); + sim->cpu.operation = CPU_FETCH; + return 0; +} + +/* REV */ +static int cpuREV(VB *sim) { + uint32_t x = cpuGetReg1(sim); + x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF); + x = (x << 8 & 0xFF00FF00) | (x >> 8 & 0x00FF00FF); + x = (x << 4 & 0xF0F0F0F0) | (x >> 4 & 0x0F0F0F0F); + x = (x << 2 & 0xCCCCCCCC) | (x >> 2 & 0x33333333); + x = (x << 1 & 0xAAAAAAAA) | (x >> 1 & 0x55555555); + cpuSetReg2(sim, x); + return 0; +} + +/* SAR immediate */ +static int cpuSARImm(VB *sim) { + cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetImm5U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SEI */ +static int cpuSEI(VB *sim) { + sim->cpu.psw.id = 1; + cpuAdvance(sim, cpuClocks(12)); + return 0; +} + +/* SETF */ +static int cpuSETF(VB *sim) { + cpuSetReg2(sim, cpuCondition(sim, cpuGetImm5U(sim) & 15)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SHR register */ +static int cpuSARReg(VB *sim) { + cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetReg1(sim) & 31)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SHL immediate */ +static int cpuSHLImm(VB *sim) { + cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetImm5U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SHR register */ +static int cpuSHLReg(VB *sim) { + cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetReg1(sim) & 31)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SHR immediate */ +static int cpuSHRImm(VB *sim) { + cpuSetReg2(sim, cpuShiftRight(sim, cpuGetImm5U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* SHR register */ +static int cpuSHRReg(VB *sim) { + cpuSetReg2(sim, cpuShiftRight(sim, cpuGetReg1(sim) & 31)); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* ST.B */ +static int cpuST_B(VB *sim) { + return cpuST_OUT(sim, VB_S8); +} + +/* ST.H */ +static int cpuST_H(VB *sim) { + return cpuST_OUT(sim, VB_S16); +} + +/* ST.W */ +static int cpuST_W(VB *sim) { + return cpuST_OUT(sim, VB_S32); +} + +/* STSR */ +static int cpuSTSR(VB *sim) { + cpuSetReg2(sim, cpuGetSystemRegister(sim, cpuGetImm5U(sim))); + cpuAdvance(sim, cpuClocks(8)); + return 0; +} + +/* SUB */ +static int cpuSUB(VB *sim) { + cpuSetReg2(sim, cpuSubtract(sim, cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* TRAP */ +static int cpuTRAP(VB *sim) { + sim->cpu.clocks += cpuClocks(15); + sim->cpu.exception = 0xFFA0 + cpuGetImm5U(sim); + sim->cpu.operation = CPU_EXCEPTION; + return 0; +} + +/* XB */ +static int cpuXB(VB *sim) { + uint32_t x = cpuGetReg2(sim); + x = (x & 0xFFFF0000) | (x << 8 & 0x0000FF00) | (x >> 8 & 0x000000FF); + cpuSetReg2(sim, x); + return 0; +} + +/* XH */ +static int cpuXH(VB *sim) { + uint32_t x = cpuGetReg2(sim); + x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF); + cpuSetReg2(sim, x); + return 0; +} + +/* XOR */ +static int cpuXOR(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetReg1(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + +/* XORI */ +static int cpuXORI(VB *sim) { + cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetImm16U(sim))); + cpuAdvance(sim, cpuClocks(1)); + return 0; +} + + + +/***************************** Library Functions *****************************/ + +/* Process component */ +static int cpuEmulate(VB *sim, uint32_t clocks) { + int brk; + + /* Process until there are clocks to wait */ + for (;;) { + + /* The next event is after the time remaining */ + if (sim->cpu.clocks > clocks) { + sim->cpu.clocks -= clocks; + return 0; + } + + /* Advance forward the CPU's number of clocks */ + if (sim->cpu.clocks != 0) { + clocks -= sim->cpu.clocks; + sim->cpu.clocks = 0; + } + + /* Processing by operation ID */ + switch (sim->cpu.operation) { + case CPU_FETCH: brk = cpuFetch(sim); break; + + case CPU_ADD_IMM: brk = cpuADDImm(sim); break; + case CPU_ADD_REG: brk = cpuADDReg(sim); break; + case CPU_ADDI : brk = cpuADDI (sim); break; + case CPU_AND : brk = cpuAND (sim); break; + case CPU_ANDI : brk = cpuANDI (sim); break; + case CPU_BCOND : brk = cpuBCOND (sim); break; + case CPU_CAXI : brk = cpuCAXI (sim); break; + case CPU_CLI : brk = cpuCLI (sim); break; + case CPU_CMP_IMM: brk = cpuCMPImm(sim); break; + case CPU_CMP_REG: brk = cpuCMPReg(sim); break; + case CPU_DIV : brk = cpuDIV (sim); break; + case CPU_DIVU : brk = cpuDIVU (sim); break; + case CPU_HALT : brk = cpuHALT (sim); break; + case CPU_IN_B : brk = cpuIN_B (sim); break; + case CPU_IN_H : brk = cpuIN_H (sim); break; + case CPU_IN_W : brk = cpuIN_W (sim); break; + case CPU_JAL : brk = cpuJAL (sim); break; + case CPU_JMP : brk = cpuJMP (sim); break; + case CPU_JR : brk = cpuJR (sim); break; + case CPU_LD_B : brk = cpuLD_B (sim); break; + case CPU_LD_H : brk = cpuLD_H (sim); break; + case CPU_LD_W : brk = cpuLD_W (sim); break; + case CPU_LDSR : brk = cpuLDSR (sim); break; + case CPU_MOV_IMM: brk = cpuMOVImm(sim); break; + case CPU_MOV_REG: brk = cpuMOVReg(sim); break; + case CPU_MOVEA : brk = cpuMOVEA (sim); break; + case CPU_MOVHI : brk = cpuMOVHI (sim); break; + case CPU_MPYHW : brk = cpuMPYHW (sim); break; + case CPU_MUL : brk = cpuMUL (sim); break; + case CPU_MULU : brk = cpuMULU (sim); break; + case CPU_NOT : brk = cpuNOT (sim); break; + case CPU_OR : brk = cpuOR (sim); break; + case CPU_ORI : brk = cpuORI (sim); break; + case CPU_OUT_B : brk = cpuOUT_B (sim); break; + case CPU_OUT_H : brk = cpuOUT_H (sim); break; + case CPU_OUT_W : brk = cpuOUT_W (sim); break; + case CPU_RETI : brk = cpuRETI (sim); break; + case CPU_REV : brk = cpuREV (sim); break; + case CPU_SAR_IMM: brk = cpuSARImm(sim); break; + case CPU_SAR_REG: brk = cpuSARReg(sim); break; + case CPU_SEI : brk = cpuSEI (sim); break; + case CPU_SETF : brk = cpuSETF (sim); break; + case CPU_SHL_IMM: brk = cpuSHLImm(sim); break; + case CPU_SHL_REG: brk = cpuSHLReg(sim); break; + case CPU_SHR_IMM: brk = cpuSHRImm(sim); break; + case CPU_SHR_REG: brk = cpuSHRReg(sim); break; + case CPU_ST_B : brk = cpuST_B (sim); break; + case CPU_ST_H : brk = cpuST_H (sim); break; + case CPU_ST_W : brk = cpuST_W (sim); break; + case CPU_STSR : brk = cpuSTSR (sim); break; + case CPU_SUB : brk = cpuSUB (sim); break; + case CPU_TRAP : brk = cpuTRAP (sim); break; + case CPU_XB : brk = cpuXB (sim); break; + case CPU_XH : brk = cpuXH (sim); break; + case CPU_XOR : brk = cpuXOR (sim); break; + case CPU_XORI : brk = cpuXORI (sim); break; + + default: return -1; /* TODO: Temporary for debugging */ + } + + /* A callback requested a break */ + if (brk) + return 1; + } + + return 0; +} + /* Determine how many clocks are guaranteed to process */ static uint32_t cpuUntil(VB *sim, uint32_t clocks) { return sim->cpu.clocks < clocks ? sim->cpu.clocks : clocks; diff --git a/core/vb.c b/core/vb.c index 9bb249c..6a919b4 100644 --- a/core/vb.c +++ b/core/vb.c @@ -73,6 +73,7 @@ struct VB { /* Other state */ uint32_t clocks; /* Master clocks to wait */ uint16_t code[2]; /* Instruction code units */ + uint16_t exception; /* Exception cause code */ uint16_t irq; /* Interrupt request lines */ int length; /* Instruction code length */ uint32_t nextPC; /* Address of next instruction */ @@ -83,27 +84,27 @@ struct VB { /* Other system state */ uint8_t wram[0x10000]; /* System RAM */ - /* Application callbacks */ + /* Application data */ vbOnExecute onExecute; /* CPU instruction execute */ vbOnFetch onFetch; /* CPU instruction fetch */ vbOnRead onRead; /* CPU instruction read */ vbOnWrite onWrite; /* CPU instruction write */ + void *tag; /* User data */ }; /***************************** Library Functions *****************************/ -/* Determine the lesser of two clocks figures */ -static uint32_t MinClocks(uint32_t a, uint32_t b) { - return a < b ? a : b; -} - /* Sign-extend an integer of variable width */ static int32_t SignExtend(int32_t value, int32_t bits) { - value &= ~((uint32_t) 0xFFFFFFFF << bits); - bits = (int32_t) 1 << (bits - (int32_t) 1); - return (value ^ bits) - bits; + #ifndef VB_SIGNED_PROPAGATE + value &= ~((uint32_t) 0xFFFFFFFF << bits); + bits = (int32_t) 1 << (bits - (int32_t) 1); + return (value ^ bits) - bits; + #else + return value << (32 - bits) >> (32 - bits); + #endif } @@ -169,19 +170,6 @@ VBAPI int vbEmulateEx(VB **sims, int count, uint32_t *clocks) { return 0; } -/* Retrieve a callback handler */ -VBAPI void* vbGetCallback(VB *sim, int id) { - switch (id) { - /*case VB_EXCEPTION: return *(void **) &sim->onException;*/ - case VB_EXECUTE : return *(void **) &sim->onExecute; - case VB_FETCH : return *(void **) &sim->onFetch; - /*case VB_FRAME : return *(void **) &sim->onFrame;*/ - case VB_READ : return *(void **) &sim->onRead; - case VB_WRITE : return *(void **) &sim->onWrite; - } - return NULL; -} - /* Retrieve the game pack RAM buffer */ VBAPI void* vbGetCartRAM(VB *sim, uint32_t *size) { if (size != NULL) @@ -196,6 +184,16 @@ VBAPI void* vbGetCartROM(VB *sim, uint32_t *size) { return sim->cart.rom; } +/* Retrieve the execute callback handle */ +VBAPI vbOnExecute vbGetExecuteCallback(VB *sim) { + return sim->onExecute; +} + +/* Retrieve the fetch callback handle */ +VBAPI vbOnFetch vbGetFetchCallback(VB *sim) { + return sim->onFetch; +} + /* Retrieve the value of the program counter */ VBAPI uint32_t vbGetProgramCounter(VB *sim) { return sim->cpu.pc; @@ -206,11 +204,26 @@ VBAPI int32_t vbGetProgramRegister(VB *sim, int index) { return index < 1 || index > 31 ? 0 : sim->cpu.program[index]; } +/* Retrieve the read callback handle */ +VBAPI vbOnRead vbGetReadCallback(VB *sim) { + return sim->onRead; +} + /* Retrieve the value in a system register */ VBAPI uint32_t vbGetSystemRegister(VB *sim, int index) { return index < 0 || index > 31 ? 0 : cpuGetSystemRegister(sim, index); } +/* Retrieve a simulation's userdata pointer */ +VBAPI void* vbGetUserData(VB *sim) { + return sim->tag; +} + +/* Retrieve the write callback handle */ +VBAPI vbOnWrite vbGetWriteCallback(VB *sim) { + return sim->onWrite; +} + /* Initialize a simulation instance */ VBAPI VB* vbInit(VB *sim) { sim->cart.ram = NULL; @@ -241,8 +254,9 @@ VBAPI VB* vbReset(VB *sim) { sim->wram[x] = 0x00; /* CPU (normal) */ - sim->cpu.irq = 0; - sim->cpu.pc = 0xFFFFFFF0; + sim->cpu.exception = 0; + sim->cpu.irq = 0; + sim->cpu.pc = 0xFFFFFFF0; cpuSetSystemRegister(sim, VB_ECR, 0x0000FFF0, 1); cpuSetSystemRegister(sim, VB_PSW, 0x00008000, 1); @@ -267,29 +281,6 @@ VBAPI VB* vbReset(VB *sim) { return sim; } -/* Specify a new callback handler */ -VBAPI void* vbSetCallback(VB *sim, int id, void *callback) { - void *prev = NULL; - void **target = NULL; - - /* Select callback by ID */ - switch (id) { - /*case VB_EXCEPTION: target = (void **) &sim->onException; break;*/ - case VB_EXECUTE : target = (void **) &sim->onExecute ; break; - case VB_FETCH : target = (void **) &sim->onFetch ; break; - /*case VB_FRAME : target = (void **) &sim->onFrame ; break;*/ - case VB_READ : target = (void **) &sim->onRead ; break; - case VB_WRITE : target = (void **) &sim->onWrite ; break; - } - - /* Retrieve current state and update new state */ - if (target != NULL) { - prev = *target; - *target = callback; - } - return prev; -} - /* Specify a game pak RAM buffer */ VBAPI int vbSetCartRAM(VB *sim, void *sram, uint32_t size) { if (sram != NULL) { @@ -312,6 +303,20 @@ VBAPI int vbSetCartROM(VB *sim, void *rom, uint32_t size) { return 0; } +/* Specify a new execute callback handle */ +VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback) { + vbOnExecute prev = sim->onExecute; + sim->onExecute = callback; + return prev; +} + +/* Specify a new fetch callback handle */ +VBAPI vbOnFetch vbSetFetchCallback(VB *sim, vbOnFetch callback) { + vbOnFetch prev = sim->onFetch; + sim->onFetch = callback; + return prev; +} + /* Specify a new value for the program counter */ VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) { sim->cpu.operation = CPU_FETCH; @@ -325,17 +330,38 @@ VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value) { return index < 1 || index > 31 ? 0 : (sim->cpu.program[index] = value); } +/* Specify a new read callback handle */ +VBAPI vbOnRead vbSetReadCallback(VB *sim, vbOnRead callback) { + vbOnRead prev = sim->onRead; + sim->onRead = callback; + return prev; +} + /* Specify a new value for a system register */ VBAPI uint32_t vbSetSystemRegister(VB *sim, int index, uint32_t value) { return index < 0 || index > 31 ? 0 : cpuSetSystemRegister(sim, index, value, 1); } +/* Specify a new write callback handle */ +VBAPI vbOnWrite vbSetWriteCallback(VB *sim, vbOnWrite callback) { + vbOnWrite prev = sim->onWrite; + sim->onWrite = callback; + return prev; +} + /* Determine the size of a simulation instance */ VBAPI size_t vbSizeOf() { return sizeof (VB); } +/* Specify a simulation's userdata pointer */ +VBAPI void* vbSetUserData(VB *sim, void *tag) { + void *prev = sim->tag; + sim->tag = tag; + return prev; +} + /* Write a value to the memory bus */ VBAPI int32_t vbWrite(VB *sim, uint32_t address, int type, int32_t value) { if (type < 0 || type > 4) diff --git a/core/vb.h b/core/vb.h index 6edc937..bad8d4e 100644 --- a/core/vb.h +++ b/core/vb.h @@ -44,11 +44,6 @@ extern "C" { #define VB_U16 3 #define VB_S32 4 -/* CPU modes */ -#define VB_ACCURACY 0 -#define VB_DEBUG 1 -#define VB_WHOLE 2 - /*********************************** Types ***********************************/ @@ -67,25 +62,34 @@ typedef int (*vbOnWrite )(VB *sim, uint32_t address, int type, int32_t *value, /******************************* API Commands ********************************/ -VBAPI int vbEmulate (VB *sim, uint32_t *clocks); -VBAPI int vbEmulateEx (VB **sims, int count, uint32_t *clocks); -VBAPI void* vbGetCallback (VB *sim, int id); -VBAPI void* vbGetCartRAM (VB *sim, uint32_t *size); -VBAPI void* vbGetCartROM (VB *sim, uint32_t *size); -VBAPI uint32_t vbGetProgramCounter (VB *sim); -VBAPI int32_t vbGetProgramRegister(VB *sim, int index); -VBAPI uint32_t vbGetSystemRegister (VB *sim, int index); -VBAPI VB* vbInit (VB *sim); -VBAPI int32_t vbRead (VB *sim, uint32_t address, int type); -VBAPI VB* vbReset (VB *sim); -VBAPI void* vbSetCallback (VB *sim, int index, void *callback); -VBAPI int vbSetCartRAM (VB *sim, void *sram, uint32_t size); -VBAPI int vbSetCartROM (VB *sim, void *rom, uint32_t size); -VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value); -VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value); -VBAPI uint32_t vbSetSystemRegister (VB *sim, int index, uint32_t value); -VBAPI size_t vbSizeOf (); -VBAPI int32_t vbWrite (VB *sim, uint32_t address, int type, int32_t value); +VBAPI int vbEmulate (VB *sim, uint32_t *clocks); +VBAPI int vbEmulateEx (VB **sims, int count, uint32_t *clocks); +VBAPI void* vbGetCallback (VB *sim, int id); +VBAPI void* vbGetCartRAM (VB *sim, uint32_t *size); +VBAPI void* vbGetCartROM (VB *sim, uint32_t *size); +VBAPI vbOnExecute vbGetExecuteCallback(VB *sim); +VBAPI vbOnFetch vbGetFetchCallback (VB *sim); +VBAPI uint32_t vbGetProgramCounter (VB *sim); +VBAPI int32_t vbGetProgramRegister(VB *sim, int index); +VBAPI vbOnRead vbGetReadCallback (VB *sim); +VBAPI uint32_t vbGetSystemRegister (VB *sim, int index); +VBAPI void* vbGetUserData (VB *sim); +VBAPI vbOnWrite vbGetWriteCallback (VB *sim); +VBAPI VB* vbInit (VB *sim); +VBAPI int32_t vbRead (VB *sim, uint32_t address, int type); +VBAPI VB* vbReset (VB *sim); +VBAPI int vbSetCartRAM (VB *sim, void *sram, uint32_t size); +VBAPI int vbSetCartROM (VB *sim, void *rom, uint32_t size); +VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback); +VBAPI vbOnFetch vbSetFetchCallback (VB *sim, vbOnFetch callback); +VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value); +VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value); +VBAPI vbOnRead vbSetReadCallback (VB *sim, vbOnRead callback); +VBAPI uint32_t vbSetSystemRegister (VB *sim, int index, uint32_t value); +VBAPI void* vbSetUserData (VB *sim, void *tag); +VBAPI vbOnWrite vbSetWriteCallback (VB *sim, vbOnWrite callback); +VBAPI size_t vbSizeOf (); +VBAPI int32_t vbWrite (VB *sim, uint32_t address, int type, int32_t value); diff --git a/makefile b/makefile index 4b8d91c..8ff16e1 100644 --- a/makefile +++ b/makefile @@ -41,14 +41,14 @@ core: # GCC compilation control @gcc core/vb.c -I core -c -o /dev/null \ -Werror -std=c90 -Wall -Wextra -Wpedantic \ - -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE + -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC # Clang generic @emcc core/vb.c -I core -c -o /dev/null \ -Werror -std=c90 -Wall -Wextra -Wpedantic # Clang compilation control @emcc core/vb.c -I core -c -o /dev/null \ -Werror -std=c90 -Wall -Wextra -Wpedantic \ - -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE + -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC .PHONY: wasm wasm: