/[gxemul]/trunk/src/cpus/generate_arm_r.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/generate_arm_r.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18 - (show annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 11408 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


1 /*
2 * Copyright (C) 2005 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.1 2005/10/09 21:32:07 debug Exp $
29 *
30 * Generate functions for computing "reg" operands.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35
36
37 #if 0
38 /*
39 * update_c is set if the C flag should be updated with the last shifted/
40 * rotated bit.
41 */
42 uint32_t R(struct cpu *cpu, struct arm_instr_call *ic,
43 uint32_t iword, int update_c)
44 {
45 int rm = iword & 15, lastbit, t, c;
46 uint32_t tmp = cpu->cd.arm.r[rm];
47
48 case 2: /* lsr #c (c = 1..32) */
49 if (c == 0)
50 c = 32;
51 if (update_c) {
52 lastbit = ((uint64_t)tmp >> (c-1)) & 1;
53 }
54 tmp = (uint64_t)tmp >> c;
55 break;
56 case 3: /* lsr Rc */
57 c = cpu->cd.arm.r[c >> 1] & 255;
58 if (c >= 32)
59 c = 33;
60 if (update_c) {
61 if (c == 0)
62 update_c = 0;
63 else
64 lastbit = ((uint64_t)tmp >> (c-1)) & 1;
65 }
66 tmp = (uint64_t)tmp >> c;
67 break;
68 case 4: /* asr #c (c = 1..32) */
69 if (c == 0)
70 c = 32;
71 if (update_c) {
72 lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;
73 }
74 tmp = (int64_t)(int32_t)tmp >> c;
75 break;
76 case 5: /* asr Rc */
77 c = cpu->cd.arm.r[c >> 1] & 255;
78 if (c >= 32)
79 c = 33;
80 if (update_c) {
81 if (c == 0)
82 update_c = 0;
83 else
84 lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;
85 }
86 tmp = (int64_t)(int32_t)tmp >> c;
87 break;
88 case 6: /* ror 1..31 */
89 if (c == 0) {
90 fatal("TODO: rrx\n");
91 exit(1);
92 }
93 if (update_c)
94 lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1;
95 tmp = (uint64_t)(((uint64_t)tmp << 32) | tmp) >> c;
96 break;
97 case 7: /* ror Rc */
98 c = cpu->cd.arm.r[c >> 1] & 255;
99 if (update_c) {
100 if (c == 0)
101 update_c = 0;
102 else {
103 c &= 31;
104 if (c == 0)
105 lastbit = tmp & 0x80000000;
106 else
107 lastbit = ((int64_t)(int32_t)tmp
108 >> (c-1)) & 1;
109 tmp = (uint64_t)(((uint64_t)tmp << 32)
110 | tmp) >> c;
111 }
112 }
113 break;
114 }
115 if (update_c) {
116 cpu->cd.arm.cpsr &= ~ARM_FLAG_C;
117 if (lastbit)
118 cpu->cd.arm.cpsr |= ARM_FLAG_C;
119 }
120 return tmp;
121 }
122 #endif
123
124
125 void sync_pc(void)
126 {
127 printf("\tuint32_t tmp, low_pc = ((size_t)ic - (size_t)\n"
128 "\t cpu->cd.arm.cur_ic_page)/sizeof(struct arm_instr_call);\n");
129 printf("\ttmp = cpu->cd.arm.r[15] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<\n"
130 "\t ARM_INSTR_ALIGNMENT_SHIFT);\n");
131 printf("\ttmp += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;\n");
132 }
133
134
135 void f(int s, int func, int only_name)
136 {
137 int rm = func & 15;
138 int c = (func >> 7) & 31;
139 int t = (func >> 4) & 7;
140 char name[200];
141 int pc = rm == 15, rc = c >> 1;
142
143 snprintf(name, sizeof(name), "arm_r%s_r%i_t%i_c%i", s? "s" : "",
144 rm, t, c);
145 if (only_name) {
146 printf("%s", name);
147 return;
148 }
149
150 printf("uint32_t %s(struct cpu *cpu, struct arm_instr_call *ic)"
151 " {\n", name);
152 if (pc)
153 sync_pc();
154
155 switch (t) {
156
157 case 0: /* lsl c (Logical Shift Left by constant) */
158 if (s) {
159 printf("{ uint32_t x = ");
160 if (pc)
161 printf("tmp");
162 else
163 printf("cpu->cd.arm.r[%i]", rm);
164 printf(";\n");
165 if (c != 0) {
166 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
167 printf("if (x & 0x%x)\n"
168 "\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n",
169 (int)(0x80000000 >> (c-1)));
170 printf("x <<= %i;\n", c);
171 }
172 printf(" return x; }\n");
173 } else {
174 if (pc)
175 printf("\treturn tmp");
176 else
177 printf("\treturn cpu->cd.arm.r[%i]", rm);
178 if (c != 0)
179 printf(" << %i", c);
180 printf(";\n");
181 }
182 break;
183
184 case 1: /* lsl Rc (Logical Shift Left by register) */
185 if (s) {
186 printf("{ uint32_t x = ");
187 if (pc)
188 printf("tmp");
189 else
190 printf("cpu->cd.arm.r[%i]", rm);
191 printf(";\n");
192 printf(" uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc);
193 printf(" if (y != 0) {\n");
194 printf(" cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
195 printf(" if (y >= 32) return 0;\n");
196 printf(" x <<= (y - 1);\n");
197 printf(" if (x & 0x80000000)\n"
198 "\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n");
199 printf(" x <<= 1;\n");
200 printf(" }\n");
201 printf(" return x; }\n");
202 } else {
203 printf("{ uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc);
204 printf(" uint32_t x =");
205 if (pc)
206 printf("tmp");
207 else
208 printf("cpu->cd.arm.r[%i]", rm);
209 printf(";\n");
210 printf("if (y > 31) return 0; else x <<= y;\n");
211 printf("return x; }\n");
212 }
213 break;
214
215 case 2: /* lsr c (Logical Shift Right by constant) */
216 /* 1..32 */
217 if (s) {
218 printf("{ uint32_t x = ");
219 if (pc)
220 printf("tmp");
221 else
222 printf("cpu->cd.arm.r[%i]", rm);
223 printf(";\n");
224 if (c == 0)
225 c = 32;
226 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
227 printf("if (x & 0x%x)\n"
228 "\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n",
229 (int)(1 << (c-1)));
230 if (c == 32)
231 printf("x = 0;\n");
232 else
233 printf("x >>= %i;\n", c);
234 printf(" return x; }\n");
235 } else {
236 if (c == 0)
237 printf("\treturn 0;\n");
238 else {
239 if (pc)
240 printf("\treturn tmp");
241 else
242 printf("\treturn cpu->cd.arm.r[%i]",rm);
243 printf(" >> %i;\n", c);
244 }
245 }
246 break;
247
248 case 3: /* lsr Rc (Logical Shift Right by register) */
249 if (s) {
250 printf("{ uint32_t x = ");
251 if (pc)
252 printf("tmp");
253 else
254 printf("cpu->cd.arm.r[%i]", rm);
255 printf(",y=cpu->cd.arm.r[%i]&255;\n", rc);
256 printf("if(y==0) return x;\n");
257 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
258 printf("if(y>31) y=32;\n");
259 printf("y--; x >>= y;\n");
260 printf("if (x & 1) "
261 "cpu->cd.arm.cpsr |= ARM_FLAG_C;\n");
262 printf(" return x >> 1; }\n");
263 } else {
264 printf("{ uint32_t y=cpu->cd.arm.r[%i]&255;\n", rc);
265 printf("uint32_t x=");
266 if (pc)
267 printf("tmp");
268 else
269 printf("cpu->cd.arm.r[%i]",rm);
270 printf("; ");
271 printf("if (y>=32) return 0;\n");
272 printf("return x >> y; } ");
273 }
274 break;
275
276 case 4: /* asr c (Arithmetic Shift Right by constant) */
277 /* 1..32 */
278 if (s) {
279 printf("{ int32_t x = ");
280 if (pc)
281 printf("tmp");
282 else
283 printf("cpu->cd.arm.r[%i]", rm);
284 printf(";\n");
285 if (c == 0)
286 c = 32;
287 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
288 printf("if (x & 0x%x)\n"
289 "\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n",
290 (int)(1 << (c-1)));
291 if (c == 32)
292 printf("x = (x<0)? 0xffffffff : 0;\n");
293 else
294 printf("x >>= %i;\n", c);
295 printf(" return x; }\n");
296 } else {
297 if (c == 0) {
298 printf("\treturn ");
299 if (pc)
300 printf("tmp");
301 else
302 printf("cpu->cd.arm.r[%i]",rm);
303 printf(" & 0x80000000? 0xffffffff : 0;\n");
304 } else {
305 printf("return (int32_t)");
306 if (pc)
307 printf("tmp");
308 else
309 printf("cpu->cd.arm.r[%i]",rm);
310 printf(" >> %i;\n", c);
311 }
312 }
313 break;
314
315 case 5: /* asr Rc (Arithmetic Shift Right by register) */
316 if (s) {
317 printf("{ int32_t x = ");
318 if (pc)
319 printf("tmp");
320 else
321 printf("cpu->cd.arm.r[%i]", rm);
322 printf(",y=cpu->cd.arm.r[%i]&255;\n", rc);
323 printf("if(y==0) return x;\n");
324 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
325 printf("if(y>31) y=31;\n");
326 printf("y--; x >>= y;\n");
327 printf("if (x & 1) "
328 "cpu->cd.arm.cpsr |= ARM_FLAG_C;\n");
329 printf(" return (int32_t)x >> 1; }\n");
330 } else {
331 printf("{ int32_t y=cpu->cd.arm.r[%i]&255;\n", rc);
332 printf("int32_t x=");
333 if (pc)
334 printf("tmp");
335 else
336 printf("cpu->cd.arm.r[%i]",rm);
337 printf("; ");
338 printf("if (y>=31) return (x<0)?0xffffffff:0;\n");
339 printf("return (int32_t)x >> y; } ");
340 }
341 break;
342
343 case 6: /* ror c OR rrx (Arithmetic Shift Right by constant) */
344 /* 0=rrx, 1..31=ror */
345 if (c == 0) {
346 printf("\tprintf(\"%s\\n\");\n", name);
347 printf("\texit(1); /* TODO */\n\treturn 0;\n");
348 } else if (s) {
349 printf("{ uint64_t x = ");
350 if (pc)
351 printf("tmp");
352 else
353 printf("cpu->cd.arm.r[%i]", rm);
354 printf("; x |= (x << 32);\n");
355 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
356 printf("if (x & 0x%x)\n"
357 "\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n",
358 (int)(1 << (c-1)));
359 printf(" return x >> %i; }\n", c);
360 } else {
361 printf("{ uint64_t x=");
362 if (pc)
363 printf("tmp");
364 else
365 printf("cpu->cd.arm.r[%i]",rm);
366 printf("; x |= (x << 32); ");
367 printf("return x >> %i; }\n", c);
368 }
369 break;
370
371 case 7: /* ror Rc (Rotate Right by register) */
372 if (s) {
373 printf("{ uint64_t x = ");
374 if (pc)
375 printf("tmp");
376 else
377 printf("cpu->cd.arm.r[%i]", rm);
378 printf("; int y=cpu->cd.arm.r[%i]&255;\n", rc);
379 printf("if(y==0) return x;\n");
380 printf("y --; y &= 31; x >>= y;\n");
381 printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n");
382 printf("if (x & 1) "
383 "cpu->cd.arm.cpsr |= ARM_FLAG_C;\n");
384 printf(" return x >> 1; }\n");
385 } else {
386 printf("{ int y=cpu->cd.arm.r[%i]&31;\n", rc);
387 printf("uint64_t x=");
388 if (pc)
389 printf("tmp");
390 else
391 printf("cpu->cd.arm.r[%i]",rm);
392 printf("; x |= (x << 32); ");
393 printf("return (x >> y); } ");
394 }
395 break;
396
397 default:
398 printf("\tprintf(\"%s\\n\");\n", name);
399 printf("\texit(1); /* TODO */\n\treturn 0;\n");
400 }
401
402 printf("}\n");
403 }
404
405
406 int main(int argc, char *argv[])
407 {
408 int s, func, f_start, f_end;
409
410 if (argc < 3) {
411 fprintf(stderr, "usage: %s start end\n", argv[0]);
412 exit(1);
413 }
414
415 f_start = strtol(argv[1], NULL, 0);
416 f_end = strtol(argv[2], NULL, 0);
417
418 printf("/*\n * DO NOT EDIT! AUTOMATICALLY GENERATED!\n */\n\n");
419 printf("#include <stdio.h>\n");
420 printf("#include <stdlib.h>\n");
421 printf("#include \"cpu.h\"\n");
422 printf("#include \"misc.h\"\n");
423 printf("\n\n");
424
425 if (f_start != 0 || f_end != 0) {
426 for (s=0; s<=1; s++)
427 for (func=f_start; func<=f_end; func++)
428 f(s, func, 0);
429 } else {
430 for (s=0; s<=1; s++)
431 for (func=0; func<=0xfff; func++) {
432 printf("extern uint32_t ");
433 f(s, func, 1);
434 printf("(struct cpu *, struct arm_"
435 "instr_call *);\n");
436 }
437
438 printf("\nuint32_t (*arm_r[8192])(struct cpu *,"
439 " struct arm_instr_call *) = {\n");
440 for (s=0; s<=1; s++)
441 for (func=0; func<=0xfff; func++) {
442 printf("\t");
443 f(s, func, 1);
444 if (s!=1 || func!=0xfff)
445 printf(",");
446 printf("\n");
447 }
448 printf("};\n\n");
449 }
450
451 return 0;
452 }
453

  ViewVC Help
Powered by ViewVC 1.1.26