first check-in of Cyclone 0.069 under GPLv2 and MAME License. Pico Disa.c/h included too
[cyclone68000.git] / Cyclone / OpBranch.cpp
1 \r
2 #include "app.h"\r
3 \r
4 static 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
15 void 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
26 void 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
38 static 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
50 static 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
62 int 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
83 int 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
121 int 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
150 int 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
183 int 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
232 static 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
239 int 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
291 int 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