first check-in of Cyclone 0.069 under GPLv2 and MAME License. Pico Disa.c/h included too
[cyclone68000.git] / Cyclone / Ea.cpp
1 \r
2 #include "app.h"\r
3 \r
4 // ---------------------------------------------------------------------------\r
5 // Gets the offset of a register for an ea, and puts it in 'r'\r
6 // Shifted left by 'shift'\r
7 // Doesn't trash anything\r
8 static int EaCalcReg(int r,int ea,int mask,int forceor,int shift)\r
9 {\r
10   int i=0,low=0,needor=0;\r
11   int lsl=0;\r
12 \r
13   for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
14   mask&=0xf<<low; // This is the max we can do\r
15 \r
16   if (ea>=8) needor=1; // Need to OR to access A0-7\r
17 \r
18   if ((mask>>low)&8) if (ea&8) needor=0; // Ah - no we don't actually need to or, since the bit is high in r8\r
19 \r
20   if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)\r
21 \r
22   ot("  and r%d,r8,#0x%.4x\n",r,mask);\r
23 \r
24   // Find out amount to shift left:\r
25   lsl=shift-low;\r
26 \r
27   if (lsl)\r
28   {\r
29     ot("  mov r%d,r%d,",r,r);\r
30     if (lsl>0) ot("lsl #%d\n", lsl);\r
31     else       ot("lsr #%d\n",-lsl);\r
32   }\r
33 \r
34   if (needor) ot("  orr r%d,r%d,#0x%x ;@ A0-7\n",r,r,8<<shift);\r
35   return 0;\r
36 }\r
37 \r
38 // EaCalc - ARM Register 'a' = Effective Address\r
39 // Trashes r0,r2 and r3\r
40 int EaCalc(int a,int mask,int ea,int size)\r
41 {\r
42   char text[32]="";\r
43   int func=0;\r
44 \r
45   DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
46   func=0x68+(size<<2); // Get correct read handler\r
47 \r
48   if (ea<0x10)\r
49   {\r
50     int lsl=2;\r
51     if (size>=2) lsl=0; // Saves one opcode\r
52 \r
53     ot(";@ EaCalc : Get register index into r%d:\n",a);\r
54 \r
55     EaCalcReg(a,ea,mask,0,lsl);\r
56     return 0;\r
57   }\r
58   \r
59   ot(";@ EaCalc : Get '%s' into r%d:\n",text,a);\r
60   // (An), (An)+, -(An):\r
61   if (ea<0x28)\r
62   {\r
63     int step=1<<size;\r
64 \r
65     if ((ea&7)==7 && step<2) step=2; // move.b (a7)+ or -(a7) steps by 2 not 1\r
66 \r
67     EaCalcReg(2,ea,mask,0,2);\r
68     ot("  ldr r%d,[r7,r2]\n",a);\r
69 \r
70     if ((ea&0x38)==0x18)\r
71     {\r
72       ot("  add r3,r%d,#%d ;@ Post-increment An\n",a,step);\r
73       ot("  str r3,[r7,r2]\n");\r
74     }\r
75 \r
76     if ((ea&0x38)==0x20)\r
77     {\r
78       ot("  sub r%d,r%d,#%d ;@ Pre-decrement An\n",a,a,step);\r
79       ot("  str r%d,[r7,r2]\n",a);\r
80     }\r
81 \r
82     if ((ea&0x38)==0x20) Cycles+=size<2 ? 6:10; // -(An) Extra cycles\r
83     else                 Cycles+=size<2 ? 4:8;  // (An),(An)+ Extra cycles\r
84     return 0;\r
85   }\r
86 \r
87   if (ea<0x30) // ($nn,An)\r
88   {\r
89     EaCalcReg(2,8,mask,0,2);\r
90     ot("  ldr r2,[r7,r2]\n");\r
91     ot("  ldrsh r0,[r4],#2 ;@ Fetch offset\n");\r
92     ot("  add r%d,r0,r2 ;@ Add on offset\n",a);\r
93     Cycles+=size<2 ? 8:12; // Extra cycles\r
94     return 0;\r
95   }\r
96 \r
97   if (ea<0x38) // ($nn,An,Rn)\r
98   {\r
99     ot(";@ Get extension word into r3:\n");\r
100     ot("  ldrh r3,[r4],#2 ;@ ($Disp,PC,Rn)\n");\r
101     ot("  mov r2,r3,lsr #10\n");\r
102     ot("  tst r3,#0x0800 ;@ Is Rn Word or Long\n");\r
103     ot("  and r2,r2,#0x3c ;@ r2=Index of Rn\n");\r
104     ot("  mov r0,r3,asl #24 ;@ r0=Get 8-bit signed Disp\n");\r
105     ot("  ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n");\r
106     ot("  ldrne   r2,[r7,r2] ;@ r2=Rn.l\n");\r
107     ot("  add r3,r2,r0,asr #24 ;@ r3=Disp+Rn\n");\r
108 \r
109     EaCalcReg(2,8,mask,1,2);\r
110     ot("  ldr r2,[r7,r2]\n");\r
111     ot("  add r%d,r2,r3 ;@ r%d=Disp+An+Rn\n",a,a);\r
112     Cycles+=size<2 ? 10:14; // Extra cycles\r
113     return 0;\r
114   }\r
115 \r
116   if (ea==0x38)\r
117   {\r
118     ot("  ldrsh r%d,[r4],#2 ;@ Fetch Absolute Short address\n",a);\r
119     Cycles+=size<2 ? 8:12; // Extra cycles\r
120     return 0;\r
121   }\r
122 \r
123   if (ea==0x39)\r
124   {\r
125     ot("  ldrh r2,[r4],#2 ;@ Fetch Absolute Long address\n");\r
126     ot("  ldrh r0,[r4],#2\n");\r
127     ot("  orr r%d,r0,r2,lsl #16\n",a);\r
128     Cycles+=size<2 ? 12:16; // Extra cycles\r
129     return 0;\r
130   }\r
131 \r
132   if (ea==0x3a)\r
133   {\r
134     ot("  ldr r0,[r7,#0x60] ;@ Get Memory base\n");\r
135     ot("  sub r0,r4,r0 ;@ Real PC\n");\r
136     ot("  ldrsh r2,[r4],#2 ;@ Fetch extension\n");\r
137     ot("  add r%d,r0,r2 ;@ ($nn,PC)\n",a);\r
138     Cycles+=size<2 ? 8:12; // Extra cycles\r
139     return 0;\r
140   }\r
141 \r
142   if (ea==0x3b) // ($nn,pc,Rn)\r
143   {\r
144     ot(";@ Get extension word into r3:\n");\r
145     ot("  ldrh r3,[r4]\n");\r
146     ot("  mov r2,r3,lsr #10\n");\r
147     ot("  tst r3,#0x0800 ;@ Is Rn Word or Long\n");\r
148     ot("  and r2,r2,#0x3c ;@ r2=Index of Rn\n");\r
149     ot("  mov r0,r3,asl #24 ;@ r0=Get 8-bit signed Disp\n");\r
150     ot("  ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n");\r
151     ot("  ldrne   r2,[r7,r2] ;@ r2=Rn.l\n");\r
152     ot("  add r2,r2,r0,asr #24 ;@ r2=Disp+Rn\n");\r
153     ot("  ldr r0,[r7,#0x60] ;@ Get Memory base\n");\r
154     ot("  add r2,r2,r4 ;@ r2=Disp+Rn + Base+PC\n");\r
155     ot("  add r4,r4,#2 ;@ Increase PC\n");\r
156     ot("  sub r%d,r2,r0 ;@ r%d=Disp+PC+Rn\n",a,a);\r
157     Cycles+=size<2 ? 10:14; // Extra cycles\r
158     return 0;\r
159   }\r
160 \r
161   if (ea==0x3c)\r
162   {\r
163     if (size<2)\r
164     {\r
165       ot("  ldr%s r%d,[r4],#2 ;@ Fetch immediate value\n",Sarm[size&3],a);\r
166       Cycles+=4; // Extra cycles\r
167       return 0;\r
168     }\r
169 \r
170     ot("  ldrh r2,[r4],#2 ;@ Fetch immediate value\n");\r
171     ot("  ldrh r0,[r4],#2\n");\r
172     ot("  orr r%d,r0,r2,lsl #16\n",a);\r
173     Cycles+=8; // Extra cycles\r
174     return 0;\r
175   }\r
176 \r
177   return 1;\r
178 }\r
179 \r
180 // ---------------------------------------------------------------------------\r
181 // Read effective address in (ARM Register 'a') to ARM register 'v'\r
182 // 'a' and 'v' can be anything but 0 is generally best (for both)\r
183 // If (ea<0x10) nothing is trashed, else r0-r3 is trashed\r
184 // If 'top' is 1, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000\r
185 // Otherwise the ARM register v is sign extended, e.g. 0xc000 -> 0xffffc000\r
186 \r
187 int EaRead(int a,int v,int ea,int size,int top)\r
188 {\r
189   char text[32]="";\r
190   int shift=0;\r
191   \r
192   shift=32-(8<<size);\r
193 \r
194   DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
195 \r
196   if (ea<0x10)\r
197   {\r
198     int lsl=2;\r
199     if (size>=2) lsl=0; // Having a lsl #2 here saves one opcode\r
200 \r
201     ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v);\r
202 \r
203     if (lsl==0) ot("  ldr r%d,[r7,r%d,lsl #2]\n",v,a);\r
204     else        ot("  ldr%s r%d,[r7,r%d]\n",Sarm[size&3],v,a);\r
205 \r
206     if (top && shift) ot("  mov r%d,r%d,asl #%d\n",v,v,shift);\r
207 \r
208     ot("\n"); return 0;\r
209   }\r
210 \r
211   ot(";@ EaRead : Read '%s' (address in r%d) into r%d:\n",text,a,v);\r
212 \r
213   if (ea==0x3c)\r
214   {\r
215     int asl=0;\r
216 \r
217     if (top) asl=shift;\r
218 \r
219     if (v!=a || asl) ot("  mov r%d,r%d,asl #%d\n",v,a,asl);\r
220     ot("\n"); return 0;\r
221   }\r
222 \r
223   if (a!=0) ot("  mov r0,r%d\n",a);\r
224 \r
225   if (ea>=0x3a && ea<=0x3b) MemHandler(2,size); // Fetch\r
226   else                      MemHandler(0,size); // Read\r
227 \r
228   if (v!=0 || shift) ot("  mov r%d,r0,asl #%d\n",v,shift);\r
229   if (top==0 && shift) ot("  mov r%d,r%d,asr #%d\n",v,v,shift);\r
230 \r
231   ot("\n"); return 0;\r
232 }\r
233 \r
234 // Return 1 if we can read this ea\r
235 int EaCanRead(int ea,int size)\r
236 {\r
237   if (size<0)\r
238   {\r
239     // LEA:\r
240     // These don't make sense?:\r
241     if (ea<0x10) return 0; // Register\r
242     if (ea==0x3c) return 0; // Immediate\r
243     if (ea>=0x18 && ea<0x28) return 0; // Pre/Post inc/dec An\r
244   }\r
245 \r
246   if (ea<=0x3c) return 1;\r
247   return 0;\r
248 }\r
249 \r
250 // ---------------------------------------------------------------------------\r
251 // Write effective address (ARM Register 'a') with ARM register 'v'\r
252 // Trashes r0-r3, 'a' can be 0 or 2+, 'v' can be 1 or higher\r
253 // If a==0 and v==1 it's faster though.\r
254 int EaWrite(int a,int v,int ea,int size,int top)\r
255 {\r
256   char text[32]="";\r
257   int shift=0;\r
258 \r
259   if (top) shift=32-(8<<size);\r
260 \r
261   DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
262 \r
263   if (ea<0x10)\r
264   {\r
265     int lsl=2;\r
266     if (size>=2) lsl=0; // Having a lsl #2 here saves one opcode\r
267 \r
268     ot(";@ EaWrite: r%d into register[r%d]:\n",v,a);\r
269     if (shift) ot("  mov r%d,r%d,asr #%d\n",v,v,shift);\r
270 \r
271     if (lsl==0) ot("  str r%d,[r7,r%d,lsl #2]\n",v,a);\r
272     else        ot("  str%s r%d,[r7,r%d]\n",Narm[size&3],v,a);\r
273 \r
274     ot("\n"); return 0;\r
275   }\r
276 \r
277   ot(";@ EaWrite: Write r%d into '%s' (address in r%d):\n",v,text,a);\r
278 \r
279   if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; }\r
280 \r
281   if (a!=0 && v!=0)  ot("  mov r0,r%d\n",a);\r
282   if (v!=1 || shift) ot("  mov r1,r%d,asr #%d\n",v,shift);\r
283   if (a!=0 && v==0)  ot("  mov r0,r%d\n",a);\r
284 \r
285   MemHandler(1,size); // Call write handler\r
286 \r
287   ot("\n"); return 0;\r
288 }\r
289 \r
290 // Return 1 if we can write this ea\r
291 int EaCanWrite(int ea)\r
292 {\r
293   if (ea<=0x3b) return 1;\r
294   return 0;\r
295 }\r
296 // ---------------------------------------------------------------------------\r