1 |
dpavlin |
16 |
/* |
2 |
dpavlin |
34 |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
dpavlin |
16 |
* |
4 |
|
|
* Redistribution and use in source and binary forms, with or without |
5 |
|
|
* modification, are permitted provided that the following conditions are met: |
6 |
|
|
* |
7 |
|
|
* 1. Redistributions of source code must retain the above copyright |
8 |
|
|
* notice, this list of conditions and the following disclaimer. |
9 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer in the |
11 |
|
|
* documentation and/or other materials provided with the distribution. |
12 |
|
|
* 3. The name of the author may not be used to endorse or promote products |
13 |
|
|
* derived from this software without specific prior written permission. |
14 |
|
|
* |
15 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
|
|
* SUCH DAMAGE. |
26 |
|
|
* |
27 |
|
|
* |
28 |
dpavlin |
34 |
* $Id: generate_arm_r.c,v 1.6 2006/12/30 13:30:56 debug Exp $ |
29 |
dpavlin |
16 |
* |
30 |
|
|
* Generate functions for computing "reg" operands. |
31 |
|
|
*/ |
32 |
|
|
|
33 |
|
|
#include <stdio.h> |
34 |
|
|
#include <stdlib.h> |
35 |
|
|
|
36 |
|
|
|
37 |
|
|
void sync_pc(void) |
38 |
|
|
{ |
39 |
|
|
printf("\tuint32_t tmp, low_pc = ((size_t)ic - (size_t)\n" |
40 |
|
|
"\t cpu->cd.arm.cur_ic_page)/sizeof(struct arm_instr_call);\n"); |
41 |
dpavlin |
20 |
printf("\ttmp = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<\n" |
42 |
dpavlin |
16 |
"\t ARM_INSTR_ALIGNMENT_SHIFT);\n"); |
43 |
|
|
printf("\ttmp += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;\n"); |
44 |
|
|
} |
45 |
|
|
|
46 |
|
|
|
47 |
|
|
void f(int s, int func, int only_name) |
48 |
|
|
{ |
49 |
|
|
int rm = func & 15; |
50 |
|
|
int c = (func >> 7) & 31; |
51 |
|
|
int t = (func >> 4) & 7; |
52 |
|
|
char name[200]; |
53 |
|
|
int pc = rm == 15, rc = c >> 1; |
54 |
|
|
|
55 |
|
|
snprintf(name, sizeof(name), "arm_r%s_r%i_t%i_c%i", s? "s" : "", |
56 |
|
|
rm, t, c); |
57 |
|
|
if (only_name) { |
58 |
|
|
printf("%s", name); |
59 |
|
|
return; |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
printf("uint32_t %s(struct cpu *cpu, struct arm_instr_call *ic)" |
63 |
|
|
" {\n", name); |
64 |
|
|
if (pc) |
65 |
|
|
sync_pc(); |
66 |
|
|
|
67 |
|
|
switch (t) { |
68 |
|
|
|
69 |
|
|
case 0: /* lsl c (Logical Shift Left by constant) */ |
70 |
|
|
if (s) { |
71 |
|
|
printf("{ uint32_t x = "); |
72 |
|
|
if (pc) |
73 |
|
|
printf("tmp"); |
74 |
|
|
else |
75 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
76 |
|
|
printf(";\n"); |
77 |
|
|
if (c != 0) { |
78 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
79 |
dpavlin |
16 |
printf("if (x & 0x%x)\n" |
80 |
dpavlin |
20 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
81 |
dpavlin |
16 |
(int)(0x80000000 >> (c-1))); |
82 |
|
|
printf("x <<= %i;\n", c); |
83 |
|
|
} |
84 |
|
|
printf(" return x; }\n"); |
85 |
|
|
} else { |
86 |
|
|
if (pc) |
87 |
|
|
printf("\treturn tmp"); |
88 |
|
|
else |
89 |
|
|
printf("\treturn cpu->cd.arm.r[%i]", rm); |
90 |
|
|
if (c != 0) |
91 |
|
|
printf(" << %i", c); |
92 |
|
|
printf(";\n"); |
93 |
|
|
} |
94 |
|
|
break; |
95 |
|
|
|
96 |
|
|
case 1: /* lsl Rc (Logical Shift Left by register) */ |
97 |
|
|
if (s) { |
98 |
|
|
printf("{ uint32_t x = "); |
99 |
|
|
if (pc) |
100 |
|
|
printf("tmp"); |
101 |
|
|
else |
102 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
103 |
|
|
printf(";\n"); |
104 |
|
|
printf(" uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc); |
105 |
|
|
printf(" if (y != 0) {\n"); |
106 |
dpavlin |
20 |
printf(" cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
107 |
dpavlin |
16 |
printf(" if (y >= 32) return 0;\n"); |
108 |
|
|
printf(" x <<= (y - 1);\n"); |
109 |
|
|
printf(" if (x & 0x80000000)\n" |
110 |
dpavlin |
20 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n"); |
111 |
dpavlin |
16 |
printf(" x <<= 1;\n"); |
112 |
|
|
printf(" }\n"); |
113 |
|
|
printf(" return x; }\n"); |
114 |
|
|
} else { |
115 |
|
|
printf("{ uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc); |
116 |
|
|
printf(" uint32_t x ="); |
117 |
|
|
if (pc) |
118 |
|
|
printf("tmp"); |
119 |
|
|
else |
120 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
121 |
|
|
printf(";\n"); |
122 |
|
|
printf("if (y > 31) return 0; else x <<= y;\n"); |
123 |
|
|
printf("return x; }\n"); |
124 |
|
|
} |
125 |
|
|
break; |
126 |
|
|
|
127 |
|
|
case 2: /* lsr c (Logical Shift Right by constant) */ |
128 |
|
|
/* 1..32 */ |
129 |
|
|
if (s) { |
130 |
|
|
printf("{ uint32_t x = "); |
131 |
|
|
if (pc) |
132 |
|
|
printf("tmp"); |
133 |
|
|
else |
134 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
135 |
|
|
printf(";\n"); |
136 |
|
|
if (c == 0) |
137 |
|
|
c = 32; |
138 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
139 |
dpavlin |
16 |
printf("if (x & 0x%x)\n" |
140 |
dpavlin |
20 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
141 |
dpavlin |
16 |
(int)(1 << (c-1))); |
142 |
|
|
if (c == 32) |
143 |
|
|
printf("x = 0;\n"); |
144 |
|
|
else |
145 |
|
|
printf("x >>= %i;\n", c); |
146 |
|
|
printf(" return x; }\n"); |
147 |
|
|
} else { |
148 |
|
|
if (c == 0) |
149 |
|
|
printf("\treturn 0;\n"); |
150 |
|
|
else { |
151 |
|
|
if (pc) |
152 |
|
|
printf("\treturn tmp"); |
153 |
|
|
else |
154 |
|
|
printf("\treturn cpu->cd.arm.r[%i]",rm); |
155 |
|
|
printf(" >> %i;\n", c); |
156 |
|
|
} |
157 |
|
|
} |
158 |
|
|
break; |
159 |
|
|
|
160 |
|
|
case 3: /* lsr Rc (Logical Shift Right by register) */ |
161 |
|
|
if (s) { |
162 |
|
|
printf("{ uint32_t x = "); |
163 |
|
|
if (pc) |
164 |
|
|
printf("tmp"); |
165 |
|
|
else |
166 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
167 |
|
|
printf(",y=cpu->cd.arm.r[%i]&255;\n", rc); |
168 |
|
|
printf("if(y==0) return x;\n"); |
169 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
170 |
dpavlin |
16 |
printf("if(y>31) y=32;\n"); |
171 |
|
|
printf("y--; x >>= y;\n"); |
172 |
|
|
printf("if (x & 1) " |
173 |
dpavlin |
20 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
174 |
dpavlin |
16 |
printf(" return x >> 1; }\n"); |
175 |
|
|
} else { |
176 |
|
|
printf("{ uint32_t y=cpu->cd.arm.r[%i]&255;\n", rc); |
177 |
|
|
printf("uint32_t x="); |
178 |
|
|
if (pc) |
179 |
|
|
printf("tmp"); |
180 |
|
|
else |
181 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
182 |
|
|
printf("; "); |
183 |
|
|
printf("if (y>=32) return 0;\n"); |
184 |
|
|
printf("return x >> y; } "); |
185 |
|
|
} |
186 |
|
|
break; |
187 |
|
|
|
188 |
|
|
case 4: /* asr c (Arithmetic Shift Right by constant) */ |
189 |
|
|
/* 1..32 */ |
190 |
|
|
if (s) { |
191 |
|
|
printf("{ int32_t x = "); |
192 |
|
|
if (pc) |
193 |
|
|
printf("tmp"); |
194 |
|
|
else |
195 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
196 |
|
|
printf(";\n"); |
197 |
|
|
if (c == 0) |
198 |
|
|
c = 32; |
199 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
200 |
dpavlin |
16 |
printf("if (x & 0x%x)\n" |
201 |
dpavlin |
20 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
202 |
dpavlin |
16 |
(int)(1 << (c-1))); |
203 |
|
|
if (c == 32) |
204 |
|
|
printf("x = (x<0)? 0xffffffff : 0;\n"); |
205 |
|
|
else |
206 |
|
|
printf("x >>= %i;\n", c); |
207 |
|
|
printf(" return x; }\n"); |
208 |
|
|
} else { |
209 |
|
|
if (c == 0) { |
210 |
|
|
printf("\treturn "); |
211 |
|
|
if (pc) |
212 |
|
|
printf("tmp"); |
213 |
|
|
else |
214 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
215 |
|
|
printf(" & 0x80000000? 0xffffffff : 0;\n"); |
216 |
|
|
} else { |
217 |
|
|
printf("return (int32_t)"); |
218 |
|
|
if (pc) |
219 |
|
|
printf("tmp"); |
220 |
|
|
else |
221 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
222 |
|
|
printf(" >> %i;\n", c); |
223 |
|
|
} |
224 |
|
|
} |
225 |
|
|
break; |
226 |
|
|
|
227 |
|
|
case 5: /* asr Rc (Arithmetic Shift Right by register) */ |
228 |
|
|
if (s) { |
229 |
|
|
printf("{ int32_t x = "); |
230 |
|
|
if (pc) |
231 |
|
|
printf("tmp"); |
232 |
|
|
else |
233 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
234 |
|
|
printf(",y=cpu->cd.arm.r[%i]&255;\n", rc); |
235 |
|
|
printf("if(y==0) return x;\n"); |
236 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
237 |
dpavlin |
16 |
printf("if(y>31) y=31;\n"); |
238 |
|
|
printf("y--; x >>= y;\n"); |
239 |
|
|
printf("if (x & 1) " |
240 |
dpavlin |
20 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
241 |
dpavlin |
16 |
printf(" return (int32_t)x >> 1; }\n"); |
242 |
|
|
} else { |
243 |
|
|
printf("{ int32_t y=cpu->cd.arm.r[%i]&255;\n", rc); |
244 |
|
|
printf("int32_t x="); |
245 |
|
|
if (pc) |
246 |
|
|
printf("tmp"); |
247 |
|
|
else |
248 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
249 |
|
|
printf("; "); |
250 |
|
|
printf("if (y>=31) return (x<0)?0xffffffff:0;\n"); |
251 |
|
|
printf("return (int32_t)x >> y; } "); |
252 |
|
|
} |
253 |
|
|
break; |
254 |
|
|
|
255 |
|
|
case 6: /* ror c OR rrx (Arithmetic Shift Right by constant) */ |
256 |
|
|
/* 0=rrx, 1..31=ror */ |
257 |
|
|
if (c == 0) { |
258 |
dpavlin |
22 |
printf("{ uint64_t x="); |
259 |
|
|
if (pc) |
260 |
|
|
printf("tmp"); |
261 |
|
|
else |
262 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
263 |
|
|
printf("; if (cpu->cd.arm.flags & ARM_F_C)" |
264 |
|
|
" x |= 0x100000000ULL;"); |
265 |
|
|
if (s) { |
266 |
|
|
printf("cpu->cd.arm.flags &= ~ARM_F_C;" |
267 |
|
|
"if(x&1) cpu->cd.arm.flags |= " |
268 |
|
|
"ARM_F_C;"); |
269 |
|
|
} |
270 |
|
|
printf("return x >> 1; }\n"); |
271 |
dpavlin |
16 |
} else if (s) { |
272 |
|
|
printf("{ uint64_t x = "); |
273 |
|
|
if (pc) |
274 |
|
|
printf("tmp"); |
275 |
|
|
else |
276 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
277 |
|
|
printf("; x |= (x << 32);\n"); |
278 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
279 |
dpavlin |
16 |
printf("if (x & 0x%x)\n" |
280 |
dpavlin |
20 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
281 |
dpavlin |
16 |
(int)(1 << (c-1))); |
282 |
|
|
printf(" return x >> %i; }\n", c); |
283 |
|
|
} else { |
284 |
dpavlin |
18 |
printf("{ uint64_t x="); |
285 |
dpavlin |
16 |
if (pc) |
286 |
|
|
printf("tmp"); |
287 |
|
|
else |
288 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
289 |
|
|
printf("; x |= (x << 32); "); |
290 |
dpavlin |
18 |
printf("return x >> %i; }\n", c); |
291 |
dpavlin |
16 |
} |
292 |
|
|
break; |
293 |
|
|
|
294 |
|
|
case 7: /* ror Rc (Rotate Right by register) */ |
295 |
|
|
if (s) { |
296 |
|
|
printf("{ uint64_t x = "); |
297 |
|
|
if (pc) |
298 |
|
|
printf("tmp"); |
299 |
|
|
else |
300 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
301 |
|
|
printf("; int y=cpu->cd.arm.r[%i]&255;\n", rc); |
302 |
|
|
printf("if(y==0) return x;\n"); |
303 |
|
|
printf("y --; y &= 31; x >>= y;\n"); |
304 |
dpavlin |
20 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
305 |
dpavlin |
16 |
printf("if (x & 1) " |
306 |
dpavlin |
20 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
307 |
dpavlin |
16 |
printf(" return x >> 1; }\n"); |
308 |
|
|
} else { |
309 |
|
|
printf("{ int y=cpu->cd.arm.r[%i]&31;\n", rc); |
310 |
|
|
printf("uint64_t x="); |
311 |
|
|
if (pc) |
312 |
|
|
printf("tmp"); |
313 |
|
|
else |
314 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
315 |
|
|
printf("; x |= (x << 32); "); |
316 |
|
|
printf("return (x >> y); } "); |
317 |
|
|
} |
318 |
|
|
break; |
319 |
|
|
|
320 |
|
|
default: |
321 |
|
|
printf("\tprintf(\"%s\\n\");\n", name); |
322 |
|
|
printf("\texit(1); /* TODO */\n\treturn 0;\n"); |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
printf("}\n"); |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
|
329 |
|
|
int main(int argc, char *argv[]) |
330 |
|
|
{ |
331 |
|
|
int s, func, f_start, f_end; |
332 |
|
|
|
333 |
|
|
if (argc < 3) { |
334 |
|
|
fprintf(stderr, "usage: %s start end\n", argv[0]); |
335 |
|
|
exit(1); |
336 |
|
|
} |
337 |
|
|
|
338 |
|
|
f_start = strtol(argv[1], NULL, 0); |
339 |
|
|
f_end = strtol(argv[2], NULL, 0); |
340 |
|
|
|
341 |
|
|
printf("/*\n * DO NOT EDIT! AUTOMATICALLY GENERATED!\n */\n\n"); |
342 |
|
|
printf("#include <stdio.h>\n"); |
343 |
|
|
printf("#include <stdlib.h>\n"); |
344 |
|
|
printf("#include \"cpu.h\"\n"); |
345 |
|
|
printf("#include \"misc.h\"\n"); |
346 |
|
|
printf("\n\n"); |
347 |
|
|
|
348 |
|
|
if (f_start != 0 || f_end != 0) { |
349 |
|
|
for (s=0; s<=1; s++) |
350 |
|
|
for (func=f_start; func<=f_end; func++) |
351 |
|
|
f(s, func, 0); |
352 |
|
|
} else { |
353 |
|
|
for (s=0; s<=1; s++) |
354 |
|
|
for (func=0; func<=0xfff; func++) { |
355 |
|
|
printf("extern uint32_t "); |
356 |
|
|
f(s, func, 1); |
357 |
|
|
printf("(struct cpu *, struct arm_" |
358 |
|
|
"instr_call *);\n"); |
359 |
|
|
} |
360 |
|
|
|
361 |
|
|
printf("\nuint32_t (*arm_r[8192])(struct cpu *," |
362 |
|
|
" struct arm_instr_call *) = {\n"); |
363 |
|
|
for (s=0; s<=1; s++) |
364 |
|
|
for (func=0; func<=0xfff; func++) { |
365 |
|
|
printf("\t"); |
366 |
|
|
f(s, func, 1); |
367 |
|
|
if (s!=1 || func!=0xfff) |
368 |
|
|
printf(","); |
369 |
|
|
printf("\n"); |
370 |
|
|
} |
371 |
|
|
printf("};\n\n"); |
372 |
|
|
} |
373 |
|
|
|
374 |
|
|
return 0; |
375 |
|
|
} |
376 |
|
|
|