First cut at DAA and DAS algorithms in ARM and misc assembly cleanup

This commit is contained in:
Aaron Culliney 2015-02-19 16:03:29 -08:00
parent 86e8eeafe2
commit 59d151d684
2 changed files with 97 additions and 90 deletions

View File

@ -32,9 +32,6 @@
// r14 ARM return addr // r14 ARM return addr
// r15 ARM PC // r15 ARM PC
#define ARM_CF_Bit ... /* ARM carry */
#define ARM_AF_Bit ...
#ifdef __aarch64__ #ifdef __aarch64__
# error 20150205 ARM 64bit untested!!! # error 20150205 ARM 64bit untested!!!

View File

@ -194,15 +194,22 @@
mov r0, r0, LSL #24; \ mov r0, r0, LSL #24; \
mov r0, r0, ASR #24; mov r0, r0, ASR #24;
#define _IncOpCycles \
ldr mem_cycle_count, SYM(cpu65_opcycles); \
ldrb scratch_count, [mem_cycle_count]; \
add scratch_count, scratch_count, #1;
#define IncOpCycles \
_IncOpCycles \
strb scratch_count, [mem_cycle_count];
#define pc_hi_byte r9 #define pc_hi_byte r9
#define mem_cycle_count r1 #define mem_cycle_count r1
#define scratch_count r12 #define scratch_count r12
#define pc_hi_prev r9 #define pc_hi_prev r9
#define pc_hi_next r0 #define pc_hi_next r0
#define BranchXCycles \ #define BranchXCycles \
ldr mem_cycle_count, SYM(cpu65_opcycles); \ _IncOpCycles \
ldrb scratch_count, [mem_cycle_count]; \
add scratch_count, scratch_count, #1; /* +1 branch taken */ \
mov pc_hi_prev, PC_Reg; \ mov pc_hi_prev, PC_Reg; \
mov pc_hi_prev, pc_hi_prev, LSR #8; \ mov pc_hi_prev, pc_hi_prev, LSR #8; \
cbw; \ cbw; \
@ -217,7 +224,7 @@
#define arm_flags r12 #define arm_flags r12
#define lahf \ #define lahf \
/* Virtual x86: Load %AH (r12) from Flags */ \ /* Virtual x86: Load %AH (r12) from ARM CPU Flags */ \
mov arm_flags, r15, LSR #28; mov arm_flags, r15, LSR #28;
#define FlagC \ #define FlagC \
@ -343,13 +350,6 @@
teq ea_hi_prev, ea_hi_next; \ teq ea_hi_prev, ea_hi_next; \
beq 9f; beq 9f;
#define PageBoundaryCrossed \
ldr mem_cycle_count, SYM(cpu65_opcycles); \
eor scratch_count, scratch_count, scratch_count; /* HACK FIXME TODO VERIFY IN GDB : is this necessary? */ \
ldrb scratch_count, [mem_cycle_count]; \
add scratch_count, scratch_count, #1; /* +1 cycle on page_boundary */ \
strb scratch_count, [mem_cycle_count];
/* Absolute Indexed Addressing - The effective address is formed by /* Absolute Indexed Addressing - The effective address is formed by
adding the contents of X or Y to the address contained in the adding the contents of X or Y to the address contained in the
second and third bytes of the instruction. */ second and third bytes of the instruction. */
@ -357,25 +357,25 @@
#define GetAbs_X \ #define GetAbs_X \
GetFromPC_W \ GetFromPC_W \
AddIndexRegAndTestPageBoundary(X_Reg) \ AddIndexRegAndTestPageBoundary(X_Reg) \
PageBoundaryCrossed \ IncOpCycles \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
#define GetAbs_X_STx \ #define GetAbs_X_STx \
GetFromPC_W \ GetFromPC_W \
AddIndexRegAndTestPageBoundary(X_Reg) \ AddIndexRegAndTestPageBoundary(X_Reg) \
/* PageBoundaryCrossed */ \ /* IncOpCycles */ \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
#define GetAbs_Y \ #define GetAbs_Y \
GetFromPC_W \ GetFromPC_W \
AddIndexRegAndTestPageBoundary(Y_Reg) \ AddIndexRegAndTestPageBoundary(Y_Reg) \
PageBoundaryCrossed \ IncOpCycles \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
#define GetAbs_Y_STA \ #define GetAbs_Y_STA \
GetFromPC_W \ GetFromPC_W \
AddIndexRegAndTestPageBoundary(Y_Reg) \ AddIndexRegAndTestPageBoundary(Y_Reg) \
/* PageBoundaryCrossed */ \ /* IncOpCycles */ \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
/* Zero Page Indirect Addressing (65c02) - The second byte of the /* Zero Page Indirect Addressing (65c02) - The second byte of the
@ -438,12 +438,12 @@
#define GetIndZPage_Y \ #define GetIndZPage_Y \
_GetIndZPage_Y \ _GetIndZPage_Y \
PageBoundaryCrossed \ IncOpCycles \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
#define GetIndZPage_Y_STA \ #define GetIndZPage_Y_STA \
_GetIndZPage_Y \ _GetIndZPage_Y \
PageBoundaryCrossed \ IncOpCycles \
9: mov EffectiveAddr, r0; 9: mov EffectiveAddr, r0;
#define bt \ #define bt \
@ -452,6 +452,11 @@
biceq r15, r15, #30; \ biceq r15, r15, #30; \
orrne r15, r15, #30; orrne r15, r15, #30;
#define btc \
/* Virtual x86: Bit Test and Clear (carry flag only) */ \
tst F_Reg, #C_Flag; \
biceq r15, r15, #30;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// 65c02 instruction macros // 65c02 instruction macros
@ -685,15 +690,23 @@
ADd memory to accumulator with Carry ADd memory to accumulator with Carry
---------------------------------- */ ---------------------------------- */
#define _AF r10
#define hi_nib r0
#define lo_nib r9
// Decimal mode // Decimal mode
ENTRY(op_ADC_dec) ENTRY(op_ADC_dec)
#warning FIXME TODO op_ADC_dec IncOpCycles
#if 0
incb SYM(cpu65_opcycles) // +1 cycle
GetFromEA_B GetFromEA_B
DebugBCDCheck DebugBCDCheck
bt $C_Flag_Bit, AF_Reg_X
adcb A_Reg, %al // initial addition with nybble carry check
and _AF, A_Reg, #0x10
bt
adcs r0, A_Reg, r0
and r1, A_Reg, #0x10
eor _AF, _AF, r1
// DAA algorithm : http://www.ray.masmcode.com/BCDdaa.html // DAA algorithm : http://www.ray.masmcode.com/BCDdaa.html
// CF_old = CF // CF_old = CF
// IF (al AND 0Fh > 9) or (the Auxilliary Flag is set) // IF (al AND 0Fh > 9) or (the Auxilliary Flag is set)
@ -705,34 +718,32 @@ ENTRY(op_ADC_dec)
// al = al + 60h // al = al + 60h
// CF set // CF set
// ENDIF // ENDIF
pushq _XBX
pushfq lahf
popq _XBX bic F_Reg, #NVZC_Flags
andb $~(N_Flag|V_Flag|Z_Flag|C_Flag), F_Reg mov r1, r0
movb %al, %ah and r1, r1, #0x0f
andb $0x0f, %ah cmp r1, #0x09
cmpb $9, %ah bhi _daa_lo_nyb
jg _daa_lo_nyb teq _AF, #0
btq $X86_AF_Bit, _XBX beq _daa_next0
jnc _daa_next0 _daa_lo_nyb: mov r0, r0, LSL #24
_daa_lo_nyb: addb $6, %al // adjust lo nybble adds r0, r0, #0x06000000 // adjust lo nybble
jc _daa_hi_nyb mov r0, r0, LSR #24
_daa_next0: btq $X86_CF_Bit, _XBX bcs _daa_hi_nyb
jc _daa_hi_nyb _daa_next0: tst arm_flags, #C_Flag
xorb %ah, %ah bne _daa_hi_nyb
cmpw $0x99, %ax cmp r0, #0x9A
jle _daa_next1 bmi _daa_next1
_daa_hi_nyb: addb $0x60, %al // adjust hi nybble _daa_hi_nyb: add r0, r0, #0x60 // adjust hi nybble
orb $C_Flag, F_Reg // FlagC orr F_Reg, F_Reg, #C_Flag // FlagC
_daa_next1: testq $0x80, %rax _daa_next1: tst r0, #0x80
jz _daa_next2 beq _daa_next2
orb $N_Flag, F_Reg // FlagN orr F_Reg, F_Reg, #N_Flag // FlagN
_daa_next2: testq $0xFF, %rax _daa_next2: tst r0, #0xFF
jnz _daa_finish bne _daa_finish
orb $Z_Flag, F_Reg // FlagZ orr F_Reg, F_Reg, #Z_Flag // FlagZ
_daa_finish: popq _XBX _daa_finish: mov A_Reg, r0
movb %al, A_Reg
#endif
Continue Continue
#define maybe_DoADC_d \ #define maybe_DoADC_d \
@ -1094,7 +1105,7 @@ ENTRY(op_BRK)
EncodeFlags EncodeFlags
Push(r0) Push(r0)
orr F_Reg, F_Reg, #I_Flag orr F_Reg, F_Reg, #I_Flag
ldr EffectiveAddr, SYM(interrupt_vector) ldr EffectiveAddr, SYM(interrupt_vector)
ldrh EffectiveAddr, [EffectiveAddr] ldrh EffectiveAddr, [EffectiveAddr]
GetFromEA_W GetFromEA_W
mov PC_Reg, r0 mov PC_Reg, r0
@ -1856,15 +1867,18 @@ ENTRY(op_RTS) // 0x60
SuBtract memory from accumulator with Borrow SuBtract memory from accumulator with Borrow
---------------------------------- */ ---------------------------------- */
ENTRY(op_SBC_dec) ENTRY(op_SBC_dec)
#warning FIXME TODO op_ADC_dec IncOpCycles
#if 0
incb SYM(cpu65_opcycles) // +1 cycle
GetFromEA_B GetFromEA_B
DebugBCDCheck DebugBCDCheck
btc $C_Flag_Bit, AF_Reg_X
xchgb A_Reg, %al // initial subtraction with nybble borrow check
cmc and _AF, A_Reg, #0x10
sbbb A_Reg, %al btc
/*cmc*/
sbcs r0, A_Reg, r0
and r1, A_Reg, #0x10
eor _AF, _AF, r1
// DAS algorithm : http://www.ray.masmcode.com/BCDdas.html // DAS algorithm : http://www.ray.masmcode.com/BCDdas.html
// CF_old = CF // CF_old = CF
// IF (al AND 0Fh > 9) or (the Auxilliary Flag is set) // IF (al AND 0Fh > 9) or (the Auxilliary Flag is set)
@ -1876,35 +1890,31 @@ ENTRY(op_SBC_dec)
// al = al - 60h // al = al - 60h
// ^CF set // ^CF set
// ENDIF // ENDIF
pushq _XBX
pushfq lahf
popq _XBX bic F_Reg, F_Reg, #NVZ_Flags
andb $~(N_Flag|V_Flag|Z_Flag), F_Reg orr F_Reg, #C_Flag
orb $C_Flag, F_Reg mov r1, r0
movb %al, %ah and r1, r1, #0x0f
andb $0x0f, %ah cmp r1, #0x09
cmpb $9, %ah bhi _das_lo_nyb
jg _das_lo_nyb teq _AF, #0
btq $X86_AF_Bit, _XBX beq _das_next0
jnc _das_next0 _das_lo_nyb: sbcs r0, r0, #0x06000000 // adjust lo nybble
_das_lo_nyb: subb $6, %al // adjust lo nybble bcs _das_hi_nyb
jc _das_hi_nyb _das_next0: tst arm_flags, #C_Flag
_das_next0: btq $X86_CF_Bit, _XBX bne _das_hi_nyb
jc _das_hi_nyb cmp r0, #0x9A
xorb %ah, %ah bmi _das_next1
cmpw $0x99, %ax _das_hi_nyb: sub r0, r0, #0x60 // adjust hi nybble
jle _das_next1 bic F_Reg, F_Reg, #C_Flag // !FlagC
_das_hi_nyb: subb $0x60, %al // adjust hi nybble _das_next1: tst r0, #0x80
andb $~C_Flag, F_Reg // !FlagC beq _das_next2
_das_next1: testq $0x80, %rax orr F_Reg, F_Reg, #N_Flag // FlagN
jz _das_next2 _das_next2: tst r0, #0xFF
orb $N_Flag, F_Reg // FlagN bne _das_finish
_das_next2: testq $0xFF, %rax orr F_Reg, F_Reg, #Z_Flag // FlagZ
jnz _das_finish _das_finish: mov A_Reg, r0
orb $Z_Flag, F_Reg // FlagZ
_das_finish: popq _XBX
movb %al, A_Reg
#endif
Continue Continue
#define maybe_DoSBC_d \ #define maybe_DoSBC_d \