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