summaryrefslogtreecommitdiff
path: root/flags.s
diff options
context:
space:
mode:
authorAstrid Smith2011-10-21 01:07:19 -0700
committerAstrid Smith2011-10-21 01:07:19 -0700
commit541bce94a4d73e754ce522758dd25ecddb818f04 (patch)
tree6bca458ce09cc2b9470410bae62b74a747733165 /flags.s
parentef89049eae1d7e2591bef44a3e8151131fb4bed2 (diff)
First stage of converting to be GAS-compliant
I (think I) have converted all the A68k directives to their GAS equivalents. Still remaining are all the inline expressions.
Diffstat (limited to 'flags.s')
-rw-r--r--flags.s315
1 files changed, 315 insertions, 0 deletions
diff --git a/flags.s b/flags.s
new file mode 100644
index 0000000..8fc2058
--- /dev/null
+++ b/flags.s
@@ -0,0 +1,315 @@
+ ;; Routine to set the given flags
+ ;; Noted in \mask by a 1 bit
+.macro F_SET mask ; 32 cycles, 8 bytes
+ or.b \mask,flag_byte-flag_storage(a3)
+ or.b \mask,flag_valid-flag_storage(a3)
+.endm
+
+ ;; Clear the given flags
+ ;; Noted in \mask (must be a reg) by a 1 bit
+.macro F_CLEAR mask ; 36 cycles, 10 bytes
+ or.b \mask,flag_valid-flag_storage(a3)
+ not.b \mask
+ and.b \mask,flag_byte-flag_storage(a3)
+.endm
+
+ ;; Use this when an instruction uses the P/V bit as Parity.
+ ;; Sets or clears the bit explicitly.
+ ;;
+ ;; Byte for which parity is calculated must be in \byte. High
+ ;; byte of \byte.w must be zero, using d0 is suggested. (a0,d1
+ ;; destroyed)
+
+.macro F_PAR byte
+ ori.b #%00000100,flag_valid-flag_storage(a3)
+ move.b flag_byte(pc),d1
+ andi.b #%11111011,d1
+ lea lut_parity(pc),a0
+ or.b 0(a0,\byte.w),d1
+ move.b d1,flag_byte-flag_storage(a3)
+.endm
+
+
+ ;; Use this when an instruction uses the P/V bit as Overflow.
+ ;; Leaves the bit itself implicit; simply marks it dirty.
+.macro F_OVFL ; 20 cycles, 6 bytes
+ andi.b #%11111011,flag_valid-flag_storage(a3)
+.endm
+
+ ;; Save the two operands from ADD \1,\2
+.macro F_ADD_SAVE src dst
+ move.b \src,f_tmp_src_b-flag_storage(a3)
+ move.b \dst,f_tmp_dst_b-flag_storage(a3)
+ move.b #$01,f_tmp_byte-flag_storage(a3)
+ F_SET #%
+.endm
+
+
+
+.text
+
+ ;; Normalize and return inverse of emulated Carry bit (loaded
+ ;; into host zero flag)
+
+ ;; Destroys d1
+f_norm_c:
+ move.b flag_valid-flag_storage(a3),d1
+; d1 is destroyed in all cases, so you can use lsr and the C bit (same speed, smaller)
+ lsr.b #1,d1
+ bcs.s FNC_ok ; Bit is valid
+ move.b (f_host_sr+1)-flag_storage(a3),d1
+ andi.b #%00000001,d1
+ or.b d1,flag_byte-flag_storage(a3)
+ ori.b #%00000001,flag_valid-flag_storage(a3)
+FNC_ok:
+ move.b flag_byte-flag_storage(a3),d1
+ andi.b #%00000001,d1
+ rts
+
+ ;; Normalize and return **INVERSE** of emulated Zero bit
+ ;; (loaded into host's zero flag)
+
+ ;; Destroys d1
+f_norm_z:
+ move.b flag_valid-flag_storage(a3),d1
+ andi.b #%01000000,d1
+ bne.s FNZ_ok ; Bit is valid
+ bsr flags_normalize
+FNZ_ok:
+ move.b flag_byte-flag_storage(a3),d1
+ andi.b #%01000000,d1
+ rts
+
+ ;; Normalize and return **INVERSE** of emulated Parity/oVerflow
+ ;; bit (loaded into host zero flag)
+
+ ;; Destroys d1
+f_norm_pv:
+ move.b flag_valid-flag_storage(a3),d1
+ andi.b #%00000100,d1
+ bne.s FNPV_ok ; Bit is already valid
+ bsr flags_normalize
+FNPV_ok:
+ move.b flag_byte-flag_storage(a3),d1
+ andi.b #%00000100,d1
+ rts
+
+ ;; Calculate the P/V bit as Parity, for the byte in
+ ;; d1. Destroys d0,d1.
+f_calc_parity:
+ andi.w #$ff,d1
+ move.b lut_parity-flag_storage(a3,d1.w),d1
+ move.b (flag_byte),d0
+ and.b #%11110111,d0
+ or.w #%0000100000000000,d0
+ or.b d1,d0
+ move.w d0,flag_byte-flag_storage(a3)
+ rts
+
+ ;; Routine to make both the Carry and Half-Carry flags valid.
+ ;; Trashes d0, d1.
+f_calc_carries:
+ ;; XXX do this
+ ;; if f_tmp_byte == 0 {
+ ;; return, shit is valid
+ ;; } else if f_tmp_byte == 2 {
+ ;; // it's a word
+ ;; add f_tmp_src_w to f_tmp_dst_w
+ ;; low bytes only, create a carry and save
+ ;; then high bytes, create a carry and output
+ ;; then 3rd nibble, create a half-carry and output
+ ;; } else if f_tmp_byte == 3 {
+ ;; // it's a byte
+ ;; add f_tmp_src_b to f_tmp_dst_b
+ ;; create a carry and output
+ ;; add low nybbles only
+ ;; create a half-carry and output
+ ;; }
+ ;; set f_tmp_byte = 0
+ pushm d2-d5 ; how many registers do I need?
+ move.b f_tmp_byte(pc),d0
+ bne f_cc_dirty
+ rts
+f_cc_dirty:
+ cmpi.b #2,d0
+ bne f_cc_byte
+ ;; it's a word!
+ move.w f_tmp_src_w(pc),d2
+ move.w f_tmp_dst_w(pc),d3
+ move.w d3,d4
+ add.w d2,d3
+ move sr,d5
+ andi.w #1,d5
+ rol #8,d5
+ andi.w #$0fff,d2
+ andi.w #$0fff,d4
+ add.w d2,d4
+ andi.l #$1000,d4
+ ori.w #%00010001,d5
+ or.w d4,d5
+ or.w d5,flag_byte-flag_storage(a3)
+ clr.b f_tmp_byte-flag_storage(a3)
+ popm d2-d5
+ rts
+f_cc_byte:
+ move.b f_tmp_src_b(pc),d2
+ move.b f_tmp_dst_b(pc),d3
+ move.b d3,d4
+ add.b d2,d3
+ move sr,d5
+ andi.b #1,d5
+ andi.b #$0f,d2
+ andi.b #$0f,d4
+ add.b d2,d4
+ andi.b #$10,d4
+ or.b d4,d5
+ or.b d5,flag_byte-flag_storage(a3)
+ clr.b f_tmp_byte-flag_storage(a3)
+ or.b #%00010001,flag_valid-flag_storage(a3)
+ popm d2-d5
+ rts
+
+ ;; Normalize and return inverse of emulated Sign bit (loaded
+ ;; into host zero flag).
+
+ ;; Destroys d1
+f_norm_sign:
+ move.b flag_valid-flag_storage(a3),d1
+ andi.b #%01000000,d1
+ bne.s FNsign_ok ; Bit is already valid
+ bsr flags_normalize
+FNsign_ok:
+ move.b flag_byte-flag_storage(a3),d1
+ andi.b #%01000000,d1
+ rts
+
+ ;; Routine to turn 68k flags into z80 flags.
+flags_normalize:
+ move.b (f_host_sr+1)(pc),d1 ; 8/4
+ ;; .w keeps d1 clean
+ andi.w #%00011111,d1 ; 8/4
+
+ ;; doesn't this invalidate the previous contents of d1
+ ;; entirely?
+ move.b lut_ccr(pc,d1.w),d1 ; 10/4
+ move.b flag_valid(pc),d0
+ not.b d0
+ and.b d0,d1 ; Mask out all the unwanted bits
+ not.b d0
+ ori.b #%11000101,d0 ; These are the z80 flag register bits that can be derived from the 68k CCR.
+ move.b d0,flag_valid-flag_storage(a3)
+ or.b d1,flag_byte-flag_storage(a3)
+ rts
+
+ ;; Routine to completely fill the flags register
+flags_all:
+ bsr flags_normalize
+ bsr f_calc_carries
+ rts
+
+
+
+.data
+flag_storage:
+ ;; 0 if the flag is already valid
+ ;; 2 if tmp_???b is valid
+ ;; 3 if tmp_???w is valid
+f_tmp_byte: .byte 0
+
+ ;; 2 if P is 0
+ ;; 3 if P is 1
+ ;; 4 if P is uncalculated Parity
+ ;; 5 if P is uncalculated oVerflow
+f_tmp_p_type: .byte 0
+
+ ;; byte operands
+f_tmp_src_b: .byte 0
+f_tmp_dst_b: .byte 0
+f_tmp_result_b: .byte 0
+
+.even
+f_tmp_src_w: .word 0
+f_tmp_dst_w: .word 0
+f_tmp_result_w: .word 0
+
+ ;; 000XNZVC
+.even
+ ;; DO NOT REARRANGE THESE
+f_host_sr: .word 0
+f_host_ccr: .byte 0 ;XXX make overlap somehow?
+
+.even
+ ;; DO NOT REARRANGE THESE.
+flag_byte: .byte 0 ; Byte of all flags
+flag_valid: .byte 0 ; Validity mask -- 1 if valid.
+
+
+ ;; LUT for the CCR -> F mapping
+lut_ccr:
+ ;; N =S
+ ;; Z = Z
+ ;; V ~ P
+ ;; C= C
+ ;;
+ ;; =CCR= == z80==
+ ;; XNZVC SZ5H3PNC
+ .byte %00000000 ;; 00000 00000000
+ .byte %00000001 ;; 00001 00000001
+ .byte %00000100 ;; 00010 00000100
+ .byte %00000101 ;; 00011 00000101
+ .byte %01000000 ;; 00100 01000000
+ .byte %01000001 ;; 00101 01000001
+ .byte %01000100 ;; 00110 01000100
+ .byte %01000101 ;; 00111 01000101
+ .byte %10000000 ;; 01000 10000000
+ .byte %10000001 ;; 01001 10000001
+ .byte %10000100 ;; 01010 10000100
+ .byte %10000101 ;; 01011 10000101
+ .byte %11000000 ;; 01100 11000000
+ .byte %11000001 ;; 01101 11000001
+ .byte %11000100 ;; 01110 11000100
+ .byte %11000101 ;; 01111 11000101
+ .byte %00000000 ;; 10000 00000000
+ .byte %00000001 ;; 10001 00000001
+ .byte %00000100 ;; 10010 00000100
+ .byte %00000101 ;; 10011 00000101
+ .byte %01000000 ;; 10100 01000000
+ .byte %01000001 ;; 10101 01000001
+ .byte %01000100 ;; 10110 01000100
+ .byte %01000101 ;; 10111 01000101
+ .byte %10000000 ;; 11000 10000000
+ .byte %10000001 ;; 11001 10000001
+ .byte %10000100 ;; 11010 10000100
+ .byte %10000101 ;; 11011 10000101
+ .byte %11000000 ;; 11100 11000000
+ .byte %11000001 ;; 11101 11000001
+ .byte %11000100 ;; 11110 11000100
+ .byte %11000101 ;; 11111 11000101
+
+ ;; 256-byte LUT for the Parity bit.
+ ;; Keep this last so all storage references require only one
+ ;; extension word.
+ ;;
+ ;; This table taken from another z80 emulator
+lut_parity:
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0
+ .byte 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4
+
+ ;; To save space I might be able to overlay the Parity table
+ ;; with the CCR table, or even interleave it in the opcodes.
+
+