minor adjustments
[picodrive.git] / cpu / Cyclone / OpBranch.cpp
CommitLineData
cc68a136 1\r
2#include "app.h"\r
3\r
4#if USE_CHECKPC_CALLBACK\r
5static void CheckPc()\r
6{\r
7 ot(";@ Check Memory Base+pc (r4)\n");\r
8 ot(" add lr,pc,#4\n");\r
9 ot(" mov r0,r4\n");\r
10 ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");\r
11 ot(" mov r4,r0\n");\r
12 ot("\n");\r
13}\r
14#endif\r
15\r
16// Push 32-bit value in r1 - trashes r0-r3,r12,lr\r
17void OpPush32()\r
18{\r
19 ot(";@ Push r1 onto stack\n");\r
20 ot(" ldr r0,[r7,#0x3c]\n");\r
21 ot(" sub r0,r0,#4 ;@ Predecrement A7\n");\r
22 ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
23 MemHandler(1,2);\r
24 ot("\n");\r
25}\r
26\r
27// Push SR - trashes r0-r3,r12,lr\r
28void OpPushSr(int high)\r
29{\r
30 ot(";@ Push SR:\n");\r
31 OpFlagsToReg(high);\r
32 ot(" ldr r0,[r7,#0x3c]\n");\r
33 ot(" sub r0,r0,#2 ;@ Predecrement A7\n");\r
34 ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
35 MemHandler(1,1);\r
36 ot("\n");\r
37}\r
38\r
39// Pop SR - trashes r0-r3\r
40static void PopSr(int high)\r
41{\r
42 ot(";@ Pop SR:\n");\r
43 ot(" ldr r0,[r7,#0x3c]\n");\r
44 ot(" add r1,r0,#2 ;@ Postincrement A7\n");\r
45 ot(" str r1,[r7,#0x3c] ;@ Save A7\n");\r
46 MemHandler(0,1);\r
47 ot("\n");\r
48 OpRegToFlags(high);\r
49}\r
50\r
51// Pop PC - assumes r10=Memory Base - trashes r0-r3\r
52static void PopPc()\r
53{\r
54 ot(";@ Pop PC:\n");\r
55 ot(" ldr r0,[r7,#0x3c]\n");\r
56 ot(" add r1,r0,#4 ;@ Postincrement A7\n");\r
57 ot(" str r1,[r7,#0x3c] ;@ Save A7\n");\r
58 MemHandler(0,2);\r
59 ot(" add r4,r0,r10 ;@ r4=Memory Base+PC\n");\r
60 ot("\n");\r
a6785576 61#if USE_CHECKPC_CALLBACK\r
cc68a136 62 CheckPc();\r
a6785576 63#endif\r
cc68a136 64}\r
65\r
66int OpTrap(int op)\r
67{\r
68 int use=0;\r
69\r
70 use=op&~0xf;\r
71 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
72\r
a6785576 73 OpStart(op,0x10);\r
cc68a136 74 ot(" and r0,r8,#0xf ;@ Get trap number\n");\r
75 ot(" orr r0,r0,#0x20\n");\r
76 ot(" mov r0,r0,asl #2\n");\r
77 ot(" bl Exception\n");\r
78 ot("\n");\r
79\r
80 Cycles=38; OpEnd();\r
81\r
82 return 0;\r
83}\r
84\r
85// --------------------- Opcodes 0x4e50+ ---------------------\r
86int OpLink(int op)\r
87{\r
88 int use=0,reg;\r
89\r
90 use=op&~7;\r
91 reg=op&7;\r
92 if (reg==7) use=op;\r
93 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
94\r
a6785576 95 OpStart(op,0x10);\r
cc68a136 96\r
97 if(reg!=7) {\r
98 ot(";@ Get An\n");\r
99 EaCalc(10, 7, 8, 2, 1);\r
100 EaRead(10, 1, 8, 2, 7, 1);\r
101 }\r
102\r
103 ot(" ldr r0,[r7,#0x3c] ;@ Get A7\n");\r
104 ot(" sub r0,r0,#4 ;@ A7-=4\n");\r
105 ot(" mov r11,r0\n");\r
106 if(reg==7) ot(" mov r1,r0\n");\r
107 ot("\n");\r
108 \r
109 ot(";@ Write An to Stack\n");\r
110 MemHandler(1,2);\r
111\r
112 ot(";@ Save to An\n");\r
113 if(reg!=7)\r
114 EaWrite(10,11, 8, 2, 7, 1);\r
115\r
116 ot(";@ Get offset:\n");\r
117 EaCalc(0,0,0x3c,1);\r
118 EaRead(0,0,0x3c,1,0);\r
119\r
120 ot(" add r11,r11,r0 ;@ Add offset to A7\n");\r
121 ot(" str r11,[r7,#0x3c]\n");\r
122 ot("\n");\r
123\r
124 Cycles=16;\r
125 OpEnd();\r
126 return 0;\r
127}\r
128\r
129// --------------------- Opcodes 0x4e58+ ---------------------\r
130int OpUnlk(int op)\r
131{\r
132 int use=0;\r
133\r
134 use=op&~7;\r
135 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
136\r
a6785576 137 OpStart(op,0x10);\r
cc68a136 138\r
139 ot(";@ Get An\n");\r
140 EaCalc(10, 7, 8, 2, 1);\r
141 EaRead(10, 0, 8, 2, 7, 1);\r
142\r
143 ot(" add r11,r0,#4 ;@ A7+=4\n");\r
144 ot("\n");\r
145 ot(";@ Pop An from stack:\n");\r
146 MemHandler(0,2);\r
147 ot("\n");\r
148 ot(" str r11,[r7,#0x3c] ;@ Save A7\n");\r
149 ot("\n");\r
150 ot(";@ An = value from stack:\n");\r
151 EaWrite(10, 0, 8, 2, 7, 1);\r
152 \r
153 Cycles=12;\r
154 OpEnd();\r
155 return 0;\r
156}\r
157\r
158// --------------------- Opcodes 0x4e70+ ---------------------\r
159int Op4E70(int op)\r
160{\r
161 int type=0;\r
162\r
163 type=op&7; // 01001110 01110ttt, reset/nop/stop/rte/rtd/rts/trapv/rtr\r
164\r
165 switch (type)\r
166 {\r
167 case 1: // nop\r
168 OpStart(op);\r
169 Cycles=4;\r
170 OpEnd();\r
171 return 0;\r
172\r
a6785576 173 case 3: // rte\r
174 OpStart(op,0x10); Cycles=20;\r
175 SuperCheck(op);\r
cc68a136 176 PopSr(1);\r
177 ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");\r
178 PopPc();\r
a6785576 179 SuperChange(op);\r
cc68a136 180 CheckInterrupt(op);\r
181 OpEnd();\r
a6785576 182 SuperEnd(op);\r
cc68a136 183 return 0;\r
184\r
185 case 5: // rts\r
a6785576 186 OpStart(op,0x10); Cycles=16;\r
cc68a136 187 ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");\r
188 PopPc();\r
189 OpEnd();\r
190 return 0;\r
191\r
192 case 6: // trapv\r
a6785576 193 OpStart(op,0x10); Cycles=4;\r
cc68a136 194 ot(" tst r9,#0x10000000\n");\r
195 ot(" subne r5,r5,#%i\n",30);\r
196 ot(" movne r0,#0x1c ;@ TRAPV exception\n");\r
197 ot(" blne Exception\n");\r
198 OpEnd();\r
199 return 0;\r
200\r
201 case 7: // rtr\r
a6785576 202 OpStart(op,0x10); Cycles=20;\r
cc68a136 203 PopSr(0);\r
204 ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");\r
205 PopPc();\r
206 OpEnd();\r
207 return 0;\r
208\r
209 default:\r
210 return 1;\r
211 }\r
212}\r
213\r
214// --------------------- Opcodes 0x4e80+ ---------------------\r
215// Emit a Jsr/Jmp opcode, 01001110 1meeeeee\r
216int OpJsr(int op)\r
217{\r
218 int use=0;\r
219 int sea=0;\r
220\r
221 sea=op&0x003f;\r
222\r
223 // See if we can do this opcode:\r
224 if (EaCanRead(sea,-1)==0) return 1;\r
225\r
226 use=OpBase(op);\r
227 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
228\r
a6785576 229 OpStart(op,0x10);\r
cc68a136 230\r
231 ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");\r
232 ot("\n");\r
233 EaCalc(0,0x003f,sea,0);\r
234\r
235 ot(";@ Jump - Get new PC from r0\n");\r
236 if (op&0x40)\r
237 {\r
238 // Jmp - Get new PC from r0\r
239 ot(" add r4,r0,r10 ;@ r4 = Memory Base + New PC\n");\r
240 ot("\n");\r
241 }\r
242 else\r
243 {\r
244 ot(";@ Jsr - Push old PC first\n");\r
245 ot(" sub r1,r4,r10 ;@ r1 = Old PC\n");\r
246 ot(" add r4,r0,r10 ;@ r4 = Memory Base + New PC\n");\r
247 ot(" mov r1,r1,lsl #8\n");\r
248 ot(" ldr r0,[r7,#0x3c]\n");\r
249 ot(" mov r1,r1,asr #8\n");\r
250 ot(";@ Push r1 onto stack\n");\r
251 ot(" sub r0,r0,#4 ;@ Predecrement A7\n");\r
252 ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
253 MemHandler(1,2);\r
254 ot("\n");\r
255 }\r
256\r
257#if USE_CHECKPC_CALLBACK\r
258 CheckPc();\r
259#endif\r
260\r
261 Cycles=(op&0x40) ? 4 : 12;\r
262 Cycles+=Ea_add_ns((op&0x40) ? g_jmp_cycle_table : g_jsr_cycle_table, sea);\r
263\r
264 OpEnd();\r
265\r
266 return 0;\r
267}\r
268\r
269// --------------------- Opcodes 0x50c8+ ---------------------\r
270\r
271// ARM version of 68000 condition codes:\r
272static char *Cond[16]=\r
273{\r
274 "", "", "hi","ls","cc","cs","ne","eq",\r
275 "vc","vs","pl","mi","ge","lt","gt","le"\r
276};\r
277\r
278// Emit a Dbra opcode, 0101cccc 11001nnn vv\r
279int OpDbra(int op)\r
280{\r
281 int use=0;\r
282 int cc=0;\r
283\r
284 use=op&~7; // Use same handler\r
285 cc=(op>>8)&15;\r
286 \r
287 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
288 OpStart(op);\r
289\r
290 if (cc>=2)\r
291 {\r
292 ot(";@ Is the condition true?\n");\r
293 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");\r
294 ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");\r
295 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000\n");\r
296 ot(";@ If so, don't dbra\n");\r
297 ot(" b%s DbraTrue%.4x\n",Cond[cc],op);\r
298 ot("\n");\r
299 }\r
300\r
301 ot(";@ Decrement Dn.w\n");\r
302 ot(" and r1,r8,#0x0007\n");\r
303 ot(" mov r1,r1,lsl #2\n");\r
304 ot(" ldrsh r0,[r7,r1]\n");\r
305 ot(" sub r0,r0,#1\n");\r
306 ot(" strh r0,[r7,r1]\n");\r
307 ot("\n");\r
308\r
309 ot(";@ Check if Dn.w is -1\n");\r
310 ot(" cmps r0,#-1\n");\r
311 ot(" beq DbraMin1%.4x\n",op);\r
312 ot("\n");\r
313\r
314 ot(";@ Get Branch offset:\n");\r
315 ot(" ldrsh r0,[r4]\n");\r
316 ot(" add r4,r4,r0 ;@ r4 = New PC\n");\r
317 ot("\n");\r
318 Cycles=12-2;\r
319 OpEnd();\r
320 \r
321 ot(";@ Dn.w is -1:\n");\r
322 ot("DbraMin1%.4x%s\n", op, ms?"":":");\r
323 ot(" add r4,r4,#2 ;@ Skip branch offset\n");\r
324 ot("\n");\r
325 Cycles=12+2;\r
326 OpEnd();\r
327\r
328 ot(";@ condition true:\n");\r
329 ot("DbraTrue%.4x%s\n", op, ms?"":":");\r
330 ot(" add r4,r4,#2 ;@ Skip branch offset\n");\r
331 ot("\n");\r
332 Cycles=12;\r
333 OpEnd();\r
334\r
335 return 0;\r
336}\r
337\r
338// --------------------- Opcodes 0x6000+ ---------------------\r
339// Emit a Branch opcode 0110cccc nn (cccc=condition)\r
340int OpBranch(int op)\r
341{\r
342 int size=0,use=0;\r
343 int offset=0;\r
344 int cc=0;\r
345\r
346 offset=(char)(op&0xff);\r
347 cc=(op>>8)&15;\r
348\r
349 // Special offsets:\r
350 if (offset==0) size=1;\r
351 if (offset==-1) size=2;\r
352\r
353 if (size) use=op; // 16-bit or 32-bit\r
354 else use=(op&0xff00)+1; // Use same opcode for all 8-bit branches\r
355\r
356 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
a6785576 357 OpStart(op,size?0x10:0);\r
cc68a136 358\r
359 ot(";@ Get Branch offset:\n");\r
360 if (size) \r
361 {\r
362 EaCalc(0,0,0x3c,size);\r
363 EaRead(0,0,0x3c,size,0);\r
364 }\r
365\r
366 // above code messes cycles\r
367 Cycles=10; // Assume branch taken\r
368\r
369 if (size==0) ot(" mov r0,r8,asl #24 ;@ Shift 8-bit signed offset up...\n\n");\r
370\r
371 if (cc==1) ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");\r
372\r
373 if (cc>=2)\r
374 {\r
375 ot(";@ Is the condition true?\n");\r
376 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");\r
377 ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");\r
378 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000\n");\r
379\r
380 if (size==0) ot(" mov r0,r0,asr #24 ;@ ...shift down\n\n");\r
381\r
382 ot(" b%s DontBranch%.4x\n",Cond[cc^1],op);\r
383\r
384 ot("\n");\r
385 }\r
386 else\r
387 {\r
388 if (size==0) ot(" mov r0,r0,asr #24 ;@ ...shift down\n\n");\r
389 }\r
390\r
391 ot(";@ Branch taken - Add on r0 to PC\n");\r
392\r
393 if (cc==1)\r
394 {\r
395 ot(";@ Bsr - remember old PC\n");\r
396 ot(" sub r1,r4,r10 ;@ r1 = Old PC\n");\r
397 ot(" mov r1,r1, lsl #8\n");\r
398 ot(" mov r1,r1, asr #8\n");\r
399 ot("\n");\r
400 if (size) ot(" sub r4,r4,#%d ;@ (Branch is relative to Opcode+2)\n",1<<size);\r
401 ot(" ldr r2,[r7,#0x3c]\n");\r
402 ot(" add r4,r4,r0 ;@ r4 = New PC\n");\r
403 ot(";@ Push r1 onto stack\n");\r
404 ot(" sub r0,r2,#4 ;@ Predecrement A7\n");\r
405 ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
406 MemHandler(1,2);\r
407 ot("\n");\r
408 Cycles=18; // always 18\r
409 }\r
410 else\r
411 {\r
412 if (size) ot(" sub r4,r4,#%d ;@ (Branch is relative to Opcode+2)\n",1<<size);\r
413 ot(" add r4,r4,r0 ;@ r4 = New PC\n");\r
414 ot("\n");\r
415 }\r
416\r
417#if USE_CHECKPC_CALLBACK\r
418 if (offset==0 || offset==-1)\r
419 {\r
420 ot(";@ Branch is quite far, so may be a good idea to check Memory Base+pc\n");\r
421 CheckPc();\r
422 }\r
423#endif\r
424\r
425 OpEnd();\r
426\r
427 if (cc>=2)\r
428 {\r
429 ot("DontBranch%.4x%s\n", op, ms?"":":");\r
430 Cycles+=(size==1)? 2 : -2; // Branch not taken\r
431 OpEnd();\r
432 }\r
433\r
434 return 0;\r
435}\r
436\r