1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
.arm
.align 4
.data
.extern v810_state, serviceDisplayInt, serviceInt, serviceint, tVBOpt
.text
.macro ldRegs
ldr r11, =v810_state
ldr r11, [r11]
@ Load the CPSR
ldr r3, [r11, #(34*4)]
msr cpsr_f, r3
@ Load the address of the reg map (block+17)
add r3, r1, #17
@ Load cached V810 registers
ldrb r2, [r3], #1
ldr r4, [r11, r2, lsl #2]
ldrb r2, [r3], #1
ldr r5, [r11, r2, lsl #2]
ldrb r2, [r3], #1
ldr r6, [r11, r2, lsl #2]
ldrb r2, [r3], #1
ldr r7, [r11, r2, lsl #2]
ldrb r2, [r3], #1
ldr r8, [r11, r2, lsl #2]
ldrb r2, [r3], #1
ldr r9, [r11, r2, lsl #2]
.endm
.macro stRegs
ldr r11, =v810_state
ldr r11, [r11]
@ Load the address of the reg map (block+17)
add r1, r0, #17
@ Save the CPSR
mrs r3, cpsr
str r3, [r11, #(34*4)]
@ Store cached V810 registers
ldrb r2, [r1], #1
str r4, [r11, r2, lsl #2]
ldrb r2, [r1], #1
str r5, [r11, r2, lsl #2]
ldrb r2, [r1], #1
str r6, [r11, r2, lsl #2]
ldrb r2, [r1], #1
str r7, [r11, r2, lsl #2]
ldrb r2, [r1], #1
str r8, [r11, r2, lsl #2]
ldrb r2, [r1], #1
str r9, [r11, r2, lsl #2]
.endm
@ void drc_executeBlock(WORD* entrypoint, exec_block* block);
.globl drc_executeBlock
drc_executeBlock:
push {r4-r11, ip, lr}
push {r1}
@ The last instruction on the block should be "pop {pc}"
ldr lr, =postexec
push {lr}
ldRegs
@ r10 = -MAXCYCLES
ldr r10, =tVBOpt
ldr r10, [r10]
neg r10, r10
bx r0
postexec:
pop {r0}
stRegs
@ v810_state->cycles += MAXCYCLES + r10 excess
ldr r0, =tVBOpt
ldr r0, [r0]
add r10, r0
ldr r0, [r11, #67<<2]
add r0, r10
str r0, [r11, #67<<2]
pop {r4-r11, ip, pc}
@ Checks for pending interrupts and exits the block if necessary
.globl drc_handleInterrupts
drc_handleInterrupts:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
@ Load v810_state->cycles and add it to the total number of cycles
@ (MAXCYCLES + r10 excess)
ldr r0, [r11, #67<<2]
add r0, r10
ldr r2, =tVBOpt
ldr r2, [r2]
add r0, r2
str r0, [r11, #67<<2]
bl serviceDisplayInt
cmp r0, #0
bne exit_block
ldr r0, [r11, #67<<2]
mov r1, r5
bl serviceInt
cmp r0, #0
bne exit_block
ret_to_block:
@ r10 = -MAXCYCLES
ldr r10, =tVBOpt
ldr r10, [r10]
neg r10, r10
@ Return to the block
mov r0, r4
pop {r4, r5, pc}
exit_block:
@ Restore CPSR
msr cpsr_f, r4
@ Exit the block ignoring linked return address
pop {r4, r5}
pop {r0, pc}
|