/[gxemul]/trunk/src/cpus/cpu_arm.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

Annotation of /trunk/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (hide annotations)
Mon Oct 8 16:19:01 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 31697 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.988 2005/10/11 03:53:57 debug Exp $

==============  RELEASE 0.3.6  ==============

20051008	The bug was not because of faulty ARM documentation after all,
		but it was related to those parts of the code.
		Fixing the RTC (dev_mc146818) to work with CATS.
20051009	Rewriting the R() function; now there are 8192 automatically
		generated smaller functions doing the same thing, but hopefully
		faster. This also fixes some bugs which were triggered when
		trying to compile GXemul inside itself. :-)
		Adding a dummy dev_lpt.
20051010	Small hack to not update virtual translation tables if memory
		accesses are done with the NO_EXCEPTION flag; a time reduction
		of almost a factor 2 for a full NetBSD/cats install. :-)
20051011	Passing -A as the default boot arg for CATS (works fine with
		OpenBSD/cats).

==============  RELEASE 0.3.6.1  ==============


1 dpavlin 14 /*
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 dpavlin 16 * $Id: cpu_arm.c,v 1.29 2005/10/08 01:09:51 debug Exp $
29 dpavlin 14 *
30     * ARM CPU emulation.
31     *
32     * A good source of quick info on ARM instruction encoding:
33     *
34     * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
35     *
36     * (Most "xxxx0101..." and similar strings in this file are from that URL,
37     * or from the ARM manual.)
38     */
39    
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43     #include <ctype.h>
44    
45     #include "arm_cpu_types.h"
46     #include "cpu.h"
47     #include "machine.h"
48     #include "memory.h"
49     #include "misc.h"
50     #include "symbol.h"
51    
52     #define DYNTRANS_32
53     #include "tmp_arm_head.c"
54    
55    
56     /* ARM symbolic register names and condition strings: */
57     static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
58     static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
59    
60     /* Data Processing Instructions: */
61     static char *arm_dpiname[16] = ARM_DPI_NAMES;
62     static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
63     static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
64    
65     /* Forward reference: */
66     void arm_pc_to_pointers(struct cpu *cpu);
67    
68    
69     /*
70     * arm_cpu_new():
71     *
72     * Create a new ARM cpu object by filling the CPU struct.
73     * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
74     */
75     int arm_cpu_new(struct cpu *cpu, struct memory *mem,
76     struct machine *machine, int cpu_id, char *cpu_type_name)
77     {
78     int any_cache = 0, i, found;
79     struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
80    
81     /* Scan the list for this cpu type: */
82     i = 0; found = -1;
83     while (i >= 0 && cpu_type_defs[i].name != NULL) {
84     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
85     found = i;
86     break;
87     }
88     i++;
89     }
90     if (found == -1)
91     return 0;
92    
93     cpu->memory_rw = arm_memory_rw;
94     cpu->update_translation_table = arm_update_translation_table;
95     cpu->invalidate_translation_caches_paddr =
96     arm_invalidate_translation_caches_paddr;
97     cpu->invalidate_code_translation = arm_invalidate_code_translation;
98     cpu->translate_address = arm_translate_address;
99    
100     cpu->cd.arm.cpu_type = cpu_type_defs[found];
101     cpu->name = cpu->cd.arm.cpu_type.name;
102     cpu->is_32bit = 1;
103    
104     cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
105     cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
106     | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
107    
108     if (cpu->machine->prom_emulation) {
109     cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
110     cpu->cd.arm.control |= ARM_CONTROL_S;
111     } else {
112     cpu->cd.arm.cpsr |= ARM_MODE_USR32;
113     cpu->cd.arm.control |= ARM_CONTROL_S | ARM_CONTROL_R;
114     }
115    
116     /* Only show name and caches etc for CPU nr 0: */
117     if (cpu_id == 0) {
118     debug("%s", cpu->name);
119     if (cpu->cd.arm.cpu_type.icache_shift != 0)
120     any_cache = 1;
121     if (cpu->cd.arm.cpu_type.dcache_shift != 0)
122     any_cache = 1;
123     if (any_cache) {
124     debug(" (I+D = %i+%i KB",
125     (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)),
126     (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10)));
127     debug(")");
128     }
129     }
130    
131     /* Coprocessor 15 = the system control coprocessor. */
132     cpu->cd.arm.coproc[15] = arm_coproc_15;
133    
134     /*
135     * NOTE/TODO: Ugly hack for OpenFirmware emulation:
136     */
137     if (cpu->machine->prom_emulation) {
138     cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
139     * 1048576 - 8;
140     store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
141     }
142    
143     return 1;
144     }
145    
146    
147     /*
148     * arm_setup_initial_translation_table():
149     *
150     * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
151     * that the MMU is already enabled by the boot-loader. This function tries
152     * to emulate that.
153     */
154     void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
155     {
156     unsigned char nothing[16384];
157     unsigned int i, j;
158    
159     if (cpu->machine->userland_emul != NULL) {
160     fatal("arm_setup_initial_translation_table(): should not "
161     "be called for userland emulation!\n");
162     exit(1);
163     }
164    
165     cpu->cd.arm.control |= ARM_CONTROL_MMU;
166     cpu->cd.arm.dacr |= 0x00000003;
167     cpu->cd.arm.ttb = ttb_addr;
168    
169     memset(nothing, 0, sizeof(nothing));
170     cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
171     sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
172     for (i=0; i<256; i++)
173     for (j=0x0; j<=0xf; j++) {
174     unsigned char descr[4];
175     uint32_t addr = cpu->cd.arm.ttb +
176     (((j << 28) + (i << 20)) >> 18);
177     uint32_t d = (1048576*i) | 0xc02;
178     /*
179     d = (1048576 * (i + (j==12? 10 : j)*256)) | 2;
180     */
181     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
182     descr[0] = d; descr[1] = d >> 8;
183     descr[2] = d >> 16; descr[3] = d >> 24;
184     } else {
185     descr[3] = d; descr[2] = d >> 8;
186     descr[1] = d >> 16; descr[0] = d >> 24;
187     }
188     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
189     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
190     }
191     }
192    
193    
194     /*
195     * arm_cpu_dumpinfo():
196     */
197     void arm_cpu_dumpinfo(struct cpu *cpu)
198     {
199     struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
200    
201     debug(" (I+D = %i+%i KB)\n",
202     (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
203     }
204    
205    
206     /*
207     * arm_cpu_list_available_types():
208     *
209     * Print a list of available ARM CPU types.
210     */
211     void arm_cpu_list_available_types(void)
212     {
213     int i, j;
214     struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
215    
216     i = 0;
217     while (tdefs[i].name != NULL) {
218     debug("%s", tdefs[i].name);
219     for (j=13 - strlen(tdefs[i].name); j>0; j--)
220     debug(" ");
221     i++;
222     if ((i % 5) == 0 || tdefs[i].name == NULL)
223     debug("\n");
224     }
225     }
226    
227    
228     /*
229     * arm_cpu_register_match():
230     */
231     void arm_cpu_register_match(struct machine *m, char *name,
232     int writeflag, uint64_t *valuep, int *match_register)
233     {
234     int i, cpunr = 0;
235    
236     /* CPU number: */
237    
238     /* TODO */
239    
240     /* Register names: */
241     for (i=0; i<N_ARM_REGS; i++) {
242     if (strcasecmp(name, arm_regname[i]) == 0) {
243     if (writeflag) {
244     m->cpus[cpunr]->cd.arm.r[i] = *valuep;
245     if (i == ARM_PC)
246     m->cpus[cpunr]->pc = *valuep;
247     } else
248     *valuep = m->cpus[cpunr]->cd.arm.r[i];
249     *match_register = 1;
250     }
251     }
252     }
253    
254    
255     /*
256     * arm_cpu_register_dump():
257     *
258     * Dump cpu registers in a relatively readable format.
259     *
260     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
261     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
262     */
263     void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
264     {
265     char *symbol;
266     uint64_t offset;
267     int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
268     int i, x = cpu->cpu_id;
269    
270     if (gprs) {
271     symbol = get_symbol_name(&cpu->machine->symbol_context,
272     cpu->cd.arm.r[ARM_PC], &offset);
273     debug("cpu%i: cpsr = ", x);
274     debug("%s%s%s%s%s%s",
275     (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
276     (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
277     (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
278     (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
279     (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
280     (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
281     if (mode < ARM_MODE_USR32)
282     debug(" pc = 0x%07x",
283     (int)(cpu->cd.arm.r[ARM_PC] & 0x03ffffff));
284     else
285     debug(" pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
286    
287     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
288    
289     for (i=0; i<N_ARM_REGS; i++) {
290     if ((i % 4) == 0)
291     debug("cpu%i:", x);
292     if (i != ARM_PC)
293     debug(" %s = 0x%08x", arm_regname[i],
294     (int)cpu->cd.arm.r[i]);
295     if ((i % 4) == 3)
296     debug("\n");
297     }
298     }
299    
300     if (coprocs & 1) {
301     int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
302     debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
303     switch (m) {
304     case ARM_MODE_USR32:
305     debug("USR32)\n"); break;
306     case ARM_MODE_SYS32:
307     debug("SYS32)\n"); break;
308     case ARM_MODE_FIQ32:
309     debug("FIQ32)\n"); break;
310     case ARM_MODE_IRQ32:
311     debug("IRQ32)\n"); break;
312     case ARM_MODE_SVC32:
313     debug("SVC32)\n"); break;
314     case ARM_MODE_ABT32:
315     debug("ABT32)\n"); break;
316     case ARM_MODE_UND32:
317     debug("UND32)\n"); break;
318     default:debug("unimplemented)\n");
319     }
320    
321     if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
322     debug("cpu%i: usr r8..r14 =", x);
323     for (i=0; i<7; i++)
324     debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
325     debug("\n");
326     }
327    
328     if (m != ARM_MODE_FIQ32) {
329     debug("cpu%i: fiq r8..r14 =", x);
330     for (i=0; i<7; i++)
331     debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
332     debug("\n");
333     }
334    
335     if (m != ARM_MODE_IRQ32) {
336     debug("cpu%i: irq r13..r14 =", x);
337     for (i=0; i<2; i++)
338     debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
339     debug("\n");
340     }
341    
342     if (m != ARM_MODE_SVC32) {
343     debug("cpu%i: svc r13..r14 =", x);
344     for (i=0; i<2; i++)
345     debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
346     debug("\n");
347     }
348    
349     if (m != ARM_MODE_ABT32) {
350     debug("cpu%i: abt r13..r14 =", x);
351     for (i=0; i<2; i++)
352     debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
353     debug("\n");
354     }
355    
356     if (m != ARM_MODE_UND32) {
357     debug("cpu%i: und r13..r14 =", x);
358     for (i=0; i<2; i++)
359     debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
360     debug("\n");
361     }
362     }
363    
364     if (coprocs & 2) {
365     debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
366     debug("cpu%i: MMU: %s\n", x,
367     cpu->cd.arm.control &
368     ARM_CONTROL_MMU? "enabled" : "disabled");
369     debug("cpu%i: alignment checks: %s\n", x,
370     cpu->cd.arm.control &
371     ARM_CONTROL_ALIGN? "enabled" : "disabled");
372     debug("cpu%i: [data] cache: %s\n", x,
373     cpu->cd.arm.control &
374     ARM_CONTROL_CACHE? "enabled" : "disabled");
375     debug("cpu%i: instruction cache: %s\n", x,
376     cpu->cd.arm.control &
377     ARM_CONTROL_ICACHE? "enabled" : "disabled");
378     debug("cpu%i: write buffer: %s\n", x,
379     cpu->cd.arm.control &
380     ARM_CONTROL_WBUFFER? "enabled" : "disabled");
381     debug("cpu%i: prog32: %s\n", x,
382     cpu->cd.arm.control &
383     ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
384     debug("cpu%i: data32: %s\n", x,
385     cpu->cd.arm.control &
386     ARM_CONTROL_DATA32? "yes" : "no (using data26)");
387     debug("cpu%i: endianness: %s\n", x,
388     cpu->cd.arm.control &
389     ARM_CONTROL_BIG? "big endian" : "little endian");
390     debug("cpu%i: high vectors: %s\n", x,
391     cpu->cd.arm.control &
392     ARM_CONTROL_V? "yes (0xffff0000)" : "no");
393    
394     debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
395     cpu->cd.arm.ttb, cpu->cd.arm.dacr);
396     debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
397     cpu->cd.arm.fsr, cpu->cd.arm.far);
398     }
399     }
400    
401    
402     /*
403     * arm_cpu_show_full_statistics():
404     *
405     * Show detailed statistics on opcode usage on each cpu.
406     */
407     void arm_cpu_show_full_statistics(struct machine *m)
408     {
409     fatal("arm_cpu_show_full_statistics(): TODO\n");
410     }
411    
412    
413     /*
414     * arm_cpu_tlbdump():
415     *
416     * Called from the debugger to dump the TLB in a readable format.
417     * x is the cpu number to dump, or -1 to dump all CPUs.
418     *
419     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
420     * just dumped.
421     */
422     void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
423     {
424     fatal("arm_cpu_tlbdump(): TODO\n");
425     }
426    
427    
428     /*
429     * arm_save_register_bank():
430     */
431     void arm_save_register_bank(struct cpu *cpu)
432     {
433     /* Save away current registers: */
434     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
435     case ARM_MODE_USR32:
436     case ARM_MODE_SYS32:
437     memcpy(cpu->cd.arm.default_r8_r14,
438     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
439     break;
440     case ARM_MODE_FIQ32:
441     memcpy(cpu->cd.arm.fiq_r8_r14,
442     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
443     break;
444     case ARM_MODE_IRQ32:
445 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
446     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
447 dpavlin 14 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
448     cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
449     break;
450     case ARM_MODE_SVC32:
451 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
452     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
453 dpavlin 14 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
454     cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
455     break;
456     case ARM_MODE_ABT32:
457 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
458     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
459 dpavlin 14 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
460     cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
461     break;
462     case ARM_MODE_UND32:
463 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
464     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
465 dpavlin 14 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
466     cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
467     break;
468     default:fatal("arm_save_register_bank: unimplemented mode %i\n",
469     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
470     exit(1);
471     }
472     }
473    
474    
475     /*
476     * arm_load_register_bank():
477     */
478     void arm_load_register_bank(struct cpu *cpu)
479     {
480     /* Load new registers: */
481     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
482     case ARM_MODE_USR32:
483     case ARM_MODE_SYS32:
484     memcpy(&cpu->cd.arm.r[8],
485     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
486     break;
487     case ARM_MODE_FIQ32:
488     memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
489     sizeof(uint32_t) * 7);
490     break;
491     case ARM_MODE_IRQ32:
492 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
493     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
494 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
495     cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
496     break;
497     case ARM_MODE_SVC32:
498 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
499     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
500 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
501     cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
502     break;
503     case ARM_MODE_ABT32:
504 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
505     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
506 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
507     cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
508     break;
509     case ARM_MODE_UND32:
510 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
511     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
512 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
513     cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
514     break;
515     default:fatal("arm_load_register_bank: unimplemented mode %i\n",
516     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
517     exit(1);
518     }
519     }
520    
521    
522     /*
523     * arm_exception():
524     */
525     void arm_exception(struct cpu *cpu, int exception_nr)
526     {
527     int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
528     int oldmode, newmode;
529     uint32_t retaddr;
530    
531     if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
532     fatal("arm_exception(): exception_nr = %i\n", exception_nr);
533     exit(1);
534     }
535    
536     retaddr = cpu->pc;
537    
538     debug("[ arm_exception(): ");
539    
540     switch (exception_nr) {
541     case ARM_EXCEPTION_RESET:
542     cpu->running = 0;
543     fatal("RESET: TODO");
544     exit(1);
545     case ARM_EXCEPTION_UND:
546     debug("UNDEFINED");
547     retaddr += 4;
548     break;
549     case ARM_EXCEPTION_SWI:
550     debug("SWI");
551     retaddr += 4;
552     break;
553     case ARM_EXCEPTION_PREF_ABT:
554     debug("PREFETCH ABORT");
555     retaddr += 4;
556     break;
557     case ARM_EXCEPTION_IRQ:
558     debug("IRQ");
559     retaddr += 4;
560     break;
561     case ARM_EXCEPTION_FIQ:
562     debug("FIQ");
563     retaddr += 4;
564     break;
565     case ARM_EXCEPTION_DATA_ABT:
566     debug("DATA ABORT, far=0x%08x fsr=0x%02x",
567     cpu->cd.arm.far, cpu->cd.arm.fsr);
568     retaddr += 8;
569     break;
570     }
571    
572     debug(" ]\n");
573    
574     arm_save_register_bank(cpu);
575    
576     switch (arm_exception_to_mode[exception_nr]) {
577     case ARM_MODE_SVC32:
578     cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
579     case ARM_MODE_ABT32:
580     cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
581     case ARM_MODE_UND32:
582     cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
583     case ARM_MODE_IRQ32:
584     cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
585     case ARM_MODE_FIQ32:
586     cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
587     default:fatal("arm_exception(): unimplemented exception nr\n");
588     exit(1);
589     }
590    
591     /*
592     * Disable Thumb mode (because exception handlers always execute
593     * in ARM mode), set the exception mode, and disable interrupts:
594     */
595     cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
596    
597     oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
598    
599     cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
600     cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
601    
602     newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
603     if (oldmode == newmode) {
604     fatal("Exception caused no mode change? TODO\n");
605     exit(1);
606     }
607    
608     cpu->cd.arm.cpsr |= ARM_FLAG_I;
609     if (exception_nr == ARM_EXCEPTION_RESET ||
610     exception_nr == ARM_EXCEPTION_FIQ)
611     cpu->cd.arm.cpsr |= ARM_FLAG_F;
612    
613     /* Load the new register bank, if we switched: */
614     arm_load_register_bank(cpu);
615    
616     /* Set the return address and new PC: */
617     cpu->cd.arm.r[ARM_LR] = retaddr;
618    
619     cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
620     ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
621     arm_pc_to_pointers(cpu);
622     }
623    
624    
625     /*
626     * arm_cpu_interrupt():
627     *
628     * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
629     * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
630     *
631     * TODO: don't hardcode to footbridge!
632     */
633     int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
634     {
635     /* fatal("arm_cpu_interrupt(): 0x%llx\n", (int)irq_nr); */
636     if (irq_nr <= 64) {
637     if (cpu->machine->md_interrupt != NULL)
638     cpu->machine->md_interrupt(cpu->machine,
639     cpu, irq_nr, 1);
640     else
641     fatal("arm_cpu_interrupt(): md_interrupt == NULL\n");
642     } else {
643     /* Assert ARM IRQs: */
644     cpu->cd.arm.irq_asserted = 1;
645     }
646    
647     return 1;
648     }
649    
650    
651     /*
652     * arm_cpu_interrupt_ack():
653     */
654     int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
655     {
656     if (irq_nr <= 64) {
657     if (cpu->machine->md_interrupt != NULL)
658     cpu->machine->md_interrupt(cpu->machine,
659     cpu, irq_nr, 0);
660     } else {
661     /* De-assert ARM IRQs: */
662     cpu->cd.arm.irq_asserted = 0;
663     }
664    
665     return 1;
666     }
667    
668    
669     /*
670     * arm_cpu_disassemble_instr():
671     *
672     * Convert an instruction word into human readable format, for instruction
673     * tracing.
674     *
675     * If running is 1, cpu->pc should be the address of the instruction.
676     *
677     * If running is 0, things that depend on the runtime environment (eg.
678     * register contents) will not be shown, and addr will be used instead of
679     * cpu->pc for relative addresses.
680     */
681     int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
682     int running, uint64_t dumpaddr, int bintrans)
683     {
684     uint32_t iw, tmp;
685     int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
686     int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
687     char *symbol, *condition;
688     uint64_t offset;
689    
690     if (running)
691     dumpaddr = cpu->pc;
692    
693     symbol = get_symbol_name(&cpu->machine->symbol_context,
694     dumpaddr, &offset);
695     if (symbol != NULL && offset == 0)
696     debug("<%s>\n", symbol);
697    
698     if (cpu->machine->ncpus > 1 && running)
699     debug("cpu%i:\t", cpu->cpu_id);
700    
701     debug("%08x: ", (int)dumpaddr);
702    
703     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
704     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
705     else
706     iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
707     debug("%08x\t", (int)iw);
708    
709     condition = arm_condition_string[iw >> 28];
710     main_opcode = (iw >> 24) & 15;
711     secondary_opcode = (iw >> 21) & 15;
712     u_bit = (iw >> 23) & 1;
713     b_bit = (iw >> 22) & 1;
714     w_bit = (iw >> 21) & 1;
715     s_bit = l_bit = (iw >> 20) & 1;
716     r16 = (iw >> 16) & 15;
717     r12 = (iw >> 12) & 15;
718     r8 = (iw >> 8) & 15;
719    
720     switch (main_opcode) {
721     case 0x0:
722     case 0x1:
723     case 0x2:
724     case 0x3:
725     /*
726     * Special cases first:
727     */
728    
729     /*
730     * Multiplication:
731     * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
732     */
733     if ((iw & 0x0fc000f0) == 0x00000090) {
734     int a_bit = (iw >> 21) & 1;
735     debug("%s%s%s\t", a_bit? "mla" : "mul",
736     condition, s_bit? "s" : "");
737     debug("%s,", arm_regname[r16]);
738     debug("%s,", arm_regname[iw & 15]);
739     debug("%s", arm_regname[r8]);
740     if (a_bit)
741     debug(",%s", arm_regname[r12]);
742     debug("\n");
743     break;
744     }
745    
746     /*
747     * Long multiplication:
748     * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
749     */
750     if ((iw & 0x0f8000f0) == 0x00800090) {
751     int u_bit = (iw >> 22) & 1;
752     int a_bit = (iw >> 21) & 1;
753     debug("%s%sl%s%s\t", u_bit? "s" : "u",
754     a_bit? "mla" : "mul", condition, s_bit? "s" : "");
755     debug("%s,", arm_regname[r12]);
756     debug("%s,", arm_regname[r16]);
757     debug("%s,", arm_regname[iw & 15]);
758     debug("%s\n", arm_regname[r8]);
759     break;
760     }
761    
762     /*
763     * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
764     */
765     if ((iw & 0x0ff000d0) == 0x01200010) {
766     int l_bit = iw & 0x20;
767     debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
768     arm_regname[iw & 15]);
769     break;
770     }
771    
772     /*
773     * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
774     * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
775     * xxxx0001 0s001111 dddd0000 00000000 MRS
776     */
777     if ((iw & 0x0fb0fff0) == 0x0120f000 ||
778     (iw & 0x0fb0f000) == 0x0320f000) {
779     int a = (iw >> 16) & 15;
780     debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
781     debug("PSR_");
782     switch (a) {
783     case 1: debug("ctl"); break;
784     case 8: debug("flg"); break;
785     case 9: debug("all"); break;
786     default:debug(" UNIMPLEMENTED (a=%i)", a);
787     }
788     if (iw & 0x02000000) {
789     int r = (iw >> 7) & 30;
790     uint32_t b = iw & 0xff;
791     while (r-- > 0)
792     b = (b >> 1) | ((b & 1) << 31);
793     debug(",#0x%x\n", b);
794     } else
795     debug(",%s\n", arm_regname[iw & 15]);
796     break;
797     }
798     if ((iw & 0x0fbf0fff) == 0x010f0000) {
799     debug("mrs%s\t", condition);
800     debug("%s,%sPSR\n", arm_regname[r12],
801     (iw&0x400000)? "S":"C");
802     break;
803     }
804    
805     /*
806     * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
807     */
808     if ((iw & 0x0fb00ff0) == 0x01000090) {
809     debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
810     debug("%s,%s,[%s]\n", arm_regname[r12],
811     arm_regname[iw & 15], arm_regname[r16]);
812     break;
813     }
814    
815     /*
816     * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
817     */
818     if ((iw & 0x0e000090) == 0x00000090) {
819     int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
820     int regform = !(iw & 0x00400000);
821     p_bit = main_opcode & 1;
822     /*
823     * TODO: detect some illegal variants:
824     * signed store, or unsigned byte load/store
825     */
826     if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
827     debug("TODO: r12 odd, not load/store\n");
828     break;
829     }
830     /* Semi-generic case: */
831     debug("%sr%s", iw & 0x00100000? "ld" : "st",
832     condition);
833     if (!l_bit && (iw & 0xd0) == 0xd0) {
834     debug("d"); /* Double-register */
835     } else {
836     if (iw & 0x40)
837     debug("s"); /* signed */
838     if (iw & 0x20)
839     debug("h"); /* half-word */
840     else
841     debug("b"); /* byte */
842     }
843     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
844     if (p_bit) {
845     /* Pre-index: */
846     if (regform)
847     debug(",%s%s", u_bit? "" : "-",
848     arm_regname[iw & 15]);
849     else {
850     if (imm != 0)
851     debug(",#%s%i", u_bit? "" : "-",
852     imm);
853     }
854     debug("]%s\n", w_bit? "!" : "");
855     } else {
856     /* Post-index: */
857     debug("],");
858     if (regform)
859     debug("%s%s\n", u_bit? "" : "-",
860     arm_regname[iw & 15]);
861     else
862     debug("#%s%i\n", u_bit? "" : "-", imm);
863     }
864     break;
865     }
866    
867     /* Other special cases: */
868     if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
869     debug("UNIMPLEMENTED reg (c!=0), t odd\n");
870     break;
871     }
872    
873     /*
874     * Generic Data Processing Instructions:
875     *
876     * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
877     * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
878     */
879    
880     debug("%s%s%s\t", arm_dpiname[secondary_opcode],
881     condition, s_bit? "s" : "");
882     if (arm_dpi_uses_d[secondary_opcode])
883     debug("%s,", arm_regname[r12]);
884     if (arm_dpi_uses_n[secondary_opcode])
885     debug("%s,", arm_regname[r16]);
886    
887     if (main_opcode & 2) {
888     /* Immediate form: */
889     int r = (iw >> 7) & 30;
890     uint32_t b = iw & 0xff;
891     while (r-- > 0)
892     b = (b >> 1) | ((b & 1) << 31);
893     if (b < 15)
894     debug("#%i", b);
895     else
896     debug("#0x%x", b);
897     } else {
898     /* Register form: */
899     int t = (iw >> 4) & 7;
900     int c = (iw >> 7) & 31;
901     debug("%s", arm_regname[iw & 15]);
902     switch (t) {
903     case 0: if (c != 0)
904     debug(", lsl #%i", c);
905     break;
906     case 1: debug(", lsl %s", arm_regname[c >> 1]);
907     break;
908     case 2: debug(", lsr #%i", c? c : 32);
909     break;
910     case 3: debug(", lsr %s", arm_regname[c >> 1]);
911     break;
912     case 4: debug(", asr #%i", c? c : 32);
913     break;
914     case 5: debug(", asr %s", arm_regname[c >> 1]);
915     break;
916     case 6: if (c != 0)
917     debug(", ror #%i", c);
918     else
919     debug(", rrx");
920     break;
921     case 7: debug(", ror %s", arm_regname[c >> 1]);
922     break;
923     }
924    
925     /* mov pc,reg: */
926     if (running && t == 0 && c == 0 && secondary_opcode
927     == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
928     symbol = get_symbol_name(&cpu->machine->
929     symbol_context, cpu->cd.arm.r[iw & 15],
930     &offset);
931     if (symbol != NULL)
932     debug(" \t<%s>", symbol);
933     }
934     }
935     debug("\n");
936     break;
937     case 0x4: /* Single Data Transfer */
938     case 0x5:
939     case 0x6:
940     case 0x7:
941     /* Special case first: */
942     if ((iw & 0xfc70f000) == 0xf450f000) {
943     /* Preload: */
944     debug("pld\t[%s]\n", arm_regname[r16]);
945     break;
946     }
947    
948     /*
949     * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
950     * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
951     */
952     p_bit = main_opcode & 1;
953     if (main_opcode >= 6 && iw & 0x10) {
954     debug("TODO: single data transf. but 0x10\n");
955     break;
956     }
957     debug("%s%s%s", l_bit? "ldr" : "str",
958     condition, b_bit? "b" : "");
959     if (!p_bit && w_bit)
960     debug("t");
961     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
962     if ((iw & 0x0e000000) == 0x04000000) {
963     /* Immediate form: */
964     uint32_t imm = iw & 0xfff;
965     if (!p_bit)
966     debug("]");
967     if (imm != 0)
968     debug(",#%s%i", u_bit? "" : "-", imm);
969     if (p_bit)
970     debug("]");
971     } else if ((iw & 0x0e000010) == 0x06000000) {
972     /* Register form: */
973     if (!p_bit)
974     debug("]");
975     if ((iw & 0xfff) != 0)
976     debug(",%s%s", u_bit? "" : "-",
977     arm_regname[iw & 15]);
978     if ((iw & 0xff0) != 0x000) {
979     int c = (iw >> 7) & 31;
980     int t = (iw >> 4) & 7;
981     switch (t) {
982     case 0: if (c != 0)
983     debug(", lsl #%i", c);
984     break;
985     case 2: debug(", lsr #%i", c? c : 32);
986     break;
987     case 4: debug(", asr #%i", c? c : 32);
988     break;
989     case 6: if (c != 0)
990     debug(", ror #%i", c);
991     else
992     debug(", rrx");
993     break;
994     }
995     }
996     if (p_bit)
997     debug("]");
998     } else {
999     debug("UNKNOWN\n");
1000     break;
1001     }
1002     debug("%s", (p_bit && w_bit)? "!" : "");
1003     if ((iw & 0x0f000000) == 0x05000000 &&
1004     (r16 == ARM_PC || running)) {
1005     unsigned char tmpw[4];
1006     uint32_t imm = iw & 0xfff;
1007     uint32_t addr = (u_bit? imm : -imm);
1008     if (r16 == ARM_PC)
1009     addr += dumpaddr + 8;
1010     else
1011     addr += cpu->cd.arm.r[r16];
1012     symbol = get_symbol_name(&cpu->machine->symbol_context,
1013     addr, &offset);
1014     if (symbol != NULL)
1015     debug(" \t<%s", symbol);
1016     else
1017     debug(" \t<0x%08x", addr);
1018     if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1019     b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1020     || (!l_bit && running)) {
1021     if (l_bit) {
1022     if (cpu->byte_order ==
1023     EMUL_LITTLE_ENDIAN)
1024     addr = tmpw[0] +(tmpw[1] << 8) +
1025     (tmpw[2]<<16)+(tmpw[3]<<24);
1026     else
1027     addr = tmpw[3] + (tmpw[2]<<8) +
1028     (tmpw[1]<<16)+(tmpw[0]<<24);
1029     } else {
1030     tmpw[0] = addr = cpu->cd.arm.r[r12];
1031     if (r12 == ARM_PC)
1032     addr += 8;
1033     }
1034     debug(": ");
1035     if (b_bit)
1036     debug("%i", tmpw[0]);
1037     else {
1038     symbol = get_symbol_name(&cpu->machine->
1039     symbol_context, addr, &offset);
1040     if (symbol != NULL)
1041     debug("%s", symbol);
1042     else if ((int32_t)addr > -256 &&
1043     (int32_t)addr < 256)
1044     debug("%i", addr);
1045     else
1046     debug("0x%x", addr);
1047     }
1048     }
1049     debug(">");
1050     }
1051     debug("\n");
1052     break;
1053     case 0x8: /* Block Data Transfer */
1054     case 0x9:
1055     /* xxxx100P USWLnnnn llllllll llllllll */
1056     p_bit = main_opcode & 1;
1057     s_bit = b_bit;
1058     debug("%s%s", l_bit? "ldm" : "stm", condition);
1059     switch (u_bit * 2 + p_bit) {
1060     case 0: debug("da"); break;
1061     case 1: debug("db"); break;
1062     case 2: debug("ia"); break;
1063     case 3: debug("ib"); break;
1064     }
1065     debug("\t%s", arm_regname[r16]);
1066     if (w_bit)
1067     debug("!");
1068     debug(",{");
1069     n = 0;
1070     for (i=0; i<16; i++)
1071     if ((iw >> i) & 1) {
1072     debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1073     n++;
1074     }
1075     debug("}");
1076     if (s_bit)
1077     debug("^");
1078     debug("\n");
1079     break;
1080     case 0xa: /* B: branch */
1081     case 0xb: /* BL: branch and link */
1082     debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1083     tmp = (iw & 0x00ffffff) << 2;
1084     if (tmp & 0x02000000)
1085     tmp |= 0xfc000000;
1086     tmp = (int32_t)(dumpaddr + tmp + 8);
1087     debug("0x%x", (int)tmp);
1088     symbol = get_symbol_name(&cpu->machine->symbol_context,
1089     tmp, &offset);
1090     if (symbol != NULL)
1091     debug(" \t<%s>", symbol);
1092     debug("\n");
1093     break;
1094     case 0xc: /* Coprocessor */
1095     case 0xd: /* LDC/STC */
1096     /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1097     debug("TODO: coprocessor LDC/STC\n");
1098     break;
1099     case 0xe: /* CDP (Coprocessor Op) */
1100     /* or MRC/MCR!
1101     * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1102     * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1103     */
1104     if (iw & 0x10) {
1105     debug("%s%s\t",
1106     (iw & 0x00100000)? "mrc" : "mcr", condition);
1107     debug("%i,%i,r%i,cr%i,cr%i,%i",
1108     (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1109     (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1110     (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1111     } else {
1112     debug("cdp%s\t", condition);
1113     debug("%i,%i,cr%i,cr%i,cr%i",
1114     (int)((iw >> 8) & 15),
1115     (int)((iw >>20) & 15),
1116     (int)((iw >>12) & 15),
1117     (int)((iw >>16) & 15),
1118     (int)((iw >> 0) & 15));
1119     if ((iw >> 5) & 7)
1120     debug(",0x%x", (int)((iw >> 5) & 7));
1121     }
1122     debug("\n");
1123     break;
1124     case 0xf: /* SWI */
1125     debug("swi%s\t", condition);
1126     debug("0x%x\n", (int)(iw & 0x00ffffff));
1127     break;
1128     default:debug("UNIMPLEMENTED\n");
1129     }
1130    
1131     return sizeof(uint32_t);
1132     }
1133    
1134    
1135     /*****************************************************************************/
1136    
1137    
1138     /*
1139     * arm_mcr_mrc():
1140     *
1141     * Coprocessor register move.
1142     *
1143     * The program counter should be synched before calling this function (to
1144     * make debug output with the correct PC value possible).
1145     */
1146     void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1147     {
1148     int opcode1 = (iword >> 21) & 7;
1149     int l_bit = (iword >> 20) & 1;
1150     int crn = (iword >> 16) & 15;
1151     int rd = (iword >> 12) & 15;
1152     int cp_num = (iword >> 8) & 15;
1153     int opcode2 = (iword >> 5) & 7;
1154     int crm = iword & 15;
1155    
1156     if (cpu->cd.arm.coproc[cp_num] != NULL)
1157     cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1158     crn, crm, rd);
1159     else {
1160     fatal("arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1161     "cp_num=%i\n", (int)cpu->pc, iword, cp_num);
1162     exit(1);
1163     }
1164     }
1165    
1166    
1167     /*
1168     * arm_cdp():
1169     *
1170     * Coprocessor operations.
1171     *
1172     * The program counter should be synched before calling this function (to
1173     * make debug output with the correct PC value possible).
1174     */
1175     void arm_cdp(struct cpu *cpu, uint32_t iword)
1176     {
1177     fatal("arm_cdp: pc=0x%08x, iword=0x%08x\n", (int)cpu->pc, iword);
1178     exit(1);
1179     }
1180    
1181    
1182     /*****************************************************************************/
1183    
1184    
1185     #include "tmp_arm_tail.c"
1186    

  ViewVC Help
Powered by ViewVC 1.1.26