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