#define OTOFFS_NES_STACK (nes_stack - cpu_exec_table)
#define OTOFFS_NES_REGS (nes_registers - cpu_exec_table)
#define OTOFFS_PC_BASE (pc_base - cpu_exec_table)
+#define OTOFFS_IRQ_HOOK (MapIRQHook - cpu_exec_table)
+#define OTOFFS_TIMESTAMP (timestamp - cpu_exec_table)
+#define OTOFFS_X (X_ - cpu_exec_table)
@ fceu
#define FCEU_IQNMI 0x08
SECTION_TEXT
ALIGN
-
+/*
+bbbb:
+.ascii "lsr_a: %02x"
+.byte 0x0a,0
+.align 4
+stmfd sp!,{r0-r3,r12,lr}
+mov r1,r0
+ldr r0,=bbbb
+bl printf
+ldmfd sp!,{r0-r3,r12,lr}
+*/
@@@
@@@ r0 = Address (unbased)
@@@
.macro REBASE_PC
@ FIXME: do something with mem not in Page[].
+@ stmfd sp!, {r0-r3,r12,lr}
+@ mov r1, r0
+@ ldr r0, =bbbb
+@ bl printf
+@ ldmfd sp!, {r0-r3,r12,lr}
+
cmp r0, #0x2000
ldrge r1, =Page
movge r2, r0, lsr #11
.endm
-.macro RETURN_FROM_CPU_EXEC
- b cpu_exec_end
+@ updates fceu "timestamp" variable
+@ loads cycles to reg, reg!=r1, trashes r1
+.macro FLUSH_TIMESTAMP reg
+ ldr r1, [REG_OP_TABLE, #OTOFFS_TIMESTAMP]
+ and \reg, REG_CYCLE, #0xff
+ add r1, r1, \reg
+ bic REG_CYCLE, REG_CYCLE, #0xff
+ str r1, [REG_OP_TABLE, #OTOFFS_TIMESTAMP]
.endm
@@@
@@@ ¤Ê¤ó¤«Ì¾Á°¤¬ÊѤÀ¤Ê(¤É¡¼¤Ç¤â¤¤¡¼¤±¤É¡¼
@@@
-.macro CYCLE_NEXT n
+.macro CYCLE_NEXT n, hook_check=1
@@DEBUG_INFO
- subs REG_CYCLE, REG_CYCLE, #\n*48
+ add REG_CYCLE, REG_CYCLE, #\n
+ subs REG_CYCLE, REG_CYCLE, #\n*48<<16
ble cpu_exec_end
+.if \hook_check
+ tst REG_P_REST, #1<<16
+ blne do_irq_hook
+.endif
ldrb r0, [REG_PC], #1
tst REG_P_REST, #0xff<<8
ldreq pc, [REG_OP_TABLE, r0, lsl #2]
@@@ CLI¡¦PHP¤Ê¤É¥Õ¥é¥°¤òÊѹ¹¤·¤¿¾ì¹ç¤Ï¤³¤ì
@@@
.macro CYCLE_NEXT_INT n
-@ @@DEBUG_INFO
-@
-@ subs REG_CYCLE, REG_CYCLE, #\n*48
-@ bgt cpu_exec_check_int
-@ RETURN_FROM_CPU_EXEC
CYCLE_NEXT \n
.endm
strb r0, [REG_ADDR]
.endm
-.macro READ_WRITE_3
- .long read_rom_byte
- .long read_rom_byte
- .long read_rom_byte
- .long read_rom_byte
- .long read_save_ram
- .long read_high_reg
- .long read_ppu_reg
-9999:
-.endm
-
-.macro READ_WRITE_4
+.macro READ_WRITE_W
adr lr, 1f
ldr pc, [pc, r3, lsl #2]
nop
1:
.endm
+.macro READ_WRITE_3
+ .long read_rom_byte
+ .long read_rom_byte
+ .long read_rom_byte
+ .long read_rom_byte
+ .long read_save_ram
+ .long read_high_reg
+ .long read_ppu_reg
+9999:
+ READ_WRITE_W @ rmw first writes unmodified data
+.endm
+
+.macro READ_WRITE_4
+ READ_WRITE_W @ and only then modified (Blaster Master)
+.endm
+
@@@
@@@ ½ñ¤¹þ¤ß¤À¤±¤Î¾ì¹ç
@@@
bic REG_ADDR, REG_ADDR, #0x10000
and r0,REG_ADDR,#0xff
cmp REG_Y,r0
- subgt REG_CYCLE,REG_CYCLE,#1*48
+ addgt REG_CYCLE, REG_CYCLE, #1
+ subgt REG_CYCLE, REG_CYCLE, #1*48<<16
+.endm
+
+@ Indirect Indexed (for writes and rmws)
+.macro INDY_ADDR_W
+ ZERO_ADDR
+ ZP_READ_ADDR
+ add REG_ADDR, REG_ADDR, REG_Y
+ bic REG_ADDR, REG_ADDR, #0x10000
.endm
bic REG_ADDR, REG_ADDR, #0x10000
and r0,REG_ADDR,#0xff
cmp REG_X,r0
- subgt REG_CYCLE,REG_CYCLE,#1*48
+ addgt REG_CYCLE, REG_CYCLE, #1
+ subgt REG_CYCLE, REG_CYCLE, #1*48<<16
+.endm
+
+@ Absolute Indexed (for writes and rmws)
+.macro ABSX_ADDR_W
+ ABS_ADDR
+ add REG_ADDR, REG_ADDR, REG_X
+ bic REG_ADDR, REG_ADDR, #0x10000
.endm
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bic REG_ADDR, REG_ADDR, #0x10000
and r0,REG_ADDR,#0xff
cmp REG_Y,r0
- subgt REG_CYCLE,REG_CYCLE,#1*48
+ addgt REG_CYCLE, REG_CYCLE, #1
+ subgt REG_CYCLE, REG_CYCLE, #1*48<<16
.endm
+@ Absolute Indexed (for writes and rmws)
+.macro ABSY_ADDR_W
+ ABS_ADDR
+ add REG_ADDR, REG_ADDR, REG_Y
+ bic REG_ADDR, REG_ADDR, #0x10000
+.endm
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
@@@ P ¤òÉü¸µ¤¹¤ë
@@@ r0 => 6502 ¤Î P ¥ì¥¸¥¹¥¿
@@@ REG_NZ <= Éü¸µ¤µ¤ì¤¿ REG_NZ
CYCLE_NEXT 4
op9D: @ STA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 5
op99: @ STA $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 6
op91: @ STA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 6
CYCLE_NEXT 6
opFE: @ INC $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_INC
READ_WRITE_2
CYCLE_NEXT 6
opDE: @ DEC $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_DEC
READ_WRITE_2
CYCLE_NEXT 6
op1E: @ ASL $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ASL
READ_WRITE_2
CYCLE_NEXT 6
op5E: @ LSR $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_LSR
READ_WRITE_2
op3E: @ ROL $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ROL
READ_WRITE_2
CYCLE_NEXT 6
op7E: @ ROR $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ROR
READ_WRITE_2
and r1,r1,#0xff
add r1,r3,r1
tst r1,#0x100
- subne REG_CYCLE,REG_CYCLE, #1*48
+ addne REG_CYCLE, REG_CYCLE, #1
+ subne REG_CYCLE, REG_CYCLE, #1*48<<16
.endm
.macro BRANCH_EQ
ldreqsb r1, [REG_PC], #1
movne r1, #1
add REG_PC, REG_PC, r1
- subeq REG_CYCLE, REG_CYCLE, #1*48
+ addeq REG_CYCLE, REG_CYCLE, #1
+ subeq REG_CYCLE, REG_CYCLE, #1*48<<16
bne 1f
HAD_BRANCH
1:
ldrnesb r1, [REG_PC], #1
moveq r1, #1
add REG_PC, REG_PC, r1
- subne REG_CYCLE, REG_CYCLE, #1*48
+ addne REG_CYCLE, REG_CYCLE, #1
+ subne REG_CYCLE, REG_CYCLE, #1*48<<16
beq 1f
HAD_BRANCH
1:
CYCLE_NEXT 8
op53: @ SRE ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_SRE
READ_WRITE_2
op9C: @ SHY $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
OP_SHY
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 7
op1B: @ SLO $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
READ_WRITE_1
OP_SLO
READ_WRITE_2
CYCLE_NEXT 8
op13: @ SLO ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_SLO
READ_WRITE_2
CYCLE_NEXT 6
op3F: @ RLA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_RLA
READ_WRITE_2
CYCLE_NEXT 7
op3B: @ RLA $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
READ_WRITE_1
OP_RLA
- READ_WRITE_2
- CYCLE_NEXT 7
+ READ_WRITE_2
+ CYCLE_NEXT 7
READ_WRITE_3
OP_RLA
READ_WRITE_4
CYCLE_NEXT 8
op33: @ RLA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_RLA
READ_WRITE_2
CYCLE_NEXT 6
op7F: @ RRA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
CYCLE_NEXT 7
op7B: @ RRA $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
CYCLE_NEXT 8
op73: @ RRA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
@@@
@@@ ³ä¤ê¹þ¤ß¤Î½èÍý
+@@@ WARNING: decrements REG_PC
@@@
do_int:
ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE]
+ sub REG_PC, REG_PC, #1
sub r0, REG_PC, r0
PUSH_WORD
bic REG_P_REST, REG_P_REST, #P_REST_B_FLAG
subne REG_ADDR, REG_ADDR, #NMI_VECTOR
READ_WORD
REBASE_PC
- CYCLE_NEXT 7
+@ CYCLE_NEXT 7
+
+ add REG_CYCLE, REG_CYCLE, #7
+ subs REG_CYCLE, REG_CYCLE, #7*48<<16
+ ble cpu_exec_end
+ ldrb r0, [REG_PC], #1
+ tst REG_P_REST, #0xff<<8
+ ldreq pc, [REG_OP_TABLE, r0, lsl #2]
+
+ tst REG_P_REST, #P_REST_I_FLAG
+ ldrne pc, [REG_OP_TABLE, r0, lsl #2]
+ b do_int
+
@@@
@@@ ¥ê¥»¥Ã¥È¤Î½èÍý
@@REG_P_REST = 0, don't touch REG_S
bic REG_P_REST, REG_P_REST, #0xff
+ @ fceu: set MapIRQHook present flag
+ ldr r0, [REG_OP_TABLE, #OTOFFS_IRQ_HOOK]
+ tst r0, r0
+ orrne REG_P_REST, REG_P_REST, #1<<16
+ biceq REG_P_REST, REG_P_REST, #1<<16
+
@@ R bit is always 1
orr REG_NZ, REG_NZ, #P_R_FLAG
@@@ low-level memhandlers
@@@
+read_rom_byte:
+#ifndef DEBUG_ASM_6502
+ ldr r0, =CartBR
+ ldr r2, =ARead
+ mov r1, #0xff00
+ orr r1, r1, r1, lsr #4
+ ldr r1, [r2, r1, lsl #2] @ if (ARead[0xfff0] == CartBR)
+ cmp r0, r1
+ bne read_ppu_reg
+ ldr r2, =Page
+ mov r1, REG_ADDR, lsr #11
+ ldr r2, [r2, r1, lsl #2]
+ ldrb r0, [r2, REG_ADDR]
+ bx lr
+#endif
+
+
read_ppu_reg:
read_high_reg:
read_save_ram:
-read_rom_byte:
@ must preserve r3 for the callers too
- @ TODO: check if all of saves are needed, optimize read_rom_byte, _DB
+ @ TODO: check if all of saves are needed, _DB (is full needed?)
str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased
str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
str REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used
mov REG_PC, lr @ r7
mov REG_P_REST, r3 @ r8
+#ifndef DEBUG_ASM_6502
ldr r2, =ARead
bic r0, REG_ADDR, #0x00ff0000
mov lr, pc
ldr pc, [r2, r0, lsl #2]
+#else
+ ldr r2, =dread_count_a
+ ldr r0, =dreads
+ ldr r1, [r2]
+ ldrb r0, [r0, r1]
+ add r1, r1, #1
+ str r1, [r2]
+#endif
ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12
mov lr, REG_PC
ldr REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased
ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
ldr REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used
+ strb r0, [REG_OP_TABLE, #(OTOFFS_X + 0x10)] @ X.DB
bx lr
write_high_reg:
write_save_ram:
write_rom_byte:
- @ must preserve r3 for the callers too
+ FLUSH_TIMESTAMP r2 @ Blaster Master, more...
+#ifndef DEBUG_ASM_6502
+ @ must preserve r0 (data) and r3 for the callers
str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased
str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
str REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used
mov REG_PC, lr @ r7
mov REG_P_REST, r3 @ r8
+ mov REG_CYCLE, r0 @ r11
ldr r2, =BWrite
mov r1, r0
ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12
mov lr, REG_PC
mov r3, REG_P_REST
+ mov r0, REG_CYCLE
ldr REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased
ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
ldr REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used
+#else
+ ldr r1, =dwrite_count_a
+ ldr r2, =dwrites_a
+ ldr r1, [r1]
+ and r0, r0, #0xff
+ orr r0, r0, REG_ADDR, lsl #8
+ str r0, [r2, r1, lsl #2]
+ ldr r2, =dwrite_count_a
+ add r1, r1, #1
+ str r1, [r2]
+ and r0, r0, #0xff
+#endif
bx lr
@ ldr REG_OP_TABLE, = cpu_exec_table @ set on init
- CYCLE_NEXT 0
+ CYCLE_NEXT 0, 0
cpu_exec_end:
+ FLUSH_TIMESTAMP r0
+
+ tst REG_P_REST, #1<<16
+ blne do_irq_hook_noflushts
+
ldr r0, =nes_registers
stmia r0, {r4-r12}
@ TODO: write code which keeps it up-to-date
pc_base:
.long 0
+MapIRQHook:
+ .long 0
+timestamp:
+timestamp_a:
+ .long 0
+#ifndef DEBUG_ASM_6502
+X:
+#endif
+X_: .fill 0x20, 1, 0
.pool
@op37: @ RLA $nn, X
@op2F: @ RLA $nnnn
@op3F: @ RLA $nnnn, X
-@op3B: @ RLA $nnnn, Y
@op23: @ RLA ($nn, X)
-@op33: @ RLA ($nn), Y
@op67: @ RRA $nn
@op77: @ RRA $nn, X
@op6F: @ RRA $nnnn
@op7F: @ RRA $nnnn, X
-@op7B: @ RRA $nnnn, Y
@op63: @ RRA ($nn, X)
-@op73: @ RRA ($nn), Y
op87: @ SAX $nn
op97: @ SAX $nn, Y
op8F: @ SAX $nnnn
op93: @ SHA ($nn), Y
op9B: @ SHS $nnnn, Y
op9E: @ SHX $nnnn, Y
-@op9C: @ SHY $nnnn, X
@op03: @ SLO ($nn, X)
@op07: @ SLO $nn
@op17: @ SLO $nn, X
@op0F: @ SLO $nnnn
@op1F: @ SLO $nnnn, X
-@op1B: @ SLO $nnnn, Y
-@op13: @ SLO ($nn), Y
@op47: @ SRE $nn
@op57: @ SRE $nn, X
@op4F: @ SRE $nnnn
@op5F: @ SRE $nnnn, X
@op5B: @ SRE $nnnn, Y
@op43: @ SRE ($nn, X)
-@op53: @ SRE ($nn), Y
CYCLE_NEXT 1
@ emu_panic?
.extern Page
.extern ARead
.extern BWrite
+.extern MapIRQHook
SECTION_DATA
ALIGN
-@ .globl X
- .globl RAM
.globl nes_registers @ TODO: hide?
.globl pc_base
-@ .globl timestamp
-@ .globl MapIRQHook @ (int a)
-@ TODO... .. conversion X <-> nes_registers for savestates
-@timestamp: .long 0
-@MapIRQHook: .long 0
-@X: .fill 0x20, 1, 0
+ .globl MapIRQHook @ (int a)
+#ifndef DEBUG_ASM_6502
+ .globl X
+ .globl RAM
+ .globl timestamp
+#else
+ .globl nes_internal_ram
+ .globl timestamp_a
+#endif
.globl X6502_Reset_a @ (void);
.globl X6502_Power_a @ (void);
.globl X6502_Run_a @ (int32 cycles);
.globl X6502_AddCycles_a @ (int x);
.globl X6502_IRQBegin_a @ (int w);
.globl X6502_IRQEnd_a @ (int w);
- .globl X6502_rebase_a @ (void);
+ .globl X6502_Rebase_a @ (void);
SECTION_TEXT
ALIGN
TriggerNMI_a:
- mov r0, #FCEU_IQTEMP
+ mov r0, #FCEU_IQNMI
b X6502_IRQBegin_a
X6502_AddCycles_a:
ldr r2, =nes_registers
- ldr r1, [r2, #0x1c]
- mvn r3, #49
+ ldrsh r1, [r2, #0x1e]
+ mvn r3, #47 @ r3=-48
mla r0, r3, r0, r1
- str r0, [r2, #0x1c]
+ strh r0, [r2, #0x1e]
bx lr
@ rebase PC when not executing or in memhandlers
-X6502_rebase_a:
+X6502_Rebase_a:
stmfd sp!,{REG_PC,REG_OP_TABLE}
ldr REG_OP_TABLE, =cpu_exec_table
ldr r0, [REG_OP_TABLE, #(OTOFFS_NES_REGS+0x0c)] @ PC
.pool
+@ the nasty MapIRQHook thing from FCE..
+@ test Gradius 2 (J) if you change this
+do_irq_hook:
+ FLUSH_TIMESTAMP r0
+
+do_irq_hook_noflushts:
+#ifndef DEBUG_ASM_6502
+ @ I have reviewed all MapIRQHook functions, they only seem to cause IRQs, not messing cycles or something
+ str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
+ mov REG_P_REST, lr @ r8
+
+ @ if somebody modifies MapIRQHook without calling reset, we are doomed
+ mov lr, pc
+ ldr pc, [REG_OP_TABLE, #OTOFFS_IRQ_HOOK]
+
+ ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12
+ mov lr, REG_P_REST
+ ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq
+#else
+ ldr r1, =mapirq_cyc_a
+ str r0, [r1]
+ mov r1, r0
+#endif
+ bx lr
+
+
@ vim:filetype=armasm