grape/source/cpu.s

1552 lines
25 KiB
ArmAsm

.arm
.section .itcm,"ax",%progbits
.global cpu_run
.global cpu_reset
.global cpu_regs
.extern mainram
.extern readb
.extern writeb
reg_pc .req r11
reg_sp .req r10
reg_a .req r9
reg_x .req r8
reg_y .req r7
reg_f .req r6
cycles .req r5
.macro fetch
ldrb r0, [reg_pc], #1
.endm
.macro fetchw
ldrb r0, [reg_pc], #1
ldrb r1, [reg_pc], #1
orr r0, r1, lsl #8
.endm
.macro rebase_sp r
ldr r0, =(mainram+0x100)
add \r, r0
.endm
.macro unbase_sp r
ldr r0, =(mainram+0x100)
sub \r, reg_sp, r0
.endm
.macro rebase_pc r
ldr r1, =memmap_r
mov r2, \r, lsr #12
ldr r1, [r1, r2, lsl #2]
add \r, r1
ldr r2, =last_page
str r1, [r2]
.endm
.macro unbase_pc r
ldr r1, =last_page
ldr r2, [r1]
sub \r, reg_pc, r2
.endm
.macro push b
strb \b, [reg_sp], #-1
.endm
.macro pop
ldrb r0, [reg_sp, #1]!
.endm
.macro adr_zp_z
fetch
.endm
.macro adr_zp r
fetch
add r0, \r
and r0, #0xff
.endm
.macro adr_abs_z
fetchw
.endm
.macro adr_abs r
fetchw
mov r1, r0, lsr #8
cmp r1, #0xff
subeq cycles, #1
add r0, \r
.endm
.macro adr_idx
fetchw
ldr r1, =memmap_r
mov r2, r0, lsr #12
ldr r1, [r1, r2, lsl #2]
add r1, r0
ldrb r0, [r1, #0]
ldrb r1, [r1, #1]
orr r0, r1, lsl #8
.endm
.macro adr_idx_x
fetch
ldr r1, =memmap_r
add r0, reg_x
ldr r1, [r1]
add r1, r0
ldrb r0, [r1, #0]
ldrb r1, [r1, #1]
orr r0, r1, lsl #8
.endm
.macro adr_idx_y
fetch
ldr r3, =memmap_r
ldr r2, [r3]
add r2, r2, r0
ldrb r0, [r2, #0]
ldrb r1, [r2, #1]
orr r0, r1, lsl #8
add r1, r0, reg_y
eor r2, r1, r0
tst r2, #0x100
subne cycles, #1
mov r0, r1
.endm
.macro adr_rel
ldrsb r0, [reg_pc], #1
// Sign extend
add r2, reg_pc, r0
eor r1, r2, reg_pc
tst r1, #0x100
subne cycles, #2
add reg_pc, r0
.endm
#define FLAG_CARRY 0x01<<24
#define FLAG_ZERO 0x02<<24
#define FLAG_INTR 0x04<<24
#define FLAG_DEC 0x08<<24
#define FLAG_OVER 0x40<<24
#define FLAG_NEG 0x80<<24
.macro op_adc r
mov reg_a, reg_a, lsl #24
movs r2, reg_f, lsr #25
bic reg_f, #(FLAG_ZERO+FLAG_CARRY+FLAG_OVER+FLAG_NEG)
subcs \r, \r, #0x100
adcs reg_a, \r, ror #8
orreq reg_f, #FLAG_ZERO
orrcs reg_f, #FLAG_CARRY
orrvs reg_f, #FLAG_OVER
orrmi reg_f, #FLAG_NEG
mov reg_a, reg_a, lsr #24
.endm
.macro op_sbc r
mov reg_a, reg_a, lsl #24
movs r2, reg_f, lsr #25
bic reg_f, #(FLAG_ZERO+FLAG_CARRY+FLAG_OVER+FLAG_NEG)
sbcs reg_a, \r, lsl #24
orrcs reg_f, #FLAG_CARRY
orrvs reg_f, #FLAG_OVER
orrmi reg_f, #FLAG_NEG
movs reg_a, reg_a, lsr #24
orreq reg_f, #FLAG_ZERO
.endm
.macro op_and a1
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
lsl reg_a, #24
ands reg_a, \a1, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
.endm
.macro op_asl a1
bic reg_f, #(FLAG_CARRY+FLAG_ZERO+FLAG_NEG)
movs \a1, \a1, lsl #25
orrcs reg_f, #FLAG_CARRY
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr \a1, #24
.endm
.macro op_cmp a1, a2
bic reg_f, #(FLAG_CARRY+FLAG_ZERO+FLAG_NEG)
mov r3, \a1, lsl #24
cmp r3, \a2, lsl #24
orrcs reg_f, #FLAG_CARRY
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
.endm
.macro op_dec a1
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
lsl \a1, #24
subs \a1, #1<<24
orrmi reg_f, #FLAG_NEG
movs \a1, \a1, lsr #24
orreq reg_f, #FLAG_ZERO
.endm
.macro op_eor a1
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
lsl reg_a, #24
eors reg_a, \a1, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
.endm
.macro op_inc a1
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
lsl \a1, #24
adds \a1, #1<<24
orrmi reg_f, #FLAG_NEG
movs \a1, \a1, lsr #24
orreq reg_f, #FLAG_ZERO
.endm
.macro op_lsr a1
bic reg_f, #(FLAG_CARRY+FLAG_ZERO)
movs \a1, \a1, lsr #1
orrcs reg_f, #FLAG_CARRY
orreq reg_f, #FLAG_ZERO
//flag_neg \a1
.endm
.macro op_ora a1
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
lsl reg_a, #24
orrs reg_a, \a1, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
.endm
.macro op_rol a1
and r3, reg_f, #FLAG_CARRY
bic reg_f, #(FLAG_CARRY+FLAG_ZERO+FLAG_NEG)
movs \a1, \a1, lsl #25
orrcs reg_f, #FLAG_CARRY
adds \a1, r3
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr \a1, #24
.endm
.macro op_ror a1
movs r3, reg_f, lsr #25
bic reg_f, #(FLAG_CARRY+FLAG_ZERO+FLAG_NEG)
lsl \a1, #23
orrcs reg_f, #FLAG_NEG
orrcs \a1, #1<<31
movs \a1, \a1, lsr #24
orreq reg_f, #FLAG_ZERO
orrcs reg_f, #FLAG_CARRY
.endm
.macro op_bit a1
bic reg_f, #(FLAG_ZERO+FLAG_OVER+FLAG_NEG)
tst reg_a, \a1
orreq reg_f, #FLAG_ZERO
tst \a1, #0x40
orrne reg_f, #FLAG_OVER
tst \a1, #0x80
orrne reg_f, #FLAG_NEG
.endm
// NOP
_ea:
_7a:
mov r0, #2
b instr_end
// ORA
_09:
fetch
op_ora r0
mov r0, #2
b instr_end
_05:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_ora r2
mov r0, #3
b instr_end
_15:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_ora r2
mov r0, #4
b instr_end
_0d:
adr_abs_z
bl readb
op_ora r0
mov r0, #4
b instr_end
_1d:
adr_abs reg_x
bl readb
op_ora r0
mov r0, #4
b instr_end
_19:
adr_abs reg_y
bl readb
op_ora r0
mov r0, #4
b instr_end
_01:
adr_idx_x
bl readb
op_ora r0
mov r0, #6
b instr_end
_11:
adr_idx_y
bl readb
op_ora r0
mov r0, #5
b instr_end
// AND
_29:
fetch
op_and r0
mov r0, #2
b instr_end
_25:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_and r2
mov r0, #3
b instr_end
_35:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_and r2
mov r0, #4
b instr_end
_2d:
adr_abs_z
bl readb
op_and r0
mov r0, #4
b instr_end
_3d:
adr_abs reg_x
bl readb
op_and r0
mov r0, #4
b instr_end
_39:
adr_abs reg_y
bl readb
op_and r0
mov r0, #4
b instr_end
_21:
adr_idx_x
bl readb
op_and r0
mov r0, #6
b instr_end
_31:
adr_idx_y
bl readb
op_and r0
mov r0, #5
b instr_end
// ASL
_0a:
op_asl reg_a
mov r0, #2
b instr_end
_06:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_asl r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_16:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_asl r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_0e:
adr_abs_z
mov r4, r0
bl readb
op_asl r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_1e:
adr_abs reg_x
mov r4, r0
bl readb
op_asl r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// BCC
_90:
tst reg_f, #FLAG_CARRY
addne reg_pc, #1
mov r0, #2
bne instr_end
adr_rel
mov r0, #3
b instr_end
// BCS
_b0:
tst reg_f, #FLAG_CARRY
addeq reg_pc, #1
mov r0, #2
beq instr_end
adr_rel
mov r0, #3
b instr_end
// BEQ
_f0:
tst reg_f, #FLAG_ZERO
addeq reg_pc, #1
mov r0, #2
beq instr_end
adr_rel
mov r0, #3
b instr_end
// BIT
_24:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_bit r2
mov r0, #3
b instr_end
_2c:
adr_abs_z
bl readb
op_bit r0
mov r0, #4
b instr_end
.ltorg
// BMI
_30:
tst reg_f, #FLAG_NEG
addeq reg_pc, #1
mov r0, #2
beq instr_end
adr_rel
mov r0, #3
b instr_end
// BNE
_d0:
tst reg_f, #FLAG_ZERO
addne reg_pc, #1
mov r0, #2
bne instr_end
adr_rel
mov r0, #3
b instr_end
// BPL
_10:
tst reg_f, #FLAG_NEG
addne reg_pc, #1
mov r0, #2
bne instr_end
adr_rel
mov r0, #3
b instr_end
// BRK
_00:
add reg_pc, #1
unbase_pc r0
mov r1, r0, lsr #8
and r2, r0, #0xff
push r1
push r2
mov r0, reg_f, lsr #24
orr r0, #0x30
push r0
orr reg_f, #FLAG_INTR
ldr r0, =memmap_r
ldr r0, [r0, #0xf<<2]
ldr r3, =0xfffe
add r0, r3
ldrb r1, [r0, #0]
ldrb r2, [r0, #1]
orr reg_pc, r1, r2, lsl #8
rebase_pc reg_pc
mov r0, #7
b instr_end
// RTI
_40:
pop
bic reg_f, #0xff000000
orr reg_f, r0, lsl #24
pop
mov reg_pc, r0
pop
orr reg_pc, r0, lsl #8
mov r0, #6
b instr_end
.ltorg
// RTS
_60:
pop
mov reg_pc, r0
pop
orr reg_pc, r0, lsl #8
add reg_pc, #1
rebase_pc reg_pc
mov r0, #6
b instr_end
// CLD
_d8:
bic reg_f, #FLAG_DEC
mov r0, #2
b instr_end
// JSR
_20:
unbase_pc r4
add r4, #1
mov r0, r4, lsr #8
push r0
and r4, #0xff
push r4
adr_abs_z
mov reg_pc, r0
rebase_pc reg_pc
mov r0, #6
b instr_end
// STX
_86:
adr_zp_z
ldr r1, =mainram
strb reg_x, [r1, r0]
mov r0, #3
b instr_end
_96:
adr_zp reg_y
ldr r1, =mainram
strb reg_x, [r1, r0]
mov r0, #4
b instr_end
_8e:
adr_abs_z
mov r1, reg_x
bl writeb
mov r0, #4
b instr_end
// LDY
_a0:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
fetch
movs reg_y, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #2
b instr_end
_a4:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_zp_z
ldr r1, =mainram
ldrb reg_y, [r1, r0]
movs reg_y, reg_y, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #3
b instr_end
.ltorg
_b4:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_zp reg_x
ldr r1, =mainram
ldrb reg_y, [r1, r0]
movs reg_y, reg_y, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #4
b instr_end
_ac:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_abs_z
bl readb
movs reg_y, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #4
b instr_end
_bc:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_abs reg_x
bl readb
movs reg_y, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #4
b instr_end
// STY
_84:
adr_zp_z
ldr r1, =mainram
strb reg_y, [r1, r0]
mov r0, #3
b instr_end
_94:
adr_zp reg_x
ldr r1, =mainram
strb reg_y, [r1, r0]
mov r0, #4
b instr_end
_8c:
adr_abs_z
mov r1, reg_y
bl writeb
mov r0, #4
b instr_end
.ltorg
// BVS
_70:
tst reg_f, #FLAG_OVER
addeq reg_pc, #1
mov r0, #2
beq instr_end
adr_rel
mov r0, #3
b instr_end
// BVC
_50:
tst reg_f, #FLAG_OVER
addne reg_pc, #1
mov r0, #2
bne instr_end
adr_rel
mov r0, #3
b instr_end
// LDA
_a9:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
fetch
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #2
b instr_end
_a5:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_zp_z
ldr r1, =mainram
ldrb reg_a, [r1, r0]
movs reg_a, reg_a, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #3
b instr_end
_b5:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_zp reg_x
ldr r1, =mainram
ldrb reg_a, [r1, r0]
movs reg_a, reg_a, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #4
b instr_end
_ad:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_abs_z
bl readb
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #4
b instr_end
_bd:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_abs reg_x
bl readb
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #4
b instr_end
_b9:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_abs reg_y
bl readb
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #4
b instr_end
_a1:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_idx_x
bl readb
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #6
b instr_end
_b1:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_idx_y
bl readb
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #5
b instr_end
// STA
_85:
adr_zp_z
ldr r1, =mainram
strb reg_a, [r1, r0]
mov r0, #3
b instr_end
_95:
adr_zp reg_x
ldr r1, =mainram
strb reg_a, [r1, r0]
mov r0, #4
b instr_end
_8d:
adr_abs_z
mov r1, reg_a
bl writeb
mov r0, #4
b instr_end
_9d:
adr_abs reg_x
mov r1, reg_a
bl writeb
mov r0, #5
b instr_end
_99:
adr_abs reg_y
mov r1, reg_a
bl writeb
mov r0, #5
b instr_end
_81:
adr_idx_x
mov r1, reg_a
bl writeb
mov r0, #6
b instr_end
_91:
adr_idx_y
mov r1, reg_a
bl writeb
mov r0, #6
b instr_end
// JMP
_4c:
adr_abs_z
mov reg_pc, r0
rebase_pc reg_pc
mov r0, #3
b instr_end
_6c:
adr_idx
mov reg_pc, r0
rebase_pc reg_pc
mov r0, #5
b instr_end
// PHA
_48:
push reg_a
mov r0, #3
b instr_end
// PLA
_68:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
pop
movs reg_a, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #4
b instr_end
// LSR
_4a:
op_lsr reg_a
mov r0, #2
b instr_end
_46:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_lsr r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_56:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_lsr r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_4e:
adr_abs_z
mov r4, r0
bl readb
op_lsr r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_5e:
adr_abs reg_x
mov r4, r0
bl readb
op_lsr r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// ADC
_69:
fetch
op_adc r0
mov r0, #2
b instr_end
_65:
adr_zp_z
ldr r1, =mainram
ldrb r0, [r1, r0]
op_adc r0
mov r0, #3
b instr_end
_75:
adr_zp reg_x
ldr r1, =mainram
ldrb r0, [r1, r0]
op_adc r0
mov r0, #4
b instr_end
_6d:
adr_abs_z
bl readb
op_adc r0
mov r0, #4
b instr_end
_7d:
adr_abs reg_x
bl readb
op_adc r0
mov r0, #4
b instr_end
_79:
adr_abs reg_y
bl readb
op_adc r0
mov r0, #4
b instr_end
_61:
adr_idx_x
bl readb
op_adc r0
mov r0, #6
b instr_end
_71:
adr_idx_y
bl readb
op_adc r0
mov r0, #5
b instr_end
// SBC
_e9:
fetch
op_sbc r0
mov r0, #2
b instr_end
_e5:
adr_zp_z
ldr r1, =mainram
ldrb r0, [r1, r0]
op_sbc r0
mov r0, #3
b instr_end
_f5:
adr_zp reg_x
ldr r1, =mainram
ldrb r0, [r1, r0]
op_sbc r0
mov r0, #4
b instr_end
_ed:
adr_abs_z
bl readb
op_sbc r0
mov r0, #4
b instr_end
_fd:
adr_abs reg_x
bl readb
op_sbc r0
mov r0, #4
b instr_end
_f9:
adr_abs reg_y
bl readb
op_sbc r0
mov r0, #4
b instr_end
_e1:
adr_idx_x
bl readb
op_sbc r0
mov r0, #6
b instr_end
_f1:
adr_idx_y
bl readb
op_sbc r0
mov r0, #5
b instr_end
.ltorg
// LDX
_a2:
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
fetch
movs reg_x, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #2
b instr_end
_a6:
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
adr_zp_z
ldr r1, =mainram
ldrb reg_x, [r1, r0]
movs reg_x, reg_x, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #3
b instr_end
_b6:
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
adr_zp reg_y
ldr r1, =mainram
ldrb reg_x, [r1, r0]
movs reg_x, reg_x, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #4
b instr_end
_ae:
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
adr_abs_z
bl readb
movs reg_x, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #4
b instr_end
_be:
bic reg_f, #(FLAG_NEG+FLAG_ZERO)
adr_abs reg_y
bl readb
movs reg_x, r0, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #4
b instr_end
// CPX
_e0:
fetch
op_cmp reg_x, r0
mov r0, #2
b instr_end
_e4:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_cmp reg_x, r2
mov r0, #3
b instr_end
_ec:
adr_abs_z
bl readb
op_cmp reg_x, r0
mov r0, #4
b instr_end
// CMP
_c9:
fetch
op_cmp reg_a, r0
mov r0, #2
b instr_end
_c5:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_cmp reg_a, r2
mov r0, #3
b instr_end
_d5:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_cmp reg_a, r2
mov r0, #4
b instr_end
_cd:
adr_abs_z
bl readb
op_cmp reg_a, r0
mov r0, #4
b instr_end
_dd:
adr_abs reg_x
bl readb
op_cmp reg_a, r0
mov r0, #4
b instr_end
_d9:
adr_abs reg_y
bl readb
op_cmp reg_a, r0
mov r0, #4
b instr_end
_c1:
adr_idx_x
bl readb
op_cmp reg_a, r0
mov r0, #6
b instr_end
_d1:
adr_idx_y
bl readb
op_cmp reg_a, r0
mov r0, #5
b instr_end
// CPY
_c0:
fetch
op_cmp reg_y, r0
mov r0, #2
b instr_end
_c4:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_cmp reg_y, r2
mov r0, #3
b instr_end
_cc:
adr_abs_z
bl readb
op_cmp reg_y, r0
mov r0, #4
b instr_end
// EOR
_49:
fetch
op_eor r0
mov r0, #2
b instr_end
_45:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_eor r2
mov r0, #3
b instr_end
_55:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_eor r2
mov r0, #4
b instr_end
_4d:
adr_abs_z
bl readb
op_eor r0
mov r0, #4
b instr_end
_5d:
adr_abs reg_x
bl readb
op_eor r0
mov r0, #4
b instr_end
_59:
adr_abs reg_y
bl readb
op_eor r0
mov r0, #4
b instr_end
_41:
adr_idx_x
bl readb
op_eor r0
mov r0, #6
b instr_end
_51:
adr_idx_y
bl readb
op_eor r0
mov r0, #5
b instr_end
// INC
_e6:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_inc r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_f6:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_inc r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_ee:
adr_abs_z
mov r4, r0
bl readb
op_inc r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_fe:
adr_abs reg_x
mov r4, r0
bl readb
op_inc r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// INY
_c8:
op_inc reg_y
mov r0, #2
b instr_end
// INX
_e8:
op_inc reg_x
mov r0, #2
b instr_end
// DEX
_ca:
op_dec reg_x
mov r0, #2
b instr_end
.ltorg
// DEY
_88:
op_dec reg_y
mov r0, #2
b instr_end
// SEC
_38:
orr reg_f, #FLAG_CARRY
mov r0, #2
b instr_end
// SED
_f8:
orr reg_f, #FLAG_DEC
mov r0, #2
b instr_end
// TAX
_aa:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
movs reg_x, reg_a, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_x, #24
mov r0, #2
b instr_end
// TAY
_a8:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
movs reg_y, reg_a, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_y, #24
mov r0, #2
b instr_end
// TXA
_8a:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
movs reg_a, reg_x, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #2
b instr_end
// TYA
_98:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
movs reg_a, reg_y, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
lsr reg_a, #24
mov r0, #2
b instr_end
// TXS
_9a:
mov reg_sp, reg_x
rebase_sp reg_sp
mov r0, #2
b instr_end
// TSX
_ba:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
unbase_sp reg_x
orreq reg_f, #FLAG_ZERO
movs r1, reg_x, lsl #24
orrmi reg_f, #FLAG_NEG
mov r0, #2
b instr_end
// DEC
_c6:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_dec r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_d6:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_dec r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_ce:
adr_abs_z
mov r4, r0
bl readb
op_dec r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_de:
adr_abs reg_x
mov r4, r0
bl readb
op_dec r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// CLC
_18:
bic reg_f, #FLAG_CARRY
mov r0, #2
b instr_end
// PHP
_08:
mov r0, reg_f, lsr #24
orr r0, #0x30 // MAGIC!
push r0
mov r0, #3
b instr_end
// PLP
_28:
pop
mov reg_f, r0, lsl #24
mov r0, #4
b instr_end
// ROL
_2a:
op_rol reg_a
mov r0, #2
b instr_end
_26:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_rol r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_36:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_rol r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_2e:
adr_abs_z
mov r4, r0
bl readb
op_rol r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_3e:
adr_abs reg_x
mov r4, r0
bl readb
op_rol r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// ROR
_6a:
op_ror reg_a
mov r0, #2
b instr_end
_66:
adr_zp_z
ldr r1, =mainram
ldrb r2, [r1, r0]
op_ror r2
strb r2, [r1, r0]
mov r0, #5
b instr_end
_76:
adr_zp reg_x
ldr r1, =mainram
ldrb r2, [r1, r0]
op_ror r2
strb r2, [r1, r0]
mov r0, #6
b instr_end
_6e:
adr_abs_z
mov r4, r0
bl readb
op_ror r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #6
b instr_end
_7e:
adr_abs reg_x
mov r4, r0
bl readb
op_ror r0
mov r1, r0
mov r0, r4
bl writeb
mov r0, #7
b instr_end
// SEI
_78:
orr reg_f, #FLAG_INTR
mov r0, #2
b instr_end
// CLI
_58:
bic reg_f, #FLAG_INTR
mov r0, #2
b instr_end
// CLV
_b8:
bic reg_f, #FLAG_OVER
mov r0, #2
b instr_end
// LAX
_b7:
bic reg_f, #(FLAG_ZERO+FLAG_NEG)
adr_zp reg_y
ldr r1, =mainram
ldrb reg_a, [r1, r0]
movs reg_x, reg_a, lsl #24
orreq reg_f, #FLAG_ZERO
orrmi reg_f, #FLAG_NEG
mov reg_x, reg_a
mov r0, #4
b instr_end
// DOP
_04:
add reg_pc, #1
mov r0, #3
b instr_end
// TOP
_fc:
add reg_pc, #2
mov r0, #4
b instr_end
// SLO
_07:
adr_zp_z
ldr r2, =mainram
ldrb r1, [r2, r0]
movs r1, r1, lsl #25
orrcs reg_f, #FLAG_CARRY
lsr r1, #24
strb r1, [r2, r0]
op_ora r1
mov r0, #5
b instr_end
// http://emu-docs.org/CPU%2065xx/undocop.txt
_xx:
// Stop the vblank irq
#if 1
ldr r3, =0x4000210
ldr r2, [r3]
bic r2, #1
str r2, [r3]
#endif
mov r1, r0
ldr r0, =unhandled_msg
mov r2, reg_a
mov r3, reg_x
stmfd sp!, {reg_y,reg_sp,reg_pc}
bl iprintf
k: b k
// int cpu_run_1 (int cycles_to_do)
cpu_run:
stmfd sp!, {r4-r12, lr}
ldr r1, =cpu_regs
ldmia r1, {reg_f-reg_pc}
mov cycles, r0
loop:
fetch
#if 0
unbase_pc reg_pc
mov r3, reg_pc, lsr #12
cmp r3, #0xf
beq e
stmfd sp!, {reg_pc,r0}
ldr r0, =debug_msg
mov r1, reg_a
mov r2, reg_x
mov r3, reg_y
bl iprintf
ldmfd sp!, {reg_pc,r0}
e: rebase_pc reg_pc
#endif
ldr pc, [pc, r0, lsl #2]
nop
op_tab:
.word _00,_01,_xx,_xx,_04,_05,_06,_07,_08,_09,_0a,_xx,_xx,_0d,_0e,_xx
.word _10,_11,_xx,_xx,_xx,_15,_16,_xx,_18,_19,_xx,_xx,_xx,_1d,_1e,_xx
.word _20,_21,_xx,_xx,_24,_25,_26,_xx,_28,_29,_2a,_xx,_2c,_2d,_2e,_xx
.word _30,_31,_xx,_xx,_xx,_35,_36,_xx,_38,_39,_xx,_xx,_xx,_3d,_3e,_xx
.word _40,_41,_xx,_xx,_xx,_45,_46,_xx,_48,_49,_4a,_xx,_4c,_4d,_4e,_xx
.word _50,_51,_xx,_xx,_xx,_55,_56,_xx,_58,_59,_xx,_xx,_xx,_5d,_5e,_xx
.word _60,_61,_xx,_xx,_xx,_65,_66,_xx,_68,_69,_6a,_xx,_6c,_6d,_6e,_xx
.word _70,_71,_xx,_xx,_xx,_75,_76,_xx,_78,_79,_7a,_xx,_xx,_7d,_7e,_xx
.word _xx,_81,_xx,_xx,_84,_85,_86,_xx,_88,_xx,_8a,_xx,_8c,_8d,_8e,_xx
.word _90,_91,_xx,_xx,_94,_95,_96,_xx,_98,_99,_9a,_xx,_xx,_9d,_xx,_xx
.word _a0,_a1,_a2,_xx,_a4,_a5,_a6,_xx,_a8,_a9,_aa,_xx,_ac,_ad,_ae,_xx
.word _b0,_b1,_xx,_xx,_b4,_b5,_b6,_b7,_b8,_b9,_ba,_xx,_bc,_bd,_be,_xx
.word _c0,_c1,_xx,_xx,_c4,_c5,_c6,_xx,_c8,_c9,_ca,_xx,_cc,_cd,_ce,_xx
.word _d0,_d1,_xx,_xx,_xx,_d5,_d6,_xx,_d8,_d9,_xx,_xx,_xx,_dd,_de,_xx
.word _e0,_e1,_xx,_xx,_e4,_e5,_e6,_xx,_e8,_e9,_ea,_xx,_ec,_ed,_ee,_xx
.word _f0,_f1,_xx,_xx,_xx,_f5,_f6,_xx,_f8,_f9,_xx,_xx,_fc,_fd,_fe,_xx
instr_end:
subs cycles, r0
bpl loop
mov r0, cycles
// Copy the regs back to mem
ldr r1, =cpu_regs
stmia r1, {reg_f-reg_pc}
// Return the undone cycles
ldmfd sp!, {r4-r12, pc}
cpu_reset:
stmfd sp!, {r4-r6, lr}
ldr r4, =0xfffd
mov r0, r4
bl readb
mov r5, r0, lsl #8
sub r0, r4, #1
bl readb
orr r0, r5
ldr r6, =cpu_regs
mov r5, r0 // r5 = pc
mov r4, #0xfd // r4 = sp
rebase_pc r5
rebase_sp r4
mov r0, #0 // r0 = f
mov r1, #0 // r1 = y
mov r2, #0 // r2 = x
mov r3, #0 // r3 = a
stmia r6!, {r0-r5}
ldmfd sp!, {r4-r6, pc}
cpu_regs:
.word 0,0,0,0,0,0
last_page:
.word 0
unhandled_msg:
.ascii "Unhandled op\n"
debug_msg:
.ascii "A%02x X%02x Y%02x P%04x OP %02x\n"
.byte 0