changeset 612:5a6ff0d76032

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
author Michael Pavone <pavone@retrodev.com>
date Sun, 28 Dec 2014 17:25:36 -0800
parents 744b305965f7
children 09d5adf8d1ca
files m68k_core_x86.c runtime.S runtime_32.S
diffstat 3 files changed, 58 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- 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) {
--- 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
 
 
-
--- 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