diff options
-rw-r--r-- | sux.h | 25 |
1 files changed, 25 insertions, 0 deletions
@@ -1778,6 +1778,14 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p } } +#define shift(reg, value, sign, shift) (((reg) shift (value)) | ((sign))) +#define rotate(sum, reg, value, shift1, shift2, c1, c2) \ + switch (value & 0x3F) { \ + case 0: sum = (reg); break; \ + case 1: sum = shift(reg, value, c1, shift1); break; \ + default: sum = shift(reg, value, c2, shift1) | shift(reg, (msb+1)-value, 0, shift2); break; \ + } + #if 0 #define t(w8, w7, w6, w5, w4, w3, w2, w1, w0, code) \ do { \ @@ -1792,7 +1800,10 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p #define inst(op, ext) \ static /*inline*/ void inst_##op(struct sux *cpu, uint8_t prefix, uint8_t size, int inc_pc, int inc_clk, uint8_t thread) { \ const unsigned int o8 = 0x##op / 32, o8m = 1 << (0x##op % 32); \ + const uint8_t msb = size*8; \ uint8_t rs = ((1 << ((prefix >> 4) & 3)) - 1); \ + uint8_t carry = 0; \ + uint64_t sign = 0; \ uint64_t addr = 0, idx = 0, tmp = 0, tmp2 = 0; \ uint64_t dummy = 0, *reg = &dummy; \ uint64_t dummy2 = 0, *reg2 = &dummy; \ @@ -1851,6 +1862,20 @@ static /*inline*/ void inst_##op(struct sux *cpu, uint8_t prefix, uint8_t size, /* Set program counter to supplied address */ \ t(7, 0x00011000, 0x10010000, 0x00010000, 0x00010001, 0x00000201, 0x00010001, 0x00010001, 0x00010000) { if (tmp) { cpu->pc = addr; } } /* If flag is 1. */ \ t(0, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000) { if (!tmp) { cpu->pc = addr; } } /* If flag is 0. */ \ + /* Arithmetic operations. */ \ + t(0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00440044, 0x00000000, 0x00000000, 0x00000000) { sign = -(uint64_t)(*reg >> (msb-1)) << (msb-1)-tmp2; } /* asr. */ \ + t(0, 0x00220022, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00220022, 0x00660066) { carry = getflag(C); } /* adc, sbc, and rotate. */ \ + t(0, 0x06000000, 0x00000000, 0x04000400, 0x00441044, 0x10000000, 0x00100110, 0x00100110, 0x00100110) { carry = 1; } /* cmp, cpb, cpx, and cpy. */ \ + t(0, 0x06220022, 0x00220022, 0x04220422, 0x00441044, 0x10440044, 0x00540154, 0x00760176, 0x00760176) { tmp2 = tmp; } /* Copy source operand. */ \ + t(0, 0x06000000, 0x00000000, 0x04000400, 0x00441044, 0x10000000, 0x00100110, 0x00320132, 0x00320132) { tmp += *reg + carry; carry = tmp < tmp2; } /* adc, sbc, and cmp. */ \ + t(0, 0x00000000, 0x00000000, 0x00220022, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000) { tmp = (tmp2 < msb) ? shift(*reg, tmp2, 0, <<) : 0; } /* lsl. */ \ + t(0, 0x00000000, 0x00220022, 0x00000000, 0x00000000, 0x00440044, 0x00000000, 0x00000000, 0x00000000) { tmp = (tmp2 < msb) ? shift(*reg, tmp2, sign, >>) : 0; } /* lsr, asr. */ \ + t(0, 0x00220022, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000) { rotate(tmp, *reg, tmp2, <<, >>, carry & 1, carry << (tmp2-1)); } /* rol. */ \ + t(0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00440044) { rotate(tmp, *reg, tmp2, >>, <<, carry << (msb-1), carry << (msb-tmp2)); } /* ror. */ \ + t(0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00440044, 0x00000000) { tmp *= *reg; } /* mul. */ \ + t(0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00440044, 0x00000000, 0x00000000) { tmp /= *reg; *reg2 %= tmp2; } /* div. */ \ + t(0, 0x00220022, 0x00000000, 0x00220022, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000) { carry = (*reg >> (msb-(tmp2+!tmp2))) & 1; } /* rol, lsl. */ \ + t(0, 0x00000000, 0x00220022, 0x00000000, 0x00000000, 0x00440044, 0x00000000, 0x00000000, 0x00440044) { carry = (*reg >> tmp2-(tmp2 != 0)) & 1; } /* ror, lsr, asr. */ \ } #undef ORTHO_1CC |