# HG changeset patch # User Michael Pavone # Date 1419816336 28800 # Node ID 5a6ff0d7603276f849345c4080b8274fc9d6025c # Parent 744b305965f7a0f0d5dc5d7b12b43810a08f1a89 Removed bcd_add and bcd_sub from runtime.S and generated the logic inline with the rest of abcd and sbcd translation. Fixed some edge cases and undefined flag behavior in the process diff -r 744b305965f7 -r 5a6ff0d76032 m68k_core_x86.c --- a/m68k_core_x86.c Sat Dec 27 15:49:15 2014 -0800 +++ b/m68k_core_x86.c Sun Dec 28 17:25:36 2014 -0800 @@ -1404,17 +1404,69 @@ mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B); } } + uint8_t other_reg; + //WARNING: This may need adjustment if register assignments change + if (opts->gen.scratch2 > RBX) { + other_reg = RAX; + xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); + } else { + other_reg = opts->gen.scratch2; + } + mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B); + mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B); + and_ir(code, 0xF0, opts->gen.scratch1, SZ_B); + and_ir(code, 0xF0, other_reg, SZ_B); + and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B); + and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B); + //do op on low nibble flag_to_carry(opts, FLAG_X); - jcc(code, CC_NC, code->cur + 5); if (inst->op == M68K_ABCD) { - add_ir(code, 1, opts->gen.scratch1, SZ_B); + adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); + } else { + sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); + } + cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B); + code_ptr no_adjust = code->cur+1; + //add correction factor if necessary + jcc(code, CC_B, no_adjust); + if (inst->op == M68K_ABCD) { + add_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); } else { - sub_ir(code, 1, opts->gen.scratch1, SZ_B); + sub_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); + } + *no_adjust = code->cur - (no_adjust+1); + //add low nibble result to one of the high nibble operands + add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B); + if (inst->op == M68K_ABCD) { + add_rr(code, other_reg, opts->gen.scratch1, SZ_B); + } else { + sub_rr(code, other_reg, opts->gen.scratch1, SZ_B); + } + if (opts->gen.scratch2 > RBX) { + mov_rr(code, opts->gen.scratch2, RAX, SZ_D); } - call(code, (code_ptr) (inst->op == M68K_ABCD ? bcd_add : bcd_sub)); - reg_to_flag(opts, CH, FLAG_C); - reg_to_flag(opts, CH, FLAG_X); + set_flag(opts, 0, FLAG_C); + set_flag(opts, 0, FLAG_V); + code_ptr def_adjust = code->cur+1; + jcc(code, CC_C, def_adjust); + cmp_ir(code, 0xA0, opts->gen.scratch1, SZ_B); + no_adjust = code->cur+1; + jcc(code, CC_B, no_adjust); + *def_adjust = code->cur - (def_adjust + 1); + set_flag(opts, 1, FLAG_C); + if (inst->op == M68K_ABCD) { + add_ir(code, 0x60, opts->gen.scratch1, SZ_B); + } else { + sub_ir(code, 0x60, opts->gen.scratch1, SZ_B); + } + //V flag is set based on the result of the addition of the + //result and the correction factor + set_flag_cond(opts, CC_O, FLAG_V); + *no_adjust = code->cur - (no_adjust+1); + flag_to_flag(opts, FLAG_C, FLAG_X); + cmp_ir(code, 0, opts->gen.scratch1, SZ_B); + set_flag_cond(opts, CC_S, FLAG_N); jcc(code, CC_Z, code->cur + 4); set_flag(opts, 0, FLAG_Z); if (dst_op->base != opts->gen.scratch1) { diff -r 744b305965f7 -r 5a6ff0d76032 runtime.S --- a/runtime.S Sat Dec 27 15:49:15 2014 -0800 +++ b/runtime.S Sun Dec 28 17:25:36 2014 -0800 @@ -12,63 +12,5 @@ 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 - diff -r 744b305965f7 -r 5a6ff0d76032 runtime_32.S --- a/runtime_32.S Sat Dec 27 15:49:15 2014 -0800 +++ b/runtime_32.S Sun Dec 28 17:25:36 2014 -0800 @@ -12,63 +12,6 @@ push $1 call exit - .global bcd_add -bcd_add: - xchg %eax, %edi - - 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 %edi, %eax - ret - - .global bcd_sub -bcd_sub: - xchg %eax, %edi - - 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 %edi, %eax - ret