1 |
/* |
2 |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
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 |
* $Id: generate_arm_r.c,v 1.6 2006/12/30 13:30:56 debug Exp $ |
29 |
* |
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 |
printf("\ttmp = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<\n" |
42 |
"\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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
79 |
printf("if (x & 0x%x)\n" |
80 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
81 |
(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 |
printf(" cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
107 |
printf(" if (y >= 32) return 0;\n"); |
108 |
printf(" x <<= (y - 1);\n"); |
109 |
printf(" if (x & 0x80000000)\n" |
110 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n"); |
111 |
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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
139 |
printf("if (x & 0x%x)\n" |
140 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
141 |
(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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
170 |
printf("if(y>31) y=32;\n"); |
171 |
printf("y--; x >>= y;\n"); |
172 |
printf("if (x & 1) " |
173 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
174 |
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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
200 |
printf("if (x & 0x%x)\n" |
201 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
202 |
(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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
237 |
printf("if(y>31) y=31;\n"); |
238 |
printf("y--; x >>= y;\n"); |
239 |
printf("if (x & 1) " |
240 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
241 |
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 |
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 |
} 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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
279 |
printf("if (x & 0x%x)\n" |
280 |
"\tcpu->cd.arm.flags |= ARM_F_C;\n", |
281 |
(int)(1 << (c-1))); |
282 |
printf(" return x >> %i; }\n", c); |
283 |
} else { |
284 |
printf("{ uint64_t x="); |
285 |
if (pc) |
286 |
printf("tmp"); |
287 |
else |
288 |
printf("cpu->cd.arm.r[%i]",rm); |
289 |
printf("; x |= (x << 32); "); |
290 |
printf("return x >> %i; }\n", c); |
291 |
} |
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 |
printf("cpu->cd.arm.flags &= ~ARM_F_C;\n"); |
305 |
printf("if (x & 1) " |
306 |
"cpu->cd.arm.flags |= ARM_F_C;\n"); |
307 |
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 |
|