/[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 32 - (hide annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 40328 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 32 * $Id: cpu_arm.c,v 1.64 2006/09/09 09:04:32 debug Exp $
29 dpavlin 14 *
30     * ARM CPU emulation.
31     *
32 dpavlin 20 *
33 dpavlin 14 * A good source of quick info on ARM instruction encoding:
34     *
35     * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
36     */
37    
38     #include <stdio.h>
39     #include <stdlib.h>
40     #include <string.h>
41     #include <ctype.h>
42    
43     #include "arm_cpu_types.h"
44     #include "cpu.h"
45     #include "machine.h"
46     #include "memory.h"
47     #include "misc.h"
48 dpavlin 22 #include "of.h"
49 dpavlin 32 #include "settings.h"
50 dpavlin 14 #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 dpavlin 20 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
66    
67 dpavlin 18 /* For quick_pc_to_pointers(): */
68 dpavlin 22 void arm_pc_to_pointers(struct cpu *cpu);
69     #include "quick_pc_to_pointers.h"
70 dpavlin 14
71    
72     /*
73     * arm_cpu_new():
74     *
75     * Create a new ARM cpu object by filling the CPU struct.
76     * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
77     */
78     int arm_cpu_new(struct cpu *cpu, struct memory *mem,
79     struct machine *machine, int cpu_id, char *cpu_type_name)
80     {
81 dpavlin 32 int i, found;
82 dpavlin 14 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
83    
84     /* Scan the list for this cpu type: */
85     i = 0; found = -1;
86     while (i >= 0 && cpu_type_defs[i].name != NULL) {
87     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
88     found = i;
89     break;
90     }
91     i++;
92     }
93     if (found == -1)
94     return 0;
95    
96 dpavlin 28 cpu->run_instr = arm_run_instr;
97 dpavlin 14 cpu->memory_rw = arm_memory_rw;
98     cpu->update_translation_table = arm_update_translation_table;
99 dpavlin 18 cpu->invalidate_translation_caches =
100     arm_invalidate_translation_caches;
101 dpavlin 14 cpu->invalidate_code_translation = arm_invalidate_code_translation;
102 dpavlin 26 cpu->translate_v2p = arm_translate_v2p;
103 dpavlin 14
104 dpavlin 22 cpu->cd.arm.cpu_type = cpu_type_defs[found];
105     cpu->name = cpu->cd.arm.cpu_type.name;
106     cpu->is_32bit = 1;
107 dpavlin 32 cpu->byte_order = EMUL_LITTLE_ENDIAN;
108 dpavlin 14
109     cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
110     cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
111     | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
112 dpavlin 22 /* TODO: default auxctrl contents */
113 dpavlin 14
114     if (cpu->machine->prom_emulation) {
115     cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
116     cpu->cd.arm.control |= ARM_CONTROL_S;
117     } else {
118 dpavlin 18 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
119     cpu->cd.arm.control |= ARM_CONTROL_R;
120 dpavlin 14 }
121    
122     /* Only show name and caches etc for CPU nr 0: */
123     if (cpu_id == 0) {
124     debug("%s", cpu->name);
125 dpavlin 32 if (cpu->cd.arm.cpu_type.icache_shift != 0 ||
126     cpu->cd.arm.cpu_type.dcache_shift != 0) {
127     int isize = cpu->cd.arm.cpu_type.icache_shift;
128     int dsize = cpu->cd.arm.cpu_type.dcache_shift;
129     if (isize != 0)
130     isize = 1 << (isize - 10);
131     if (dsize != 0)
132     dsize = 1 << (dsize - 10);
133     debug(" (I+D = %i+%i KB)", isize, dsize);
134 dpavlin 14 }
135     }
136    
137 dpavlin 22 /* TODO: Some of these values (iway and dway) aren't used yet: */
138     cpu->cd.arm.cachetype =
139     (5 << ARM_CACHETYPE_CLASS_SHIFT)
140     | (1 << ARM_CACHETYPE_HARVARD_SHIFT)
141     | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
142     ARM_CACHETYPE_DSIZE_SHIFT)
143     | (5 << ARM_CACHETYPE_DASSOC_SHIFT) /* 32-way */
144     | (2 << ARM_CACHETYPE_DLINE_SHIFT) /* 8 words/line */
145     | ((cpu->cd.arm.cpu_type.icache_shift - 9) <<
146     ARM_CACHETYPE_ISIZE_SHIFT)
147     | (5 << ARM_CACHETYPE_IASSOC_SHIFT) /* 32-way */
148     | (2 << ARM_CACHETYPE_ILINE_SHIFT); /* 8 words/line */
149    
150 dpavlin 14 /* Coprocessor 15 = the system control coprocessor. */
151     cpu->cd.arm.coproc[15] = arm_coproc_15;
152    
153 dpavlin 22 /* Coprocessor 14 for XScale: */
154     if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE)
155     cpu->cd.arm.coproc[14] = arm_coproc_xscale_14;
156    
157 dpavlin 14 /*
158     * NOTE/TODO: Ugly hack for OpenFirmware emulation:
159     */
160     if (cpu->machine->prom_emulation) {
161     cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
162     * 1048576 - 8;
163     store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
164     }
165    
166 dpavlin 20 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
167    
168 dpavlin 32 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
169     for (i=0; i<N_ARM_REGS - 1; i++)
170     CPU_SETTINGS_ADD_REGISTER32(arm_regname[i], cpu->cd.arm.r[i]);
171    
172 dpavlin 14 return 1;
173     }
174    
175    
176     /*
177     * arm_setup_initial_translation_table():
178     *
179     * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
180     * that the MMU is already enabled by the boot-loader. This function tries
181     * to emulate that.
182     */
183     void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
184     {
185     unsigned char nothing[16384];
186     unsigned int i, j;
187    
188     if (cpu->machine->userland_emul != NULL) {
189     fatal("arm_setup_initial_translation_table(): should not "
190     "be called for userland emulation!\n");
191     exit(1);
192     }
193    
194     cpu->cd.arm.control |= ARM_CONTROL_MMU;
195 dpavlin 26 cpu->translate_v2p = arm_translate_v2p_mmu;
196 dpavlin 14 cpu->cd.arm.dacr |= 0x00000003;
197     cpu->cd.arm.ttb = ttb_addr;
198    
199     memset(nothing, 0, sizeof(nothing));
200     cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
201     sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
202     for (i=0; i<256; i++)
203     for (j=0x0; j<=0xf; j++) {
204     unsigned char descr[4];
205     uint32_t addr = cpu->cd.arm.ttb +
206     (((j << 28) + (i << 20)) >> 18);
207     uint32_t d = (1048576*i) | 0xc02;
208 dpavlin 18
209     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
210     descr[0] = d; descr[1] = d >> 8;
211     descr[2] = d >> 16; descr[3] = d >> 24;
212     } else {
213     descr[3] = d; descr[2] = d >> 8;
214     descr[1] = d >> 16; descr[0] = d >> 24;
215     }
216     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
217     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
218     }
219     }
220    
221    
222 dpavlin 14 /*
223 dpavlin 18 * arm_translation_table_set_l1():
224     */
225     void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
226     uint32_t paddr)
227     {
228     unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
229    
230     for (i=0; i<256; i++)
231     for (j=vhigh; j<=vhigh; j++) {
232     unsigned char descr[4];
233     uint32_t addr = cpu->cd.arm.ttb +
234     (((j << 28) + (i << 20)) >> 18);
235     uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
236    
237 dpavlin 14 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
238     descr[0] = d; descr[1] = d >> 8;
239     descr[2] = d >> 16; descr[3] = d >> 24;
240     } else {
241     descr[3] = d; descr[2] = d >> 8;
242     descr[1] = d >> 16; descr[0] = d >> 24;
243     }
244     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
245     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
246     }
247     }
248    
249    
250     /*
251 dpavlin 18 * arm_translation_table_set_l1_b():
252     */
253     void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
254     uint32_t paddr)
255     {
256     unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
257    
258     for (i=0; i<16; i++)
259     for (j=vhigh; j<=vhigh; j++) {
260     unsigned char descr[4];
261     uint32_t addr = cpu->cd.arm.ttb +
262     (((j << 24) + (i << 20)) >> 18);
263     uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
264    
265     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
266     descr[0] = d; descr[1] = d >> 8;
267     descr[2] = d >> 16; descr[3] = d >> 24;
268     } else {
269     descr[3] = d; descr[2] = d >> 8;
270     descr[1] = d >> 16; descr[0] = d >> 24;
271     }
272     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
273     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
274     }
275     }
276    
277    
278     /*
279 dpavlin 14 * arm_cpu_dumpinfo():
280     */
281     void arm_cpu_dumpinfo(struct cpu *cpu)
282     {
283     struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
284    
285     debug(" (I+D = %i+%i KB)\n",
286     (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
287     }
288    
289    
290     /*
291     * arm_cpu_list_available_types():
292     *
293     * Print a list of available ARM CPU types.
294     */
295     void arm_cpu_list_available_types(void)
296     {
297     int i, j;
298     struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
299    
300     i = 0;
301     while (tdefs[i].name != NULL) {
302     debug("%s", tdefs[i].name);
303     for (j=13 - strlen(tdefs[i].name); j>0; j--)
304     debug(" ");
305     i++;
306     if ((i % 5) == 0 || tdefs[i].name == NULL)
307     debug("\n");
308     }
309     }
310    
311    
312     /*
313     * arm_cpu_register_dump():
314     *
315     * Dump cpu registers in a relatively readable format.
316     *
317     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
318     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
319     */
320     void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
321     {
322     char *symbol;
323     uint64_t offset;
324     int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
325     int i, x = cpu->cpu_id;
326    
327 dpavlin 20 cpu->cd.arm.cpsr &= 0x0fffffff;
328     cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
329    
330 dpavlin 14 if (gprs) {
331     symbol = get_symbol_name(&cpu->machine->symbol_context,
332 dpavlin 20 cpu->pc, &offset);
333 dpavlin 14 debug("cpu%i: cpsr = ", x);
334     debug("%s%s%s%s%s%s",
335     (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
336     (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
337     (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
338     (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
339     (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
340     (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
341     if (mode < ARM_MODE_USR32)
342 dpavlin 20 debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
343 dpavlin 14 else
344 dpavlin 20 debug(" pc = 0x%08x", (int)cpu->pc);
345 dpavlin 14
346     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
347    
348     for (i=0; i<N_ARM_REGS; i++) {
349     if ((i % 4) == 0)
350     debug("cpu%i:", x);
351     if (i != ARM_PC)
352     debug(" %s = 0x%08x", arm_regname[i],
353     (int)cpu->cd.arm.r[i]);
354     if ((i % 4) == 3)
355     debug("\n");
356     }
357     }
358    
359     if (coprocs & 1) {
360     int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
361     debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
362     switch (m) {
363     case ARM_MODE_USR32:
364     debug("USR32)\n"); break;
365     case ARM_MODE_SYS32:
366     debug("SYS32)\n"); break;
367     case ARM_MODE_FIQ32:
368     debug("FIQ32)\n"); break;
369     case ARM_MODE_IRQ32:
370     debug("IRQ32)\n"); break;
371     case ARM_MODE_SVC32:
372     debug("SVC32)\n"); break;
373     case ARM_MODE_ABT32:
374     debug("ABT32)\n"); break;
375     case ARM_MODE_UND32:
376     debug("UND32)\n"); break;
377     default:debug("unimplemented)\n");
378     }
379    
380     if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
381 dpavlin 22 debug("cpu%i: usr r8-14:", x);
382 dpavlin 14 for (i=0; i<7; i++)
383     debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
384     debug("\n");
385     }
386    
387     if (m != ARM_MODE_FIQ32) {
388 dpavlin 22 debug("cpu%i: fiq r8-14:", x);
389 dpavlin 14 for (i=0; i<7; i++)
390     debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
391     debug("\n");
392     }
393    
394     if (m != ARM_MODE_IRQ32) {
395 dpavlin 22 debug("cpu%i: irq r13-14:", x);
396 dpavlin 14 for (i=0; i<2; i++)
397     debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
398     debug("\n");
399     }
400    
401     if (m != ARM_MODE_SVC32) {
402 dpavlin 22 debug("cpu%i: svc r13-14:", x);
403 dpavlin 14 for (i=0; i<2; i++)
404     debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
405     debug("\n");
406     }
407    
408     if (m != ARM_MODE_ABT32) {
409 dpavlin 22 debug("cpu%i: abt r13-14:", x);
410 dpavlin 14 for (i=0; i<2; i++)
411     debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
412     debug("\n");
413     }
414    
415     if (m != ARM_MODE_UND32) {
416 dpavlin 22 debug("cpu%i: und r13-14:", x);
417 dpavlin 14 for (i=0; i<2; i++)
418     debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
419     debug("\n");
420     }
421     }
422    
423     if (coprocs & 2) {
424     debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
425     debug("cpu%i: MMU: %s\n", x,
426     cpu->cd.arm.control &
427     ARM_CONTROL_MMU? "enabled" : "disabled");
428     debug("cpu%i: alignment checks: %s\n", x,
429     cpu->cd.arm.control &
430     ARM_CONTROL_ALIGN? "enabled" : "disabled");
431     debug("cpu%i: [data] cache: %s\n", x,
432     cpu->cd.arm.control &
433     ARM_CONTROL_CACHE? "enabled" : "disabled");
434     debug("cpu%i: instruction cache: %s\n", x,
435     cpu->cd.arm.control &
436     ARM_CONTROL_ICACHE? "enabled" : "disabled");
437     debug("cpu%i: write buffer: %s\n", x,
438     cpu->cd.arm.control &
439     ARM_CONTROL_WBUFFER? "enabled" : "disabled");
440     debug("cpu%i: prog32: %s\n", x,
441     cpu->cd.arm.control &
442     ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
443     debug("cpu%i: data32: %s\n", x,
444     cpu->cd.arm.control &
445     ARM_CONTROL_DATA32? "yes" : "no (using data26)");
446     debug("cpu%i: endianness: %s\n", x,
447     cpu->cd.arm.control &
448     ARM_CONTROL_BIG? "big endian" : "little endian");
449     debug("cpu%i: high vectors: %s\n", x,
450     cpu->cd.arm.control &
451     ARM_CONTROL_V? "yes (0xffff0000)" : "no");
452    
453 dpavlin 22 /* TODO: auxctrl on which CPU types? */
454     if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE) {
455     debug("cpu%i: auxctrl = 0x%08x\n", x,
456     cpu->cd.arm.auxctrl);
457     debug("cpu%i: minidata cache attr = 0x%x\n", x,
458     (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)
459     >> ARM_AUXCTRL_MD_SHIFT);
460     debug("cpu%i: page table memory attr: %i\n", x,
461     (cpu->cd.arm.auxctrl & ARM_AUXCTRL_P)? 1 : 0);
462     debug("cpu%i: write buffer coalescing: %s\n", x,
463     (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)?
464     "disabled" : "enabled");
465     }
466    
467 dpavlin 14 debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
468     cpu->cd.arm.ttb, cpu->cd.arm.dacr);
469     debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
470     cpu->cd.arm.fsr, cpu->cd.arm.far);
471     }
472     }
473    
474    
475     /*
476     * arm_save_register_bank():
477     */
478     void arm_save_register_bank(struct cpu *cpu)
479     {
480     /* Save away current 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.default_r8_r14,
485     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
486     break;
487     case ARM_MODE_FIQ32:
488     memcpy(cpu->cd.arm.fiq_r8_r14,
489     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
490     break;
491     case ARM_MODE_IRQ32:
492 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
493     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
494 dpavlin 14 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
495     cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
496     break;
497     case ARM_MODE_SVC32:
498 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
499     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
500 dpavlin 14 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
501     cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
502     break;
503     case ARM_MODE_ABT32:
504 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
505     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
506 dpavlin 14 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
507     cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
508     break;
509     case ARM_MODE_UND32:
510 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
511     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
512 dpavlin 14 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
513     cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
514     break;
515     default:fatal("arm_save_register_bank: unimplemented mode %i\n",
516     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
517     exit(1);
518     }
519     }
520    
521    
522     /*
523     * arm_load_register_bank():
524     */
525     void arm_load_register_bank(struct cpu *cpu)
526     {
527     /* Load new registers: */
528     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
529     case ARM_MODE_USR32:
530     case ARM_MODE_SYS32:
531     memcpy(&cpu->cd.arm.r[8],
532     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
533     break;
534     case ARM_MODE_FIQ32:
535     memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
536     sizeof(uint32_t) * 7);
537     break;
538     case ARM_MODE_IRQ32:
539 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
540     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
541 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
542     cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
543     break;
544     case ARM_MODE_SVC32:
545 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
546     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
547 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
548     cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
549     break;
550     case ARM_MODE_ABT32:
551 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
552     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
553 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
554     cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
555     break;
556     case ARM_MODE_UND32:
557 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
558     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
559 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
560     cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
561     break;
562     default:fatal("arm_load_register_bank: unimplemented mode %i\n",
563     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
564     exit(1);
565     }
566     }
567    
568    
569     /*
570     * arm_exception():
571     */
572     void arm_exception(struct cpu *cpu, int exception_nr)
573     {
574     int oldmode, newmode;
575     uint32_t retaddr;
576    
577     if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
578     fatal("arm_exception(): exception_nr = %i\n", exception_nr);
579     exit(1);
580     }
581    
582     retaddr = cpu->pc;
583    
584 dpavlin 18 if (!quiet_mode) {
585     debug("[ arm_exception(): ");
586     switch (exception_nr) {
587     case ARM_EXCEPTION_RESET:
588     fatal("RESET: TODO");
589     break;
590     case ARM_EXCEPTION_UND:
591     debug("UNDEFINED");
592     break;
593     case ARM_EXCEPTION_SWI:
594     debug("SWI");
595     break;
596     case ARM_EXCEPTION_PREF_ABT:
597     debug("PREFETCH ABORT");
598     break;
599     case ARM_EXCEPTION_IRQ:
600     debug("IRQ");
601     break;
602     case ARM_EXCEPTION_FIQ:
603     debug("FIQ");
604     break;
605     case ARM_EXCEPTION_DATA_ABT:
606     debug("DATA ABORT, far=0x%08x fsr=0x%02x",
607     cpu->cd.arm.far, cpu->cd.arm.fsr);
608     break;
609     }
610     debug(" ]\n");
611     }
612 dpavlin 14
613     switch (exception_nr) {
614     case ARM_EXCEPTION_RESET:
615     cpu->running = 0;
616 dpavlin 18 fatal("ARM RESET: TODO");
617 dpavlin 14 exit(1);
618 dpavlin 18 case ARM_EXCEPTION_DATA_ABT:
619 dpavlin 14 retaddr += 4;
620     break;
621     }
622    
623 dpavlin 18 retaddr += 4;
624 dpavlin 14
625     arm_save_register_bank(cpu);
626    
627 dpavlin 20 cpu->cd.arm.cpsr &= 0x0fffffff;
628     cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
629    
630 dpavlin 14 switch (arm_exception_to_mode[exception_nr]) {
631     case ARM_MODE_SVC32:
632     cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
633     case ARM_MODE_ABT32:
634     cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
635     case ARM_MODE_UND32:
636     cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
637     case ARM_MODE_IRQ32:
638     cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
639     case ARM_MODE_FIQ32:
640     cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
641     default:fatal("arm_exception(): unimplemented exception nr\n");
642     exit(1);
643     }
644    
645     /*
646     * Disable Thumb mode (because exception handlers always execute
647     * in ARM mode), set the exception mode, and disable interrupts:
648     */
649     cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
650    
651     oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
652    
653     cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
654     cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
655    
656 dpavlin 20 /*
657     * Usually, an exception should change modes (so that saved status
658     * bits don't get lost). However, Linux on ARM seems to use floating
659     * point instructions in the kernel (!), and it emulates those using
660     * its own fp emulation code. This leads to a situation where we
661     * sometimes change from SVC32 to SVC32.
662     */
663 dpavlin 14 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
664 dpavlin 20 if (oldmode == newmode && oldmode != ARM_MODE_SVC32) {
665     fatal("[ WARNING! Exception caused no mode change? "
666     "mode 0x%02x (pc=0x%x) ]\n", newmode, (int)cpu->pc);
667     /* exit(1); */
668 dpavlin 14 }
669 dpavlin 22
670 dpavlin 14 cpu->cd.arm.cpsr |= ARM_FLAG_I;
671     if (exception_nr == ARM_EXCEPTION_RESET ||
672     exception_nr == ARM_EXCEPTION_FIQ)
673     cpu->cd.arm.cpsr |= ARM_FLAG_F;
674    
675     /* Load the new register bank, if we switched: */
676     arm_load_register_bank(cpu);
677    
678 dpavlin 20 /*
679     * Set the return address and new PC.
680     *
681     * NOTE: r[ARM_PC] is also set; see cpu_arm_instr_loadstore.c for
682     * details. (If an exception occurs during a load into the pc
683     * register, the code in that file assumes that the r[ARM_PC]
684     * was changed to the address of the exception handler.)
685     */
686 dpavlin 14 cpu->cd.arm.r[ARM_LR] = retaddr;
687     cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
688     ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
689 dpavlin 18 quick_pc_to_pointers(cpu);
690 dpavlin 14 }
691    
692    
693     /*
694 dpavlin 24 * arm_cpu_tlbdump():
695     *
696     * Called from the debugger to dump the TLB in a readable format.
697     * x is the cpu number to dump, or -1 to dump all CPUs.
698     *
699     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
700     * just dumped.
701     */
702     void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
703     {
704     }
705    
706    
707     static void add_response_word(struct cpu *cpu, char *r, uint32_t value,
708     size_t maxlen)
709     {
710     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
711     value = ((value & 0xff) << 24) +
712     ((value & 0xff00) << 8) +
713     ((value & 0xff0000) >> 8) +
714     ((value & 0xff000000) >> 24);
715     }
716     snprintf(r + strlen(r), maxlen - strlen(r), "%08"PRIx32, value);
717     }
718    
719    
720     /*
721     * arm_cpu_gdb_stub():
722     *
723     * Execute a "remote GDB" command. Returns a newly allocated response string
724     * on success, NULL on failure.
725     */
726     char *arm_cpu_gdb_stub(struct cpu *cpu, char *cmd)
727     {
728     if (strcmp(cmd, "g") == 0) {
729     /* 15 gprs, pc, 8 fprs, fps, cpsr. */
730     int i;
731     char *r;
732     size_t len = 1 + 18 * sizeof(uint32_t);
733     r = malloc(len);
734     if (r == NULL) {
735     fprintf(stderr, "out of memory\n");
736     exit(1);
737     }
738     r[0] = '\0';
739     for (i=0; i<15; i++)
740     add_response_word(cpu, r, cpu->cd.arm.r[i], len);
741     add_response_word(cpu, r, cpu->pc, len);
742     /* TODO: fprs: */
743     for (i=0; i<8; i++)
744     add_response_word(cpu, r, 0, len);
745     /* TODO: fps */
746     add_response_word(cpu, r, 0, len);
747     add_response_word(cpu, r, cpu->cd.arm.cpsr, len);
748     return r;
749     }
750    
751     if (cmd[0] == 'p') {
752     int regnr = strtol(cmd + 1, NULL, 16);
753     size_t len = 2 * sizeof(uint32_t) + 1;
754     char *r = malloc(len);
755     r[0] = '\0';
756     if (regnr == ARM_PC) {
757     add_response_word(cpu, r, cpu->pc, len);
758     } else if (regnr >= 0 && regnr < ARM_PC) {
759     add_response_word(cpu, r, cpu->cd.arm.r[regnr], len);
760     } else if (regnr >= 0x10 && regnr <= 0x17) {
761     /* TODO: fprs */
762     add_response_word(cpu, r, 0, len);
763     add_response_word(cpu, r, 0, len);
764     add_response_word(cpu, r, 0, len);
765     } else if (regnr == 0x18) {
766     /* TODO: fps */
767     add_response_word(cpu, r, 0, len);
768     } else if (regnr == 0x19) {
769     add_response_word(cpu, r, cpu->cd.arm.cpsr, len);
770     }
771     return r;
772     }
773    
774     fatal("arm_cpu_gdb_stub(): TODO\n");
775     return NULL;
776     }
777    
778    
779     /*
780 dpavlin 14 * arm_cpu_interrupt():
781     *
782     * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
783     * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
784     *
785     * TODO: don't hardcode to footbridge!
786     */
787     int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
788     {
789 dpavlin 20 /* fatal("arm_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
790 dpavlin 14 if (irq_nr <= 64) {
791     if (cpu->machine->md_interrupt != NULL)
792     cpu->machine->md_interrupt(cpu->machine,
793     cpu, irq_nr, 1);
794     else
795 dpavlin 22 fatal("arm_cpu_interrupt(): irq_nr=%i md_interrupt =="
796     " NULL\n", (int)irq_nr);
797 dpavlin 14 } else {
798     /* Assert ARM IRQs: */
799     cpu->cd.arm.irq_asserted = 1;
800     }
801    
802     return 1;
803     }
804    
805    
806     /*
807     * arm_cpu_interrupt_ack():
808     */
809     int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
810     {
811     if (irq_nr <= 64) {
812     if (cpu->machine->md_interrupt != NULL)
813     cpu->machine->md_interrupt(cpu->machine,
814     cpu, irq_nr, 0);
815     } else {
816     /* De-assert ARM IRQs: */
817     cpu->cd.arm.irq_asserted = 0;
818     }
819    
820     return 1;
821     }
822    
823    
824     /*
825     * arm_cpu_disassemble_instr():
826     *
827     * Convert an instruction word into human readable format, for instruction
828     * tracing.
829     *
830     * If running is 1, cpu->pc should be the address of the instruction.
831     *
832     * If running is 0, things that depend on the runtime environment (eg.
833     * register contents) will not be shown, and addr will be used instead of
834     * cpu->pc for relative addresses.
835     */
836     int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
837 dpavlin 24 int running, uint64_t dumpaddr)
838 dpavlin 14 {
839     uint32_t iw, tmp;
840     int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
841     int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
842     char *symbol, *condition;
843     uint64_t offset;
844    
845     if (running)
846     dumpaddr = cpu->pc;
847    
848     symbol = get_symbol_name(&cpu->machine->symbol_context,
849     dumpaddr, &offset);
850     if (symbol != NULL && offset == 0)
851     debug("<%s>\n", symbol);
852    
853     if (cpu->machine->ncpus > 1 && running)
854     debug("cpu%i:\t", cpu->cpu_id);
855    
856     debug("%08x: ", (int)dumpaddr);
857    
858     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
859     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
860     else
861     iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
862     debug("%08x\t", (int)iw);
863    
864     condition = arm_condition_string[iw >> 28];
865     main_opcode = (iw >> 24) & 15;
866     secondary_opcode = (iw >> 21) & 15;
867     u_bit = (iw >> 23) & 1;
868     b_bit = (iw >> 22) & 1;
869     w_bit = (iw >> 21) & 1;
870     s_bit = l_bit = (iw >> 20) & 1;
871     r16 = (iw >> 16) & 15;
872     r12 = (iw >> 12) & 15;
873     r8 = (iw >> 8) & 15;
874    
875     switch (main_opcode) {
876     case 0x0:
877     case 0x1:
878     case 0x2:
879     case 0x3:
880     /*
881     * Special cases first:
882     */
883    
884     /*
885     * Multiplication:
886     * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
887     */
888     if ((iw & 0x0fc000f0) == 0x00000090) {
889     int a_bit = (iw >> 21) & 1;
890     debug("%s%s%s\t", a_bit? "mla" : "mul",
891     condition, s_bit? "s" : "");
892     debug("%s,", arm_regname[r16]);
893     debug("%s,", arm_regname[iw & 15]);
894     debug("%s", arm_regname[r8]);
895     if (a_bit)
896     debug(",%s", arm_regname[r12]);
897     debug("\n");
898     break;
899     }
900    
901     /*
902     * Long multiplication:
903     * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
904     */
905     if ((iw & 0x0f8000f0) == 0x00800090) {
906     int u_bit = (iw >> 22) & 1;
907     int a_bit = (iw >> 21) & 1;
908     debug("%s%sl%s%s\t", u_bit? "s" : "u",
909     a_bit? "mla" : "mul", condition, s_bit? "s" : "");
910 dpavlin 20 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
911     debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
912 dpavlin 14 break;
913     }
914    
915     /*
916 dpavlin 20 * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
917     * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
918     * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
919     * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
920     */
921     if ((iw & 0x0f900ff0) == 0x01000050) {
922     debug("q%s%s%s\t", iw & 0x400000? "d" : "",
923     iw & 0x200000? "sub" : "add", condition);
924     debug("%s,%s,%s\n", arm_regname[r12],
925     arm_regname[iw&15], arm_regname[r16]);
926     break;
927     }
928    
929     /*
930 dpavlin 14 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
931     */
932     if ((iw & 0x0ff000d0) == 0x01200010) {
933     int l_bit = iw & 0x20;
934     debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
935     arm_regname[iw & 15]);
936     break;
937     }
938    
939     /*
940     * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
941     * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
942     * xxxx0001 0s001111 dddd0000 00000000 MRS
943     */
944     if ((iw & 0x0fb0fff0) == 0x0120f000 ||
945     (iw & 0x0fb0f000) == 0x0320f000) {
946     int a = (iw >> 16) & 15;
947     debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
948     debug("PSR_");
949     switch (a) {
950     case 1: debug("ctl"); break;
951     case 8: debug("flg"); break;
952     case 9: debug("all"); break;
953     default:debug(" UNIMPLEMENTED (a=%i)", a);
954     }
955     if (iw & 0x02000000) {
956     int r = (iw >> 7) & 30;
957     uint32_t b = iw & 0xff;
958     while (r-- > 0)
959     b = (b >> 1) | ((b & 1) << 31);
960     debug(",#0x%x\n", b);
961     } else
962     debug(",%s\n", arm_regname[iw & 15]);
963     break;
964     }
965     if ((iw & 0x0fbf0fff) == 0x010f0000) {
966     debug("mrs%s\t", condition);
967     debug("%s,%sPSR\n", arm_regname[r12],
968     (iw&0x400000)? "S":"C");
969     break;
970     }
971    
972     /*
973     * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
974     */
975     if ((iw & 0x0fb00ff0) == 0x01000090) {
976     debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
977     debug("%s,%s,[%s]\n", arm_regname[r12],
978     arm_regname[iw & 15], arm_regname[r16]);
979     break;
980     }
981    
982     /*
983 dpavlin 20 * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
984     */
985     if ((iw & 0x0fff0ff0) == 0x016f0f10) {
986     debug("clz%s\t", condition);
987     debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
988     break;
989     }
990    
991     /*
992     * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
993     * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
994     * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
995     * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
996     * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
997     */
998     if ((iw & 0x0ff00090) == 0x01000080) {
999     debug("smla%s%s%s\t",
1000     iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1001     condition);
1002     debug("%s,%s,%s,%s\n", arm_regname[r16],
1003     arm_regname[iw&15], arm_regname[r8],
1004     arm_regname[r12]);
1005     break;
1006     }
1007     if ((iw & 0x0ff00090) == 0x01400080) {
1008     debug("smlal%s%s%s\t",
1009     iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1010     condition);
1011     debug("%s,%s,%s,%s\n", arm_regname[r12],
1012     arm_regname[r16], arm_regname[iw&15],
1013     arm_regname[r8]);
1014     break;
1015     }
1016     if ((iw & 0x0ff000b0) == 0x01200080) {
1017     debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
1018     condition);
1019     debug("%s,%s,%s,%s\n", arm_regname[r16],
1020     arm_regname[iw&15], arm_regname[r8],
1021     arm_regname[r12]);
1022     break;
1023     }
1024     if ((iw & 0x0ff0f090) == 0x01600080) {
1025     debug("smul%s%s%s\t",
1026     iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1027     condition);
1028     debug("%s,%s,%s\n", arm_regname[r16],
1029     arm_regname[iw&15], arm_regname[r8]);
1030     break;
1031     }
1032     if ((iw & 0x0ff0f0b0) == 0x012000a0) {
1033     debug("smulw%s%s\t", iw & 0x40? "t" : "b",
1034     condition);
1035     debug("%s,%s,%s\n", arm_regname[r16],
1036     arm_regname[iw&15], arm_regname[r8]);
1037     break;
1038     }
1039    
1040     /*
1041 dpavlin 14 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
1042     */
1043     if ((iw & 0x0e000090) == 0x00000090) {
1044 dpavlin 18 char *op = "st";
1045 dpavlin 14 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
1046     int regform = !(iw & 0x00400000);
1047     p_bit = main_opcode & 1;
1048     /*
1049     * TODO: detect some illegal variants:
1050     * signed store, or unsigned byte load/store
1051     */
1052     if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
1053     debug("TODO: r12 odd, not load/store\n");
1054     break;
1055     }
1056     /* Semi-generic case: */
1057 dpavlin 18 if (iw & 0x00100000)
1058     op = "ld";
1059     if (!l_bit && (iw & 0xd0) == 0xd0)
1060     op = iw & 0x20? "st" : "ld";
1061     debug("%sr%s", op, condition);
1062 dpavlin 14 if (!l_bit && (iw & 0xd0) == 0xd0) {
1063     debug("d"); /* Double-register */
1064     } else {
1065     if (iw & 0x40)
1066     debug("s"); /* signed */
1067     if (iw & 0x20)
1068     debug("h"); /* half-word */
1069     else
1070     debug("b"); /* byte */
1071     }
1072     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1073     if (p_bit) {
1074     /* Pre-index: */
1075     if (regform)
1076     debug(",%s%s", u_bit? "" : "-",
1077     arm_regname[iw & 15]);
1078     else {
1079     if (imm != 0)
1080     debug(",#%s%i", u_bit? "" : "-",
1081     imm);
1082     }
1083     debug("]%s\n", w_bit? "!" : "");
1084     } else {
1085     /* Post-index: */
1086     debug("],");
1087     if (regform)
1088     debug("%s%s\n", u_bit? "" : "-",
1089     arm_regname[iw & 15]);
1090     else
1091     debug("#%s%i\n", u_bit? "" : "-", imm);
1092     }
1093     break;
1094     }
1095    
1096     /* Other special cases: */
1097     if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
1098     debug("UNIMPLEMENTED reg (c!=0), t odd\n");
1099     break;
1100     }
1101    
1102     /*
1103     * Generic Data Processing Instructions:
1104     *
1105     * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
1106     * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
1107     */
1108    
1109     debug("%s%s%s\t", arm_dpiname[secondary_opcode],
1110     condition, s_bit? "s" : "");
1111     if (arm_dpi_uses_d[secondary_opcode])
1112     debug("%s,", arm_regname[r12]);
1113     if (arm_dpi_uses_n[secondary_opcode])
1114     debug("%s,", arm_regname[r16]);
1115    
1116     if (main_opcode & 2) {
1117     /* Immediate form: */
1118     int r = (iw >> 7) & 30;
1119     uint32_t b = iw & 0xff;
1120     while (r-- > 0)
1121     b = (b >> 1) | ((b & 1) << 31);
1122     if (b < 15)
1123     debug("#%i", b);
1124     else
1125     debug("#0x%x", b);
1126     } else {
1127     /* Register form: */
1128     int t = (iw >> 4) & 7;
1129     int c = (iw >> 7) & 31;
1130     debug("%s", arm_regname[iw & 15]);
1131     switch (t) {
1132     case 0: if (c != 0)
1133     debug(", lsl #%i", c);
1134     break;
1135     case 1: debug(", lsl %s", arm_regname[c >> 1]);
1136     break;
1137     case 2: debug(", lsr #%i", c? c : 32);
1138     break;
1139     case 3: debug(", lsr %s", arm_regname[c >> 1]);
1140     break;
1141     case 4: debug(", asr #%i", c? c : 32);
1142     break;
1143     case 5: debug(", asr %s", arm_regname[c >> 1]);
1144     break;
1145     case 6: if (c != 0)
1146     debug(", ror #%i", c);
1147     else
1148     debug(", rrx");
1149     break;
1150     case 7: debug(", ror %s", arm_regname[c >> 1]);
1151     break;
1152     }
1153    
1154     /* mov pc,reg: */
1155     if (running && t == 0 && c == 0 && secondary_opcode
1156     == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
1157     symbol = get_symbol_name(&cpu->machine->
1158     symbol_context, cpu->cd.arm.r[iw & 15],
1159     &offset);
1160     if (symbol != NULL)
1161     debug(" \t<%s>", symbol);
1162     }
1163     }
1164     debug("\n");
1165     break;
1166     case 0x4: /* Single Data Transfer */
1167     case 0x5:
1168     case 0x6:
1169     case 0x7:
1170     /* Special case first: */
1171     if ((iw & 0xfc70f000) == 0xf450f000) {
1172     /* Preload: */
1173     debug("pld\t[%s]\n", arm_regname[r16]);
1174     break;
1175     }
1176    
1177     /*
1178     * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1179     * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1180     */
1181     p_bit = main_opcode & 1;
1182     if (main_opcode >= 6 && iw & 0x10) {
1183     debug("TODO: single data transf. but 0x10\n");
1184     break;
1185     }
1186     debug("%s%s%s", l_bit? "ldr" : "str",
1187     condition, b_bit? "b" : "");
1188     if (!p_bit && w_bit)
1189     debug("t");
1190     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1191     if ((iw & 0x0e000000) == 0x04000000) {
1192     /* Immediate form: */
1193     uint32_t imm = iw & 0xfff;
1194     if (!p_bit)
1195     debug("]");
1196     if (imm != 0)
1197     debug(",#%s%i", u_bit? "" : "-", imm);
1198     if (p_bit)
1199     debug("]");
1200     } else if ((iw & 0x0e000010) == 0x06000000) {
1201     /* Register form: */
1202     if (!p_bit)
1203     debug("]");
1204     if ((iw & 0xfff) != 0)
1205     debug(",%s%s", u_bit? "" : "-",
1206     arm_regname[iw & 15]);
1207     if ((iw & 0xff0) != 0x000) {
1208     int c = (iw >> 7) & 31;
1209     int t = (iw >> 4) & 7;
1210     switch (t) {
1211     case 0: if (c != 0)
1212     debug(", lsl #%i", c);
1213     break;
1214     case 2: debug(", lsr #%i", c? c : 32);
1215     break;
1216     case 4: debug(", asr #%i", c? c : 32);
1217     break;
1218     case 6: if (c != 0)
1219     debug(", ror #%i", c);
1220     else
1221     debug(", rrx");
1222     break;
1223     }
1224     }
1225     if (p_bit)
1226     debug("]");
1227     } else {
1228     debug("UNKNOWN\n");
1229     break;
1230     }
1231     debug("%s", (p_bit && w_bit)? "!" : "");
1232     if ((iw & 0x0f000000) == 0x05000000 &&
1233     (r16 == ARM_PC || running)) {
1234     unsigned char tmpw[4];
1235     uint32_t imm = iw & 0xfff;
1236     uint32_t addr = (u_bit? imm : -imm);
1237     if (r16 == ARM_PC)
1238     addr += dumpaddr + 8;
1239     else
1240     addr += cpu->cd.arm.r[r16];
1241     symbol = get_symbol_name(&cpu->machine->symbol_context,
1242     addr, &offset);
1243     if (symbol != NULL)
1244     debug(" \t<%s", symbol);
1245     else
1246     debug(" \t<0x%08x", addr);
1247     if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1248     b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1249     || (!l_bit && running)) {
1250     if (l_bit) {
1251     if (cpu->byte_order ==
1252     EMUL_LITTLE_ENDIAN)
1253     addr = tmpw[0] +(tmpw[1] << 8) +
1254     (tmpw[2]<<16)+(tmpw[3]<<24);
1255     else
1256     addr = tmpw[3] + (tmpw[2]<<8) +
1257     (tmpw[1]<<16)+(tmpw[0]<<24);
1258     } else {
1259     tmpw[0] = addr = cpu->cd.arm.r[r12];
1260     if (r12 == ARM_PC)
1261 dpavlin 20 addr = cpu->pc + 8;
1262 dpavlin 14 }
1263     debug(": ");
1264     if (b_bit)
1265     debug("%i", tmpw[0]);
1266     else {
1267     symbol = get_symbol_name(&cpu->machine->
1268     symbol_context, addr, &offset);
1269     if (symbol != NULL)
1270     debug("%s", symbol);
1271     else if ((int32_t)addr > -256 &&
1272     (int32_t)addr < 256)
1273     debug("%i", addr);
1274     else
1275     debug("0x%x", addr);
1276     }
1277     }
1278     debug(">");
1279     }
1280     debug("\n");
1281     break;
1282     case 0x8: /* Block Data Transfer */
1283     case 0x9:
1284     /* xxxx100P USWLnnnn llllllll llllllll */
1285     p_bit = main_opcode & 1;
1286     s_bit = b_bit;
1287     debug("%s%s", l_bit? "ldm" : "stm", condition);
1288     switch (u_bit * 2 + p_bit) {
1289     case 0: debug("da"); break;
1290     case 1: debug("db"); break;
1291     case 2: debug("ia"); break;
1292     case 3: debug("ib"); break;
1293     }
1294     debug("\t%s", arm_regname[r16]);
1295     if (w_bit)
1296     debug("!");
1297     debug(",{");
1298     n = 0;
1299     for (i=0; i<16; i++)
1300     if ((iw >> i) & 1) {
1301     debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1302     n++;
1303     }
1304     debug("}");
1305     if (s_bit)
1306     debug("^");
1307     debug("\n");
1308     break;
1309     case 0xa: /* B: branch */
1310     case 0xb: /* BL: branch and link */
1311     debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1312     tmp = (iw & 0x00ffffff) << 2;
1313     if (tmp & 0x02000000)
1314     tmp |= 0xfc000000;
1315     tmp = (int32_t)(dumpaddr + tmp + 8);
1316     debug("0x%x", (int)tmp);
1317     symbol = get_symbol_name(&cpu->machine->symbol_context,
1318     tmp, &offset);
1319     if (symbol != NULL)
1320     debug(" \t<%s>", symbol);
1321     debug("\n");
1322     break;
1323     case 0xc: /* Coprocessor */
1324     case 0xd: /* LDC/STC */
1325 dpavlin 20 /*
1326     * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
1327     * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
1328     */
1329 dpavlin 22 if ((iw & 0x0fe00fff) == 0x0c400000) {
1330     debug("%s%s\t", iw & 0x100000? "mra" : "mar",
1331     condition);
1332     if (iw & 0x100000)
1333     debug("%s,%s,acc0\n",
1334     arm_regname[r12], arm_regname[r16]);
1335     else
1336     debug("acc0,%s,%s\n",
1337     arm_regname[r12], arm_regname[r16]);
1338     break;
1339     }
1340 dpavlin 20 if ((iw & 0x0fe00000) == 0x0c400000) {
1341     debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
1342     condition);
1343     debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
1344     arm_regname[r12], arm_regname[r16], iw & 15);
1345     break;
1346     }
1347    
1348 dpavlin 14 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1349     debug("TODO: coprocessor LDC/STC\n");
1350     break;
1351     case 0xe: /* CDP (Coprocessor Op) */
1352     /* or MRC/MCR!
1353     * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1354     * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1355     */
1356 dpavlin 22 if ((iw & 0x0ff00ff0) == 0x0e200010) {
1357     /* Special case: mia* DSP instructions */
1358     switch ((iw >> 16) & 0xf) {
1359     case 0: debug("mia"); break;
1360     case 8: debug("miaph"); break;
1361     case 12: debug("miaBB"); break;
1362     case 13: debug("miaTB"); break;
1363     case 14: debug("miaBT"); break;
1364     case 15: debug("miaTT"); break;
1365     default: debug("UNKNOWN mia vector instruction?");
1366     }
1367     debug("%s\t", condition);
1368     debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
1369     arm_regname[iw & 15], arm_regname[r12]);
1370     break;
1371     }
1372 dpavlin 14 if (iw & 0x10) {
1373     debug("%s%s\t",
1374     (iw & 0x00100000)? "mrc" : "mcr", condition);
1375     debug("%i,%i,r%i,cr%i,cr%i,%i",
1376     (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1377     (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1378     (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1379     } else {
1380     debug("cdp%s\t", condition);
1381     debug("%i,%i,cr%i,cr%i,cr%i",
1382     (int)((iw >> 8) & 15),
1383     (int)((iw >>20) & 15),
1384     (int)((iw >>12) & 15),
1385     (int)((iw >>16) & 15),
1386     (int)((iw >> 0) & 15));
1387     if ((iw >> 5) & 7)
1388     debug(",0x%x", (int)((iw >> 5) & 7));
1389     }
1390     debug("\n");
1391     break;
1392     case 0xf: /* SWI */
1393     debug("swi%s\t", condition);
1394     debug("0x%x\n", (int)(iw & 0x00ffffff));
1395     break;
1396     default:debug("UNIMPLEMENTED\n");
1397     }
1398    
1399     return sizeof(uint32_t);
1400     }
1401    
1402    
1403     /*****************************************************************************/
1404    
1405    
1406     /*
1407     * arm_mcr_mrc():
1408     *
1409     * Coprocessor register move.
1410     *
1411     * The program counter should be synched before calling this function (to
1412     * make debug output with the correct PC value possible).
1413     */
1414     void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1415     {
1416     int opcode1 = (iword >> 21) & 7;
1417     int l_bit = (iword >> 20) & 1;
1418     int crn = (iword >> 16) & 15;
1419     int rd = (iword >> 12) & 15;
1420     int cp_num = (iword >> 8) & 15;
1421     int opcode2 = (iword >> 5) & 7;
1422     int crm = iword & 15;
1423    
1424     if (cpu->cd.arm.coproc[cp_num] != NULL)
1425     cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1426     crn, crm, rd);
1427     else {
1428 dpavlin 20 fatal("[ arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1429     "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
1430     arm_exception(cpu, ARM_EXCEPTION_UND);
1431     /* exit(1); */
1432 dpavlin 14 }
1433     }
1434    
1435    
1436     /*
1437     * arm_cdp():
1438     *
1439     * Coprocessor operations.
1440     *
1441     * The program counter should be synched before calling this function (to
1442     * make debug output with the correct PC value possible).
1443     */
1444     void arm_cdp(struct cpu *cpu, uint32_t iword)
1445     {
1446 dpavlin 20 fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
1447     arm_exception(cpu, ARM_EXCEPTION_UND);
1448     /* exit(1); */
1449 dpavlin 14 }
1450    
1451    
1452     /*****************************************************************************/
1453    
1454    
1455     #include "tmp_arm_tail.c"
1456    

  ViewVC Help
Powered by ViewVC 1.1.26