1@ vim:filetype=armasm
2
3@ ranges/opcodes (idle, normal):
4@ 71xx, 73xx  - bne.s (8bit offset)
5@ 75xx, 77xx  - beq.s (8bit offset)
6@ 7dxx, 7fxx  - bra.s (8bit offset)
7
8.data
9.align 2
10
11idle_data:
12have_patches:
13  .word 0
14  .word Op____
15  .word Op6002
16  .word Op6602
17  .word Op6702
18
19.equ patch_desc_table_size, 10
20
21@       to             from
22patch_desc_table:
23  .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6602  @ bne.s
24  .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6602  @ bne.s
25  .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6602  @ bne.s
26  .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6602  @ bne.s
27  .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6702  @ beq.s
28  .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6702  @ beq.s
29  .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6702  @ beq.s
30  .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6702  @ beq.s
31  .word (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6002  @ bra.s
32  .word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6002  @ bra.s
33
34
35.text
36.align 2
37
38
39.global CycloneInitIdleJT @ jt
40
41CycloneInitIdleJT:
42    adr     r12,offset_table
43    ldr     r2, [r12, #1*4] @ =patch_desc_table-ot
44    mov     r3, r0          @ =CycloneJumpTab
45    add     r2, r2, r12
46    mov     r12,#patch_desc_table_size
47
48cii_loop:
49    ldrh    r0, [r2]
50    ldr     r1, [r2, #4]           @ detector
51    str     r1, [r3, r0, lsl #2]
52    ldrh    r0, [r2, #2]
53    ldr     r1, [r2, #8]           @ idle
54    add     r0, r3, r0, lsl #2
55    str     r1, [r0]
56    ldr     r1, [r2, #12]          @ normal
57    str     r1, [r0, #0x800]
58    add     r2, r2, #16
59    subs    r12,r12,#1
60    bgt     cii_loop
61
62    adr     r12,offset_table
63    ldr     r0, [r12, #0*4] @ =idle_data-ot
64    mov     r1, #1
65    str     r1, [r0, r12]   @ have_patches
66    bx      lr
67
68
69.global CycloneFinishIdleJT @ jt
70
71CycloneFinishIdleJT:
72    adr     r12,offset_table
73    ldr     r3, [r12, #0*4] @ =idle_data-ot
74    ldr     r1, [r3, r12]!  @ have_patches
75    tst     r1, r1
76    bxeq    lr
77
78    stmfd   sp!, {r4,r5}
79    mov     r5, r3
80    ldr     r2, [r12, #1*4] @ =patch_desc_table-ot
81    mov     r3, r0          @ =CycloneJumpTab
82    ldr     r4, [r5, #1*4]  @ =Op____
83    add     r2, r2, r12     @ =patch_desc_table
84    mov     r12,#patch_desc_table_size
85
86cfi_loop:
87    ldrh    r0, [r2]
88    ldr     r1, [r2, #12]         @ normal
89    str     r1, [r3, r0, lsl #2]
90    ldrh    r0, [r2, #2]
91    add     r0, r3, r0, lsl #2
92    str     r4, [r0]              @ Op____
93    str     r4, [r0, #0x800]
94    add     r2, r2, #16
95    subs    r12,r12,#1
96    bgt     cfi_loop
97
98    mov     r1, #0
99    str     r1, [r5]              @ have_patches
100    ldmfd   sp!, {r4,r5}
101    bx      lr
102
103
104
105.macro inc_counter cond
106@    ldr\cond r0, [r7, #0x60]
107@    mov     r11,lr
108@    sub     r0, r4, r0
109@    sub     r0, r0, #2
110@    bl\cond SekRegisterIdleHit
111@    mov     lr, r11
112.endm
113
114idle_bra:
115    mov     r5, #2
116    inc_counter
117    b       Op6002
118
119idle_bne:
120    tst     r10, #0x40000000      @ Z set?
121    moveq   r5, #2                @ 2 is intentional due to strange timing issues
122    inc_counter eq
123    b       Op6602
124
125idle_beq:
126    tst     r10, #0x40000000      @ Z set?
127    movne   r5, #2
128    inc_counter ne
129    b       Op6702
130
131
132@ @@@ @
133
134idle_detector_bcc8:
135    bl      SekIsIdleReady
136    tst     r0, r0
137    beq     exit_detector         @ not yet
138
139    mov     r0, r8, asl #24       @ Shift 8-bit signed offset up...
140    add     r0, r4, r0, asr #24   @ jump dest
141    bic     r0, r0, #1
142
143    mov     r1, #0
144    sub     r1, r1, r8, lsl #24
145    mov     r1, r1, lsr #24
146    sub     r1, r1, #2
147    bic     r1, r1, #1
148
149    bl      SekIsIdleCode
150    tst     r0, r0
151    and     r2, r8, #0x00ff
152    orr     r2, r2, #0x7100
153    orreq   r2, r2, #0x0200
154    mov     r0, r8, lsr #8
155    cmp     r0, #0x66
156    orrgt   r2, r2, #0x0400       @ 67xx (beq)
157    orrlt   r2, r2, #0x0c00       @ 60xx (bra)
158
159    @ r2 = patch_opcode
160    sub     r0, r4, #2
161    ldrh    r1, [r0]
162    mov     r11,r2
163    mov     r3, r7
164    bl      SekRegisterIdlePatch
165    cmp     r0, #1                @ 0 - ok to patch, 1 - no patch, 2 - remove detector
166    strlth  r11,[r4, #-2]
167    ble     exit_detector
168
169    @ remove detector from Cyclone
170    adr     r12,offset_table
171    ldr     r1, [r12]       @ =idle_data-ot
172    mov     r0, r8, lsr #8
173    cmp     r0, #0x66
174    add     r1, r1, r12     @ =idle_data
175    ldrlt   r1, [r1, #4*2]  @ =Op6002-ot
176    ldreq   r1, [r1, #4*3]  @ =Op6602-ot
177    ldrgt   r1, [r1, #4*4]  @ =Op6702-ot
178
179    str     r1, [r6, r8, lsl #2]
180    bx      r1
181
182exit_detector:
183    mov     r0, r8, lsr #8
184    cmp     r0, #0x66
185    blt     Op6002
186    beq     Op6602
187    b       Op6702
188
189offset_table:
190    .word idle_data - offset_table
191    .word patch_desc_table - offset_table
192