# HG changeset patch # User Mike Pavone # Date 1358404856 28800 # Node ID 811163790e6caab8ef5943a62cc7458f9e0547b0 # Parent c66e4636f991c787f7240f995eb9011138e07598 Implement ABCD an SBCD. Fix BTEST with register source. diff -r c66e4636f991 -r 811163790e6c gen_x86.c --- a/gen_x86.c Tue Jan 15 00:14:36 2013 -0800 +++ b/gen_x86.c Wed Jan 16 22:40:56 2013 -0800 @@ -128,7 +128,7 @@ opcode |= BIT_DIR; tmp = dst; dst = src; - src = dst; + src = tmp; } if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { *out = PRE_REX; @@ -1378,12 +1378,12 @@ uint8_t * bts_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) { - return bit_rr(out, OP2_BT, src, dst, size); + return bit_rr(out, OP2_BTS, src, dst, size); } uint8_t * bts_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size) { - return bit_rrdisp8(out, OP2_BT, src, dst_base, dst_disp, size); + return bit_rrdisp8(out, OP2_BTS, src, dst_base, dst_disp, size); } uint8_t * bts_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size) diff -r c66e4636f991 -r 811163790e6c m68k_to_x86.c --- a/m68k_to_x86.c Tue Jan 15 00:14:36 2013 -0800 +++ b/m68k_to_x86.c Wed Jan 16 22:40:56 2013 -0800 @@ -49,6 +49,8 @@ void set_ccr(); void get_sr(); void do_sync(); +void bcd_add(); +void bcd_sub(); void m68k_start_context(uint8_t * addr, m68k_context * context); uint8_t * cycles(uint8_t * dst, uint32_t num) @@ -2692,8 +2694,39 @@ uint8_t size; switch(inst->op) { - //case M68K_ABCD: - // break; + case M68K_ABCD: + if (src_op.base != SCRATCH2) { + if (src_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); + } else { + dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); + } + } + if (dst_op.base != SCRATCH1) { + if (dst_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); + } else { + dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); + } + } + dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); + dst = jcc(dst, CC_NC, dst+5); + dst = add_ir(dst, 1, SCRATCH1, SZ_B); + dst = call(dst, (uint8_t *)bcd_add); + dst = mov_rr(dst, CH, FLAG_C, SZ_B); + dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); + dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); + dst = jcc(dst, CC_Z, dst+4); + dst = mov_ir(dst, 0, FLAG_Z, SZ_B); + if (dst_op.base != SCRATCH1) { + if (dst_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); + } else { + dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); + } + } + dst = m68k_save_result(inst, dst, opts); + break; case M68K_ADD: dst = cycles(dst, BUS); size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; @@ -3515,8 +3548,40 @@ dst = call(dst, (uint8_t *)m68k_native_addr); dst = jmp_r(dst, SCRATCH1); break; - /*case M68K_SBCD: - case M68K_STOP: + case M68K_SBCD: + if (src_op.base != SCRATCH2) { + if (src_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); + } else { + dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); + } + } + if (dst_op.base != SCRATCH1) { + if (dst_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); + } else { + dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); + } + } + dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); + dst = jcc(dst, CC_NC, dst+5); + dst = sub_ir(dst, 1, SCRATCH1, SZ_B); + dst = call(dst, (uint8_t *)bcd_sub); + dst = mov_rr(dst, CH, FLAG_C, SZ_B); + dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); + dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); + dst = jcc(dst, CC_Z, dst+4); + dst = mov_ir(dst, 0, FLAG_Z, SZ_B); + if (dst_op.base != SCRATCH1) { + if (dst_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); + } else { + dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); + } + } + dst = m68k_save_result(inst, dst, opts); + break; + /*case M68K_STOP: break;*/ case M68K_SUB: size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; diff -r c66e4636f991 -r 811163790e6c runtime.S --- a/runtime.S Tue Jan 15 00:14:36 2013 -0800 +++ b/runtime.S Wed Jan 16 22:40:56 2013 -0800 @@ -100,6 +100,64 @@ call printf mov $1, %rdi call exit + + .global bcd_add +bcd_add: + xchg %rax, %rdi + + mov %cl, %ch + mov %al, %ah + and $0xF, %ch + and $0xF, %ah + and $0xF0, %cl + and $0xF0, %al + add %ah, %ch + cmp $10, %ch + jb no_adjust + add $6, %ch +no_adjust: + add %ch, %al + add %al, %cl + mov $0, %ch + jc def_adjust + cmp $0xA0, %cl + jb no_adjust_h +def_adjust: + add $0x60, %cl + mov $1, %ch +no_adjust_h: + + mov %rdi, %rax + ret + + .global bcd_sub +bcd_sub: + xchg %rax, %rdi + + mov %cl, %ch + mov %al, %ah + and $0xF, %ch + and $0xF, %ah + and $0xF0, %cl + and $0xF0, %al + sub %ah, %ch + cmp $10, %ch + jb no_adjusts + sub $6, %ch +no_adjusts: + add %ch, %cl + sub %al, %cl + mov $0, %ch + jc def_adjusts + cmp $0xA0, %cl + jb no_adjust_hs +def_adjusts: + sub $0x60, %cl + mov $1, %ch +no_adjust_hs: + + mov %rdi, %rax + ret int_dbg_msg: .asciz "Executing Interrupt!"