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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 51787 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 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.64 2006/09/21 11:53:26 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "machine.h"
41 #include "memory.h"
42 #include "misc.h"
43 #include "of.h"
44 #include "opcodes_ppc.h"
45 #include "ppc_bat.h"
46 #include "ppc_pte.h"
47 #include "ppc_spr.h"
48 #include "ppc_spr_strings.h"
49 #include "settings.h"
50 #include "symbol.h"
51
52 #define DYNTRANS_DUALMODE_32
53 #include "tmp_ppc_head.c"
54
55
56 void ppc_pc_to_pointers(struct cpu *);
57 void ppc32_pc_to_pointers(struct cpu *);
58
59
60 /*
61 * ppc_cpu_new():
62 *
63 * Create a new PPC cpu object.
64 *
65 * Returns 1 on success, 0 if there was no matching PPC processor with
66 * this cpu_type_name.
67 */
68 int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
69 int cpu_id, char *cpu_type_name)
70 {
71 int any_cache = 0;
72 int i, found;
73 struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
74
75 /* Scan the cpu_type_defs list for this cpu type: */
76 i = 0;
77 found = -1;
78 while (i >= 0 && cpu_type_defs[i].name != NULL) {
79 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
80 found = i;
81 break;
82 }
83 i++;
84 }
85 if (found == -1)
86 return 0;
87
88 cpu->memory_rw = ppc_memory_rw;
89
90 cpu->cd.ppc.cpu_type = cpu_type_defs[found];
91 cpu->name = cpu->cd.ppc.cpu_type.name;
92 cpu->byte_order = EMUL_BIG_ENDIAN;
93 cpu->cd.ppc.mode = MODE_PPC; /* TODO */
94
95 /* Current operating mode: */
96 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
97 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
98
99 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
100 PPC_MSR_SF | PPC_MSR_FP; */
101
102 cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs;
103 cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW;
104 cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs;
105 cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW;
106 cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs;
107 cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW;
108 cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs;
109 cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW;
110 cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs;
111 cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW;
112 cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs;
113 cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW;
114 cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs;
115 cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW;
116
117 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
118
119 if (cpu->is_32bit) {
120 cpu->run_instr = ppc32_run_instr;
121 cpu->update_translation_table = ppc32_update_translation_table;
122 cpu->invalidate_translation_caches =
123 ppc32_invalidate_translation_caches;
124 cpu->invalidate_code_translation =
125 ppc32_invalidate_code_translation;
126 } else {
127 cpu->run_instr = ppc_run_instr;
128 cpu->update_translation_table = ppc_update_translation_table;
129 cpu->invalidate_translation_caches =
130 ppc_invalidate_translation_caches;
131 cpu->invalidate_code_translation =
132 ppc_invalidate_code_translation;
133 }
134
135 cpu->translate_v2p = ppc_translate_v2p;
136
137 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
138 if (cpu_id == 0) {
139 debug("%s", cpu->cd.ppc.cpu_type.name);
140
141 if (cpu->cd.ppc.cpu_type.icache_shift != 0)
142 any_cache = 1;
143 if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
144 any_cache = 1;
145 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
146 any_cache = 1;
147
148 if (any_cache) {
149 debug(" (I+D = %i+%i KB",
150 (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
151 (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
152 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
153 debug(", L2 = %i KB",
154 (int)(1 << (cpu->cd.ppc.cpu_type.
155 l2cache_shift-10)));
156 }
157 debug(")");
158 }
159 }
160
161 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
162
163 /* Some default stack pointer value. TODO: move this? */
164 cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
165
166 /*
167 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
168 */
169 if (cpu->machine->prom_emulation)
170 cpu->cd.ppc.of_emul_addr = 0xfff00000;
171
172 /* Add all register names to the settings: */
173 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
174 CPU_SETTINGS_ADD_REGISTER64("msr", cpu->cd.ppc.msr);
175 CPU_SETTINGS_ADD_REGISTER64("ctr", cpu->cd.ppc.spr[SPR_CTR]);
176 CPU_SETTINGS_ADD_REGISTER64("xer", cpu->cd.ppc.spr[SPR_XER]);
177 CPU_SETTINGS_ADD_REGISTER64("dec", cpu->cd.ppc.spr[SPR_DEC]);
178 CPU_SETTINGS_ADD_REGISTER64("hdec", cpu->cd.ppc.spr[SPR_HDEC]);
179 CPU_SETTINGS_ADD_REGISTER64("srr0", cpu->cd.ppc.spr[SPR_SRR0]);
180 CPU_SETTINGS_ADD_REGISTER64("srr1", cpu->cd.ppc.spr[SPR_SRR1]);
181 CPU_SETTINGS_ADD_REGISTER64("sdr1", cpu->cd.ppc.spr[SPR_SDR1]);
182 CPU_SETTINGS_ADD_REGISTER64("ibat0u", cpu->cd.ppc.spr[SPR_IBAT0U]);
183 CPU_SETTINGS_ADD_REGISTER64("ibat0l", cpu->cd.ppc.spr[SPR_IBAT0L]);
184 CPU_SETTINGS_ADD_REGISTER64("ibat1u", cpu->cd.ppc.spr[SPR_IBAT1U]);
185 CPU_SETTINGS_ADD_REGISTER64("ibat1l", cpu->cd.ppc.spr[SPR_IBAT1L]);
186 CPU_SETTINGS_ADD_REGISTER64("ibat2u", cpu->cd.ppc.spr[SPR_IBAT2U]);
187 CPU_SETTINGS_ADD_REGISTER64("ibat2l", cpu->cd.ppc.spr[SPR_IBAT2L]);
188 CPU_SETTINGS_ADD_REGISTER64("ibat3u", cpu->cd.ppc.spr[SPR_IBAT3U]);
189 CPU_SETTINGS_ADD_REGISTER64("ibat3l", cpu->cd.ppc.spr[SPR_IBAT3L]);
190 CPU_SETTINGS_ADD_REGISTER64("dbat0u", cpu->cd.ppc.spr[SPR_DBAT0U]);
191 CPU_SETTINGS_ADD_REGISTER64("dbat0l", cpu->cd.ppc.spr[SPR_DBAT0L]);
192 CPU_SETTINGS_ADD_REGISTER64("dbat1u", cpu->cd.ppc.spr[SPR_DBAT1U]);
193 CPU_SETTINGS_ADD_REGISTER64("dbat1l", cpu->cd.ppc.spr[SPR_DBAT1L]);
194 CPU_SETTINGS_ADD_REGISTER64("dbat2u", cpu->cd.ppc.spr[SPR_DBAT2U]);
195 CPU_SETTINGS_ADD_REGISTER64("dbat2l", cpu->cd.ppc.spr[SPR_DBAT2L]);
196 CPU_SETTINGS_ADD_REGISTER64("dbat3u", cpu->cd.ppc.spr[SPR_DBAT3U]);
197 CPU_SETTINGS_ADD_REGISTER64("dbat3l", cpu->cd.ppc.spr[SPR_DBAT3L]);
198 CPU_SETTINGS_ADD_REGISTER64("lr", cpu->cd.ppc.spr[SPR_LR]);
199 CPU_SETTINGS_ADD_REGISTER32("cr", cpu->cd.ppc.cr);
200 CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.ppc.fpscr);
201 /* Integer GPRs, floating point registers, and segment registers: */
202 for (i=0; i<PPC_NGPRS; i++) {
203 char tmpstr[5];
204 snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
205 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.gpr[i]);
206 }
207 for (i=0; i<PPC_NFPRS; i++) {
208 char tmpstr[5];
209 snprintf(tmpstr, sizeof(tmpstr), "f%i", i);
210 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.fpr[i]);
211 }
212 for (i=0; i<16; i++) {
213 char tmpstr[5];
214 snprintf(tmpstr, sizeof(tmpstr), "sr%i", i);
215 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.ppc.sr[i]);
216 }
217
218 return 1;
219 }
220
221
222 /*
223 * ppc_cpu_list_available_types():
224 *
225 * Print a list of available PPC CPU types.
226 */
227 void ppc_cpu_list_available_types(void)
228 {
229 int i, j;
230 struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
231
232 i = 0;
233 while (tdefs[i].name != NULL) {
234 debug("%s", tdefs[i].name);
235 for (j=10 - strlen(tdefs[i].name); j>0; j--)
236 debug(" ");
237 i++;
238 if ((i % 6) == 0 || tdefs[i].name == NULL)
239 debug("\n");
240 }
241 }
242
243
244 /*
245 * ppc_cpu_dumpinfo():
246 */
247 void ppc_cpu_dumpinfo(struct cpu *cpu)
248 {
249 struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
250
251 debug(" (%i-bit ", cpu->cd.ppc.bits);
252
253 switch (cpu->cd.ppc.mode) {
254 case MODE_PPC:
255 debug("PPC");
256 break;
257 case MODE_POWER:
258 debug("POWER");
259 break;
260 default:
261 debug("_INTERNAL ERROR_");
262 }
263
264 debug(", I+D = %i+%i KB",
265 (1 << ct->icache_shift) / 1024,
266 (1 << ct->dcache_shift) / 1024);
267
268 if (ct->l2cache_shift) {
269 int kb = (1 << ct->l2cache_shift) / 1024;
270 debug(", L2 = %i %cB",
271 kb >= 1024? kb / 1024 : kb,
272 kb >= 1024? 'M' : 'K');
273 }
274
275 debug(")\n");
276 }
277
278
279 /*
280 * reg_access_msr():
281 */
282 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
283 int check_for_interrupts)
284 {
285 uint64_t old = cpu->cd.ppc.msr;
286
287 if (valuep == NULL) {
288 fatal("reg_access_msr(): NULL\n");
289 return;
290 }
291
292 if (writeflag) {
293 cpu->cd.ppc.msr = *valuep;
294
295 /* Switching between temporary and real gpr 0..3? */
296 if ((old & PPC_MSR_TGPR) != (cpu->cd.ppc.msr & PPC_MSR_TGPR)) {
297 int i;
298 for (i=0; i<PPC_N_TGPRS; i++) {
299 uint64_t t = cpu->cd.ppc.gpr[i];
300 cpu->cd.ppc.gpr[i] = cpu->cd.ppc.tgpr[i];
301 cpu->cd.ppc.tgpr[i] = t;
302 }
303 }
304
305 if (cpu->cd.ppc.msr & PPC_MSR_IP) {
306 fatal("\n[ Reboot hack for NetBSD/prep. TODO: "
307 "fix this. ]\n");
308 cpu->running = 0;
309 }
310 }
311
312 /* TODO: Is the little-endian bit writable? */
313
314 cpu->cd.ppc.msr &= ~PPC_MSR_LE;
315 if (cpu->byte_order != EMUL_BIG_ENDIAN)
316 cpu->cd.ppc.msr |= PPC_MSR_LE;
317
318 if (!writeflag)
319 *valuep = cpu->cd.ppc.msr;
320
321 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
322 if (cpu->cd.ppc.dec_intr_pending &&
323 !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
324 ppc_exception(cpu, PPC_EXCEPTION_DEC);
325 cpu->cd.ppc.dec_intr_pending = 0;
326 } else if (cpu->cd.ppc.irq_asserted)
327 ppc_exception(cpu, PPC_EXCEPTION_EI);
328 }
329 }
330
331
332 /*
333 * ppc_exception():
334 */
335 void ppc_exception(struct cpu *cpu, int exception_nr)
336 {
337 /* Save PC and MSR: */
338 cpu->cd.ppc.spr[SPR_SRR0] = cpu->pc;
339
340 if (exception_nr >= 0x10 && exception_nr <= 0x13)
341 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0xffff)
342 | (cpu->cd.ppc.cr & 0xf0000000);
343 else
344 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0x87c0ffff);
345
346 if (!quiet_mode)
347 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
348 (long long)cpu->pc);
349
350 /* Disable External Interrupts, Recoverable Interrupt Mode,
351 and go to Supervisor mode */
352 cpu->cd.ppc.msr &= ~(PPC_MSR_EE | PPC_MSR_RI | PPC_MSR_PR);
353
354 cpu->pc = exception_nr * 0x100;
355 if (cpu->cd.ppc.msr & PPC_MSR_IP)
356 cpu->pc += 0xfff00000ULL;
357
358 if (cpu->is_32bit)
359 ppc32_pc_to_pointers(cpu);
360 else
361 ppc_pc_to_pointers(cpu);
362 }
363
364
365 /*
366 * ppc_cpu_register_dump():
367 *
368 * Dump cpu registers in a relatively readable format.
369 *
370 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
371 * coprocs: if bit i is set, then we should dump registers from coproc i.
372 */
373 void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
374 {
375 char *symbol;
376 uint64_t offset, tmp;
377 int i, x = cpu->cpu_id;
378 int bits32 = cpu->cd.ppc.bits == 32;
379
380 if (gprs) {
381 /* Special registers (pc, ...) first: */
382 symbol = get_symbol_name(&cpu->machine->symbol_context,
383 cpu->pc, &offset);
384
385 debug("cpu%i: pc = 0x", x);
386 if (bits32)
387 debug("%08"PRIx32, (uint32_t)cpu->pc);
388 else
389 debug("%016"PRIx64, (uint64_t)cpu->pc);
390 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
391
392 debug("cpu%i: lr = 0x", x);
393 if (bits32)
394 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
395 else
396 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
397 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
398
399 if (bits32)
400 debug(" ");
401 else
402 debug("\ncpu%i: ", x);
403 debug("ctr = 0x", x);
404 if (bits32)
405 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
406 else
407 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
408
409 debug(" xer = 0x", x);
410 if (bits32)
411 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
412 else
413 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
414
415 debug("\n");
416
417 if (bits32) {
418 /* 32-bit: */
419 for (i=0; i<PPC_NGPRS; i++) {
420 if ((i % 4) == 0)
421 debug("cpu%i:", x);
422 debug(" r%02i = 0x%08x ", i,
423 (int)cpu->cd.ppc.gpr[i]);
424 if ((i % 4) == 3)
425 debug("\n");
426 }
427 } else {
428 /* 64-bit: */
429 for (i=0; i<PPC_NGPRS; i++) {
430 int r = (i >> 1) + ((i & 1) << 4);
431 if ((i % 2) == 0)
432 debug("cpu%i:", x);
433 debug(" r%02i = 0x%016llx ", r,
434 (long long)cpu->cd.ppc.gpr[r]);
435 if ((i % 2) == 1)
436 debug("\n");
437 }
438 }
439
440 /* Other special registers: */
441 if (bits32) {
442 debug("cpu%i: srr0 = 0x%08x srr1 = 0x%08x\n", x,
443 (int)cpu->cd.ppc.spr[SPR_SRR0],
444 (int)cpu->cd.ppc.spr[SPR_SRR1]);
445 } else {
446 debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x,
447 (long long)cpu->cd.ppc.spr[SPR_SRR0],
448 (long long)cpu->cd.ppc.spr[SPR_SRR1]);
449 }
450 debug("cpu%i: msr = ", x);
451 reg_access_msr(cpu, &tmp, 0, 0);
452 if (bits32)
453 debug("0x%08x ", (int)tmp);
454 else
455 debug("0x%016llx ", (long long)tmp);
456 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
457 (int)cpu->cd.ppc.spr[SPR_TBL]);
458 debug("cpu%i: dec = 0x%08x", x, (int)cpu->cd.ppc.spr[SPR_DEC]);
459 if (!bits32)
460 debug(" hdec = 0x%08x\n",
461 (int)cpu->cd.ppc.spr[SPR_HDEC]);
462 debug("\n");
463 }
464
465 if (coprocs & 1) {
466 debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
467
468 /* TODO: show floating-point values :-) */
469
470 /* TODO: 32-bit fprs on 32-bit PPC cpus? */
471
472 for (i=0; i<PPC_NFPRS; i++) {
473 if ((i % 2) == 0)
474 debug("cpu%i:", x);
475 debug(" f%02i = 0x%016llx ", i,
476 (long long)cpu->cd.ppc.fpr[i]);
477 if ((i % 2) == 1)
478 debug("\n");
479 }
480 }
481
482 if (coprocs & 2) {
483 debug("cpu%i: sdr1 = 0x%llx\n", x,
484 (long long)cpu->cd.ppc.spr[SPR_SDR1]);
485 if (cpu->cd.ppc.cpu_type.flags & PPC_601)
486 debug("cpu%i: PPC601-style, TODO!\n");
487 else {
488 for (i=0; i<8; i++) {
489 int spr = SPR_IBAT0U + i*2;
490 uint32_t upper = cpu->cd.ppc.spr[spr];
491 uint32_t lower = cpu->cd.ppc.spr[spr+1];
492 uint32_t len = (((upper & BAT_BL) << 15)
493 | 0x1ffff) + 1;
494 debug("cpu%i: %sbat%i: u=0x%08x l=0x%08x ",
495 x, i<4? "i" : "d", i&3, upper, lower);
496 if (!(upper & BAT_V)) {
497 debug(" (not valid)\n");
498 continue;
499 }
500 if (len < 1048576)
501 debug(" (%i KB, ", len >> 10);
502 else
503 debug(" (%i MB, ", len >> 20);
504 if (upper & BAT_Vu)
505 debug("user, ");
506 if (upper & BAT_Vs)
507 debug("supervisor, ");
508 if (lower & (BAT_W | BAT_I | BAT_M | BAT_G))
509 debug("%s%s%s%s, ",
510 lower & BAT_W? "W" : "",
511 lower & BAT_I? "I" : "",
512 lower & BAT_M? "M" : "",
513 lower & BAT_G? "G" : "");
514 switch (lower & BAT_PP) {
515 case BAT_PP_NONE: debug("NO access"); break;
516 case BAT_PP_RO_S: debug("read-only, soft");
517 break;
518 case BAT_PP_RO: debug("read-only"); break;
519 case BAT_PP_RW: debug("read/write"); break;
520 }
521 debug(")\n");
522 }
523 }
524 }
525
526 if (coprocs & 4) {
527 for (i=0; i<16; i++) {
528 uint32_t s = cpu->cd.ppc.sr[i];
529 debug("cpu%i:", x);
530 debug(" sr%-2i = 0x%08x", i, (int)s);
531 s &= (SR_TYPE | SR_SUKEY | SR_PRKEY | SR_NOEXEC);
532 if (s != 0) {
533 debug(" (");
534 if (s & SR_TYPE) {
535 debug("NON-memory type");
536 s &= ~SR_TYPE;
537 if (s != 0)
538 debug(", ");
539 }
540 if (s & SR_SUKEY) {
541 debug("supervisor-key");
542 s &= ~SR_SUKEY;
543 if (s != 0)
544 debug(", ");
545 }
546 if (s & SR_PRKEY) {
547 debug("user-key");
548 s &= ~SR_PRKEY;
549 if (s != 0)
550 debug(", ");
551 }
552 if (s & SR_NOEXEC)
553 debug("NOEXEC");
554 debug(")");
555 }
556 debug("\n");
557 }
558 }
559 }
560
561
562 /*
563 * ppc_cpu_tlbdump():
564 *
565 * Not currently used for PPC.
566 */
567 void ppc_cpu_tlbdump(struct machine *m, int x, int rawflag)
568 {
569 }
570
571
572 static void add_response_word(struct cpu *cpu, char *r, uint64_t value,
573 size_t maxlen, int len)
574 {
575 char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;
576 if (len == 4)
577 value &= 0xffffffffULL;
578 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
579 if (len == 4) {
580 value = ((value & 0xff) << 24) +
581 ((value & 0xff00) << 8) +
582 ((value & 0xff0000) >> 8) +
583 ((value & 0xff000000) >> 24);
584 } else {
585 value = ((value & 0xff) << 56) +
586 ((value & 0xff00) << 40) +
587 ((value & 0xff0000) << 24) +
588 ((value & 0xff000000ULL) << 8) +
589 ((value & 0xff00000000ULL) >> 8) +
590 ((value & 0xff0000000000ULL) >> 24) +
591 ((value & 0xff000000000000ULL) >> 40) +
592 ((value & 0xff00000000000000ULL) >> 56);
593 }
594 }
595 snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);
596 }
597
598
599 /*
600 * ppc_cpu_gdb_stub():
601 *
602 * Execute a "remote GDB" command. Returns a newly allocated response string
603 * on success, NULL on failure.
604 */
605 char *ppc_cpu_gdb_stub(struct cpu *cpu, char *cmd)
606 {
607 if (strcmp(cmd, "g") == 0) {
608 int i;
609 char *r;
610 size_t wlen = cpu->is_32bit?
611 sizeof(uint32_t) : sizeof(uint64_t);
612 size_t len = 1 + 76 * wlen;
613 r = malloc(len);
614 if (r == NULL) {
615 fprintf(stderr, "out of memory\n");
616 exit(1);
617 }
618 r[0] = '\0';
619 for (i=0; i<128; i++)
620 add_response_word(cpu, r, i, len, wlen);
621 return r;
622 }
623
624 if (cmd[0] == 'p') {
625 int regnr = strtol(cmd + 1, NULL, 16);
626 size_t wlen = cpu->is_32bit?
627 sizeof(uint32_t) : sizeof(uint64_t);
628 size_t len = 2 * wlen + 1;
629 char *r = malloc(len);
630 r[0] = '\0';
631 if (regnr >= 0 && regnr <= 31) {
632 add_response_word(cpu, r,
633 cpu->cd.ppc.gpr[regnr], len, wlen);
634 } else if (regnr == 0x40) {
635 add_response_word(cpu, r, cpu->pc, len, wlen);
636 } else if (regnr == 0x42) {
637 add_response_word(cpu, r, cpu->cd.ppc.cr, len, wlen);
638 } else if (regnr == 0x43) {
639 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_LR],
640 len, wlen);
641 } else if (regnr == 0x44) {
642 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_CTR],
643 len, wlen);
644 } else if (regnr == 0x45) {
645 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_XER],
646 len, wlen);
647 } else {
648 /* Unimplemented: */
649 add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);
650 }
651 return r;
652 }
653
654 fatal("ppc_cpu_gdb_stub(): TODO\n");
655 return NULL;
656 }
657
658
659 /*
660 * ppc_cpu_interrupt():
661 *
662 * 0..31 are used as BeBox interrupt numbers, 32..47 = ISA,
663 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
664 *
665 * TODO: don't hardcode to BeBox!
666 */
667 int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
668 {
669 /* fatal("ppc_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
670 if (irq_nr <= 64) {
671 if (cpu->machine->md_interrupt != NULL)
672 cpu->machine->md_interrupt(
673 cpu->machine, cpu, irq_nr, 1);
674 else
675 fatal("ppc_cpu_interrupt(): md_interrupt == NULL\n");
676 } else {
677 /* Assert PPC IRQ: */
678 cpu->cd.ppc.irq_asserted = 1;
679 }
680 return 1;
681 }
682
683
684 /*
685 * ppc_cpu_interrupt_ack():
686 */
687 int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
688 {
689 if (irq_nr <= 64) {
690 if (cpu->machine->md_interrupt != NULL)
691 cpu->machine->md_interrupt(cpu->machine,
692 cpu, irq_nr, 0);
693 } else {
694 /* De-assert PPC IRQ: */
695 cpu->cd.ppc.irq_asserted = 0;
696 }
697 return 1;
698 }
699
700
701 /*
702 * ppc_cpu_disassemble_instr():
703 *
704 * Convert an instruction word into human readable format, for instruction
705 * tracing.
706 *
707 * If running is 1, cpu->pc should be the address of the instruction.
708 *
709 * If running is 0, things that depend on the runtime environment (eg.
710 * register contents) will not be shown, and addr will be used instead of
711 * cpu->pc for relative addresses.
712 */
713 int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
714 int running, uint64_t dumpaddr)
715 {
716 int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
717 int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
718 int bfa, to, load, wlen, no_rb = 0;
719 uint64_t offset, addr;
720 uint32_t iword;
721 char *symbol, *mnem = "ERROR";
722 int power = cpu->cd.ppc.mode == MODE_POWER;
723
724 if (running)
725 dumpaddr = cpu->pc;
726
727 symbol = get_symbol_name(&cpu->machine->symbol_context,
728 dumpaddr, &offset);
729 if (symbol != NULL && offset==0)
730 debug("<%s>\n", symbol);
731
732 if (cpu->machine->ncpus > 1 && running)
733 debug("cpu%i: ", cpu->cpu_id);
734
735 if (cpu->cd.ppc.bits == 32)
736 debug("%08x", (int)dumpaddr);
737 else
738 debug("%016llx", (long long)dumpaddr);
739
740 /* NOTE: Fixed to big-endian. */
741 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
742 + instr[3];
743
744 debug(": %08x\t", iword);
745
746 /*
747 * Decode the instruction:
748 */
749
750 hi6 = iword >> 26;
751
752 switch (hi6) {
753 case 0x4:
754 debug("ALTIVEC TODO");
755 /* vxor etc */
756 break;
757 case PPC_HI6_MULLI:
758 case PPC_HI6_SUBFIC:
759 rt = (iword >> 21) & 31;
760 ra = (iword >> 16) & 31;
761 imm = (int16_t)(iword & 0xffff);
762 switch (hi6) {
763 case PPC_HI6_MULLI:
764 mnem = power? "muli":"mulli";
765 break;
766 case PPC_HI6_SUBFIC:
767 mnem = power? "sfi":"subfic";
768 break;
769 }
770 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
771 break;
772 case PPC_HI6_CMPLI:
773 case PPC_HI6_CMPI:
774 bf = (iword >> 23) & 7;
775 l_bit = (iword >> 21) & 1;
776 ra = (iword >> 16) & 31;
777 if (hi6 == PPC_HI6_CMPLI) {
778 imm = iword & 0xffff;
779 mnem = "cmpl";
780 } else {
781 imm = (int16_t)(iword & 0xffff);
782 mnem = "cmp";
783 }
784 debug("%s%si\t", mnem, l_bit? "d" : "w");
785 if (bf != 0)
786 debug("cr%i,", bf);
787 debug("r%i,%i", ra, imm);
788 break;
789 case PPC_HI6_ADDIC:
790 case PPC_HI6_ADDIC_DOT:
791 rt = (iword >> 21) & 31;
792 ra = (iword >> 16) & 31;
793 rc = hi6 == PPC_HI6_ADDIC_DOT;
794 imm = (int16_t)(iword & 0xffff);
795 mnem = power? "ai":"addic";
796 if (imm < 0 && !power) {
797 mnem = "subic";
798 imm = -imm;
799 }
800 debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
801 break;
802 case PPC_HI6_ADDI:
803 rt = (iword >> 21) & 31;
804 ra = (iword >> 16) & 31;
805 imm = (int16_t)(iword & 0xffff);
806 if (ra == 0)
807 debug("li\tr%i,%i", rt, imm);
808 else {
809 mnem = power? "cal":"addi";
810 if (imm < 0 && !power) {
811 mnem = "subi";
812 imm = -imm;
813 }
814 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
815 }
816 break;
817 case PPC_HI6_ADDIS:
818 rt = (iword >> 21) & 31;
819 ra = (iword >> 16) & 31;
820 imm = (int16_t)(iword & 0xffff);
821 if (ra == 0)
822 debug("lis\tr%i,%i", rt, imm);
823 else
824 debug("%s\tr%i,r%i,%i",
825 power? "cau":"addis", rt, ra, imm);
826 break;
827 case PPC_HI6_BC:
828 aa_bit = (iword & 2) >> 1;
829 lk_bit = iword & 1;
830 bo = (iword >> 21) & 31;
831 bi = (iword >> 16) & 31;
832 /* Sign-extend addr: */
833 addr = (int64_t)(int16_t)(iword & 0xfffc);
834 debug("bc");
835 if (lk_bit)
836 debug("l");
837 if (aa_bit)
838 debug("a");
839 else
840 addr += dumpaddr;
841 debug("\t%i,%i,", bo, bi);
842 if (cpu->cd.ppc.bits == 32)
843 addr &= 0xffffffff;
844 if (cpu->cd.ppc.bits == 32)
845 debug("0x%x", (int)addr);
846 else
847 debug("0x%llx", (long long)addr);
848 symbol = get_symbol_name(&cpu->machine->symbol_context,
849 addr, &offset);
850 if (symbol != NULL)
851 debug("\t<%s>", symbol);
852 break;
853 case PPC_HI6_SC:
854 lev = (iword >> 5) & 0x7f;
855 debug("sc");
856 if (lev != 0) {
857 debug("\t%i", lev);
858 if (lev > 1)
859 debug(" (WARNING! reserved value)");
860 }
861 break;
862 case PPC_HI6_B:
863 aa_bit = (iword & 2) >> 1;
864 lk_bit = iword & 1;
865 /* Sign-extend addr: */
866 addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
867 addr = (int64_t)addr >> 6;
868 debug("b");
869 if (lk_bit)
870 debug("l");
871 if (aa_bit)
872 debug("a");
873 else
874 addr += dumpaddr;
875 if (cpu->cd.ppc.bits == 32)
876 addr &= 0xffffffff;
877 if (cpu->cd.ppc.bits == 32)
878 debug("\t0x%x", (int)addr);
879 else
880 debug("\t0x%llx", (long long)addr);
881 symbol = get_symbol_name(&cpu->machine->symbol_context,
882 addr, &offset);
883 if (symbol != NULL)
884 debug("\t<%s>", symbol);
885 break;
886 case PPC_HI6_19:
887 xo = (iword >> 1) & 1023;
888 switch (xo) {
889 case PPC_19_MCRF:
890 bf = (iword >> 23) & 7;
891 bfa = (iword >> 18) & 7;
892 debug("mcrf\tcr%i,cr%i", bf, bfa);
893 break;
894 case PPC_19_RFI:
895 debug("rfi");
896 break;
897 case PPC_19_RFID:
898 debug("rfid");
899 break;
900 case PPC_19_RFSVC:
901 debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
902 break;
903 case PPC_19_BCLR:
904 case PPC_19_BCCTR:
905 bo = (iword >> 21) & 31;
906 bi = (iword >> 16) & 31;
907 bh = (iword >> 11) & 3;
908 lk_bit = iword & 1;
909 switch (xo) {
910 case PPC_19_BCLR:
911 mnem = power? "bcr" : "bclr"; break;
912 case PPC_19_BCCTR:
913 mnem = power? "bcc" : "bcctr"; break;
914 }
915 debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
916 bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
917 bo, bi, bh);
918 break;
919 case PPC_19_ISYNC:
920 debug("%s", power? "ics" : "isync");
921 break;
922 case PPC_19_CRAND:
923 case PPC_19_CRXOR:
924 case PPC_19_CROR:
925 case PPC_19_CRNAND:
926 case PPC_19_CRNOR:
927 case PPC_19_CRANDC:
928 case PPC_19_CREQV:
929 case PPC_19_CRORC:
930 bt = (iword >> 21) & 31;
931 ba = (iword >> 16) & 31;
932 bb = (iword >> 11) & 31;
933 switch (xo) {
934 case PPC_19_CRAND: mnem = "crand"; break;
935 case PPC_19_CRXOR: mnem = "crxor"; break;
936 case PPC_19_CROR: mnem = "cror"; break;
937 case PPC_19_CRNAND: mnem = "crnand"; break;
938 case PPC_19_CRNOR: mnem = "crnor"; break;
939 case PPC_19_CRANDC: mnem = "crandc"; break;
940 case PPC_19_CREQV: mnem = "creqv"; break;
941 case PPC_19_CRORC: mnem = "crorc"; break;
942 }
943 debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
944 break;
945 default:
946 debug("unimplemented hi6_19, xo = 0x%x", xo);
947 }
948 break;
949 case PPC_HI6_RLWNM:
950 case PPC_HI6_RLWIMI:
951 case PPC_HI6_RLWINM:
952 rs = (iword >> 21) & 31;
953 ra = (iword >> 16) & 31;
954 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
955 mb = (iword >> 6) & 31;
956 me = (iword >> 1) & 31;
957 rc = iword & 1;
958 switch (hi6) {
959 case PPC_HI6_RLWNM:
960 mnem = power? "rlnm" : "rlwnm"; break;
961 case PPC_HI6_RLWIMI:
962 mnem = power? "rlimi" : "rlwimi"; break;
963 case PPC_HI6_RLWINM:
964 mnem = power? "rlinm" : "rlwinm"; break;
965 }
966 debug("%s%s\tr%i,r%i,%s%i,%i,%i",
967 mnem, rc?".":"", ra, rs,
968 hi6 == PPC_HI6_RLWNM? "r" : "",
969 sh, mb, me);
970 break;
971 case PPC_HI6_ORI:
972 case PPC_HI6_ORIS:
973 case PPC_HI6_XORI:
974 case PPC_HI6_XORIS:
975 case PPC_HI6_ANDI_DOT:
976 case PPC_HI6_ANDIS_DOT:
977 rs = (iword >> 21) & 31;
978 ra = (iword >> 16) & 31;
979 imm = iword & 0xffff;
980 switch (hi6) {
981 case PPC_HI6_ORI:
982 mnem = power? "oril":"ori";
983 break;
984 case PPC_HI6_ORIS:
985 mnem = power? "oriu":"oris";
986 break;
987 case PPC_HI6_XORI:
988 mnem = power? "xoril":"xori";
989 break;
990 case PPC_HI6_XORIS:
991 mnem = power? "xoriu":"xoris";
992 break;
993 case PPC_HI6_ANDI_DOT:
994 mnem = power? "andil.":"andi.";
995 break;
996 case PPC_HI6_ANDIS_DOT:
997 mnem = power? "andiu.":"andis.";
998 break;
999 }
1000 if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
1001 debug("nop");
1002 else
1003 debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
1004 break;
1005 case PPC_HI6_30:
1006 xo = (iword >> 2) & 7;
1007 switch (xo) {
1008 case PPC_30_RLDICL:
1009 case PPC_30_RLDICR:
1010 case PPC_30_RLDIMI: /* mb, not me */
1011 mnem = NULL;
1012 switch (xo) {
1013 case PPC_30_RLDICL: mnem = "rldicl"; break;
1014 case PPC_30_RLDICR: mnem = "rldicr"; break;
1015 case PPC_30_RLDIMI: mnem = "rldimi"; break;
1016 }
1017 rs = (iword >> 21) & 31;
1018 ra = (iword >> 16) & 31;
1019 sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
1020 me = ((iword >> 6) & 31) | (iword & 0x20);
1021 rc = iword & 1;
1022 debug("%s%s\tr%i,r%i,%i,%i",
1023 mnem, rc?".":"", ra, rs, sh, me);
1024 break;
1025 default:
1026 debug("unimplemented hi6_30, xo = 0x%x", xo);
1027 }
1028 break;
1029 case PPC_HI6_31:
1030 xo = (iword >> 1) & 1023;
1031 switch (xo) {
1032
1033 case PPC_31_CMP:
1034 case PPC_31_CMPL:
1035 bf = (iword >> 23) & 7;
1036 l_bit = (iword >> 21) & 1;
1037 ra = (iword >> 16) & 31;
1038 rb = (iword >> 11) & 31;
1039 if (xo == PPC_31_CMPL)
1040 mnem = "cmpl";
1041 else
1042 mnem = "cmp";
1043 debug("%s%s\t", mnem, l_bit? "d" : "w");
1044 if (bf != 0)
1045 debug("cr%i,", bf);
1046 debug("r%i,r%i", ra, rb);
1047 break;
1048 case PPC_31_MFCR:
1049 rt = (iword >> 21) & 31;
1050 debug("mfcr\tr%i", rt);
1051 break;
1052 case PPC_31_MFMSR:
1053 rt = (iword >> 21) & 31;
1054 debug("mfmsr\tr%i", rt);
1055 break;
1056 case PPC_31_MTCRF:
1057 rs = (iword >> 21) & 31;
1058 mb = (iword >> 12) & 255; /* actually fxm, not mb */
1059 debug("mtcrf\t%i,r%i", mb, rs);
1060 break;
1061 case PPC_31_MTMSR:
1062 rs = (iword >> 21) & 31;
1063 l_bit = (iword >> 16) & 1;
1064 debug("mtmsr\tr%i", rs);
1065 if (l_bit)
1066 debug(",%i", l_bit);
1067 break;
1068 case PPC_31_TW:
1069 case PPC_31_TD:
1070 to = (iword >> 21) & 31;
1071 ra = (iword >> 16) & 31;
1072 rb = (iword >> 11) & 31;
1073 switch (xo) {
1074 case PPC_31_TW: mnem = power? "t" : "tw"; break;
1075 case PPC_31_TD: mnem = "td"; break;
1076 }
1077 debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
1078 break;
1079 case PPC_31_LWARX:
1080 case PPC_31_LDARX:
1081 case PPC_31_LBZX:
1082 case PPC_31_LBZUX:
1083 case PPC_31_LHAX:
1084 case PPC_31_LHAUX:
1085 case PPC_31_LHZX:
1086 case PPC_31_LHZUX:
1087 case PPC_31_LWZX:
1088 case PPC_31_LWZUX:
1089 case PPC_31_LHBRX:
1090 case PPC_31_LWBRX:
1091 case PPC_31_LFDX:
1092 case PPC_31_LFSX:
1093 case PPC_31_STWCX_DOT:
1094 case PPC_31_STDCX_DOT:
1095 case PPC_31_STBX:
1096 case PPC_31_STBUX:
1097 case PPC_31_STHX:
1098 case PPC_31_STHUX:
1099 case PPC_31_STWX:
1100 case PPC_31_STWUX:
1101 case PPC_31_STDX:
1102 case PPC_31_STDUX:
1103 case PPC_31_STHBRX:
1104 case PPC_31_STWBRX:
1105 case PPC_31_STFDX:
1106 case PPC_31_STFSX:
1107 /* rs for stores, rt for loads, actually */
1108 load = 0; wlen = 0; fpreg = 0;
1109 rs = (iword >> 21) & 31;
1110 ra = (iword >> 16) & 31;
1111 rb = (iword >> 11) & 31;
1112 switch (xo) {
1113 case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
1114 case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
1115 case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
1116 case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
1117 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1118 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1119 case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
1120 case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
1121 case PPC_31_LWZX: wlen = 4; load = 1;
1122 mnem = power? "lx" : "lwzx";
1123 break;
1124 case PPC_31_LWZUX: wlen = 4; load = 1;
1125 mnem = power? "lux":"lwzux";
1126 break;
1127 case PPC_31_LFDX: fpreg = 1; wlen = 8; load = 1;
1128 mnem = "lfdx"; break;
1129 case PPC_31_LFSX: fpreg = 1; wlen = 4; load = 1;
1130 mnem = "lfsx"; break;
1131 case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
1132 case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
1133 case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
1134 case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
1135 case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
1136 case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
1137 case PPC_31_STWX:
1138 wlen = 4; mnem = power? "stx" : "stwx";
1139 break;
1140 case PPC_31_STWUX:
1141 wlen = 4; mnem = power? "stux" : "stwux";
1142 break;
1143 case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
1144 case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
1145 case PPC_31_LHBRX: wlen = 2; mnem = "lhbrx"; break;
1146 case PPC_31_LWBRX: wlen = 4; mnem = power?
1147 "lbrx" : "lwbrx"; break;
1148 case PPC_31_STHBRX: wlen = 2; mnem = "sthbrx"; break;
1149 case PPC_31_STWBRX: wlen = 4; mnem = power?
1150 "stbrx" : "stwbrx"; break;
1151 case PPC_31_STFDX: fpreg = 1; wlen = 8;
1152 mnem = "stfdx"; break;
1153 case PPC_31_STFSX: fpreg = 1; wlen = 4;
1154 mnem = "stfsx"; break;
1155 }
1156 debug("%s\t%s%i,r%i,r%i", mnem,
1157 fpreg? "f" : "r", rs, ra, rb);
1158 if (!running)
1159 break;
1160 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1161 cpu->cd.ppc.gpr[rb];
1162 if (cpu->cd.ppc.bits == 32)
1163 addr &= 0xffffffff;
1164 symbol = get_symbol_name(&cpu->machine->symbol_context,
1165 addr, &offset);
1166 if (symbol != NULL)
1167 debug(" \t<%s", symbol);
1168 else
1169 debug(" \t<0x%llx", (long long)addr);
1170 if (wlen > 0 && !fpreg /* && !reverse */) {
1171 /* TODO */
1172 }
1173 debug(">");
1174 break;
1175 case PPC_31_NEG:
1176 case PPC_31_NEGO:
1177 rt = (iword >> 21) & 31;
1178 ra = (iword >> 16) & 31;
1179 oe_bit = (iword >> 10) & 1;
1180 rc = iword & 1;
1181 switch (xo) {
1182 case PPC_31_NEG: mnem = "neg"; break;
1183 case PPC_31_NEGO: mnem = "nego"; break;
1184 }
1185 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1186 break;
1187 case PPC_31_WRTEEI:
1188 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1189 break;
1190 case PPC_31_MTMSRD:
1191 /* TODO: Just a guess based on MTMSR */
1192 rs = (iword >> 21) & 31;
1193 l_bit = (iword >> 16) & 1;
1194 debug("mtmsrd\tr%i", rs);
1195 if (l_bit)
1196 debug(",%i", l_bit);
1197 break;
1198 case PPC_31_ADDZE:
1199 case PPC_31_ADDZEO:
1200 rt = (iword >> 21) & 31;
1201 ra = (iword >> 16) & 31;
1202 oe_bit = (iword >> 10) & 1;
1203 rc = iword & 1;
1204 switch (xo) {
1205 case PPC_31_ADDZE:
1206 mnem = power? "aze" : "addze";
1207 break;
1208 case PPC_31_ADDZEO:
1209 mnem = power? "azeo" : "addzeo";
1210 break;
1211 }
1212 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1213 break;
1214 case PPC_31_MTSR:
1215 case PPC_31_MFSR:
1216 /* Move to/from segment register */
1217 rt = (iword >> 21) & 31;
1218 ra = (iword >> 16) & 15; /* actually: sr */
1219 switch (xo) {
1220 case PPC_31_MTSR: mnem = "mtsr"; break;
1221 case PPC_31_MFSR: mnem = "mfsr"; break;
1222 }
1223 debug("%s\tr%i,%i", mnem, rt, ra);
1224 break;
1225 case PPC_31_MTSRIN:
1226 case PPC_31_MFSRIN:
1227 /* Move to/from segment register indirect */
1228 rt = (iword >> 21) & 31;
1229 rb = (iword >> 11) & 31;
1230 switch (xo) {
1231 case PPC_31_MTSRIN: mnem = "mtsrin"; break;
1232 case PPC_31_MFSRIN: mnem = "mfsrin"; break;
1233 }
1234 debug("%s\tr%i,r%i", mnem, rt, rb);
1235 break;
1236 case PPC_31_ADDC:
1237 case PPC_31_ADDCO:
1238 case PPC_31_ADDE:
1239 case PPC_31_ADDEO:
1240 case PPC_31_ADDME:
1241 case PPC_31_ADDMEO:
1242 case PPC_31_ADD:
1243 case PPC_31_ADDO:
1244 case PPC_31_MULHW:
1245 case PPC_31_MULHWU:
1246 case PPC_31_MULLW:
1247 case PPC_31_MULLWO:
1248 case PPC_31_SUBF:
1249 case PPC_31_SUBFO:
1250 case PPC_31_SUBFC:
1251 case PPC_31_SUBFCO:
1252 case PPC_31_SUBFE:
1253 case PPC_31_SUBFEO:
1254 case PPC_31_SUBFME:
1255 case PPC_31_SUBFMEO:
1256 case PPC_31_SUBFZE:
1257 case PPC_31_SUBFZEO:
1258 rt = (iword >> 21) & 31;
1259 ra = (iword >> 16) & 31;
1260 rb = (iword >> 11) & 31;
1261 oe_bit = (iword >> 10) & 1;
1262 rc = iword & 1;
1263 switch (xo) {
1264 case PPC_31_ADDC:
1265 mnem = power? "a" : "addc";
1266 break;
1267 case PPC_31_ADDCO:
1268 mnem = power? "ao" : "addco";
1269 break;
1270 case PPC_31_ADDE:
1271 mnem = power? "ae" : "adde";
1272 break;
1273 case PPC_31_ADDEO:
1274 mnem = power? "aeo" : "addeo";
1275 break;
1276 case PPC_31_ADDME:
1277 mnem = power? "ame" : "addme";
1278 no_rb = 1;
1279 break;
1280 case PPC_31_ADDMEO:
1281 mnem = power? "ameo" : "addmeo";
1282 no_rb = 1;
1283 break;
1284 case PPC_31_ADD:
1285 mnem = power? "cax" : "add";
1286 break;
1287 case PPC_31_ADDO:
1288 mnem = power? "caxo" : "addo";
1289 break;
1290 case PPC_31_MULHW: mnem = "mulhw"; break;
1291 case PPC_31_MULHWU: mnem = "mulhwu"; break;
1292 case PPC_31_MULLW:
1293 mnem = power? "muls" : "mullw";
1294 break;
1295 case PPC_31_MULLWO:
1296 mnem = power? "mulso" : "mullwo";
1297 break;
1298 case PPC_31_SUBF: mnem = "subf"; break;
1299 case PPC_31_SUBFO: mnem = "subfo"; break;
1300 case PPC_31_SUBFC:
1301 mnem = power? "sf" : "subfc"; break;
1302 case PPC_31_SUBFCO:
1303 mnem = power? "sfo" : "subfco"; break;
1304 case PPC_31_SUBFE:
1305 mnem = power? "sfe" : "subfe"; break;
1306 case PPC_31_SUBFEO:
1307 mnem = power? "sfeo" : "subfeo"; break;
1308 case PPC_31_SUBFME:
1309 mnem = power? "sfme" : "subfme"; break;
1310 case PPC_31_SUBFMEO:
1311 mnem = power? "sfmeo" : "subfmeo"; break;
1312 case PPC_31_SUBFZE:
1313 mnem = power? "sfze" : "subfze";
1314 no_rb = 1;
1315 break;
1316 case PPC_31_SUBFZEO:
1317 mnem = power? "sfzeo" : "subfzeo";
1318 no_rb = 1;
1319 break;
1320 }
1321 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1322 if (!no_rb)
1323 debug(",r%i", rb);
1324 break;
1325 case PPC_31_MFSPR:
1326 rt = (iword >> 21) & 31;
1327 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1328 switch (spr) {
1329 /* Some very common ones: */
1330 case 8: debug("mflr\tr%i", rt); break;
1331 case 9: debug("mfctr\tr%i", rt); break;
1332 default:debug("mfspr\tr%i,spr%i", rt, spr);
1333 }
1334 if (spr == 8 || spr == 9)
1335 debug("\t");
1336 debug("\t<%s%s", running? "read from " : "",
1337 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1338 if (running) {
1339 if (cpu->cd.ppc.bits == 32)
1340 debug(": 0x%x", (int)
1341 cpu->cd.ppc.spr[spr]);
1342 else
1343 debug(": 0x%llx", (long long)
1344 cpu->cd.ppc.spr[spr]);
1345 }
1346 debug(">");
1347 break;
1348 case PPC_31_TLBIA:
1349 debug("tlbia");
1350 break;
1351 case PPC_31_SLBIA:
1352 debug("slbia");
1353 break;
1354 case PPC_31_TLBLD:
1355 case PPC_31_TLBLI:
1356 rb = (iword >> 11) & 31;
1357 debug("tlbl%s\tr%i", xo == PPC_31_TLBLD? "d" : "i", rb);
1358 break;
1359 case PPC_31_TLBIE:
1360 /* TODO: what is ra? The IBM online docs didn't say */
1361 ra = 0;
1362 rb = (iword >> 11) & 31;
1363 if (power)
1364 debug("tlbi\tr%i,r%i", ra, rb);
1365 else
1366 debug("tlbie\tr%i", rb);
1367 break;
1368 case PPC_31_TLBSX_DOT:
1369 rs = (iword >> 21) & 31;
1370 ra = (iword >> 16) & 31;
1371 rb = (iword >> 11) & 31;
1372 debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb);
1373 break;
1374 case PPC_31_TLBSYNC:
1375 debug("tlbsync");
1376 break;
1377 case PPC_31_MFTB:
1378 rt = (iword >> 21) & 31;
1379 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1380 debug("mftb%s\tr%i", spr==268? "" :
1381 (spr==269? "u" : "?"), rt);
1382 break;
1383 case PPC_31_CNTLZW:
1384 rs = (iword >> 21) & 31;
1385 ra = (iword >> 16) & 31;
1386 rc = iword & 1;
1387 mnem = power? "cntlz" : "cntlzw";
1388 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1389 break;
1390 case PPC_31_CLF: /* POWER only */
1391 case PPC_31_CLI: /* POWER only */
1392 case PPC_31_DCLST: /* POWER only */
1393 case PPC_31_DCBF: /* PowerPC only */
1394 case PPC_31_DCBI: /* PowerPC only */
1395 case PPC_31_DCBST: /* PowerPC only */
1396 case PPC_31_DCBTST: /* PowerPC only */
1397 case PPC_31_DCBT: /* PowerPC only */
1398 case PPC_31_ICBI: /* PowerPC only */
1399 case PPC_31_DCBZ: /* POWER/PowerPC */
1400 ra = (iword >> 16) & 31;
1401 rb = (iword >> 11) & 31;
1402 switch (xo) {
1403 case PPC_31_CLF: mnem = "clf"; break;
1404 case PPC_31_CLI: mnem = "cli"; break;
1405 case PPC_31_DCLST: mnem = "dclst"; break;
1406 case PPC_31_DCBF: mnem = "dcbf"; break;
1407 case PPC_31_DCBI: mnem = "dcbi"; break;
1408 case PPC_31_DCBST: mnem = "dcbst"; break;
1409 case PPC_31_DCBTST:mnem = "dcbtst"; break;
1410 case PPC_31_DCBT: mnem = "dcbt"; break;
1411 case PPC_31_ICBI: mnem = "icbi"; break;
1412 case PPC_31_DCBZ: mnem = power ?
1413 "dclz" : "dcbz"; break;
1414 }
1415 debug("%s\tr%i,r%i", mnem, ra, rb);
1416 break;
1417 case PPC_31_SLW:
1418 case PPC_31_SLD:
1419 case PPC_31_SRAW:
1420 case PPC_31_SRW:
1421 case PPC_31_AND:
1422 case PPC_31_ANDC:
1423 case PPC_31_NOR:
1424 case PPC_31_EQV:
1425 case PPC_31_OR:
1426 case PPC_31_ORC:
1427 case PPC_31_XOR:
1428 case PPC_31_NAND:
1429 rs = (iword >> 21) & 31;
1430 ra = (iword >> 16) & 31;
1431 rb = (iword >> 11) & 31;
1432 rc = iword & 1;
1433 if (rs == rb && xo == PPC_31_OR)
1434 debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1435 else {
1436 switch (xo) {
1437 case PPC_31_SLW: mnem =
1438 power? "sl" : "slw"; break;
1439 case PPC_31_SLD: mnem = "sld"; break;
1440 case PPC_31_SRAW: mnem =
1441 power? "sra" : "sraw"; break;
1442 case PPC_31_SRW: mnem =
1443 power? "sr" : "srw"; break;
1444 case PPC_31_AND: mnem = "and"; break;
1445 case PPC_31_NAND: mnem = "nand"; break;
1446 case PPC_31_ANDC: mnem = "andc"; break;
1447 case PPC_31_NOR: mnem = "nor"; break;
1448 case PPC_31_EQV: mnem = "eqv"; break;
1449 case PPC_31_OR: mnem = "or"; break;
1450 case PPC_31_ORC: mnem = "orc"; break;
1451 case PPC_31_XOR: mnem = "xor"; break;
1452 }
1453 debug("%s%s\tr%i,r%i,r%i", mnem,
1454 rc? "." : "", ra, rs, rb);
1455 }
1456 break;
1457 case PPC_31_DCCCI:
1458 ra = (iword >> 16) & 31;
1459 rb = (iword >> 11) & 31;
1460 debug("dccci\tr%i,r%i", ra, rb);
1461 break;
1462 case PPC_31_ICCCI:
1463 ra = (iword >> 16) & 31;
1464 rb = (iword >> 11) & 31;
1465 debug("iccci\tr%i,r%i", ra, rb);
1466 break;
1467 case PPC_31_DIVW:
1468 case PPC_31_DIVWO:
1469 case PPC_31_DIVWU:
1470 case PPC_31_DIVWUO:
1471 rt = (iword >> 21) & 31;
1472 ra = (iword >> 16) & 31;
1473 rb = (iword >> 11) & 31;
1474 oe_bit = (iword >> 10) & 1;
1475 rc = iword & 1;
1476 switch (xo) {
1477 case PPC_31_DIVWU: mnem = "divwu"; break;
1478 case PPC_31_DIVWUO: mnem = "divwuo"; break;
1479 case PPC_31_DIVW: mnem = "divw"; break;
1480 case PPC_31_DIVWO: mnem = "divwo"; break;
1481 }
1482 debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1483 rt, ra, rb);
1484 break;
1485 case PPC_31_MTSPR:
1486 rs = (iword >> 21) & 31;
1487 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1488 switch (spr) {
1489 /* Some very common ones: */
1490 case 8: debug("mtlr\tr%i", rs); break;
1491 case 9: debug("mtctr\tr%i", rs); break;
1492 default:debug("mtspr\tspr%i,r%i", spr, rs);
1493 }
1494 if (spr == 8 || spr == 9)
1495 debug("\t");
1496 debug("\t<%s%s", running? "write to " : "",
1497 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1498 if (running) {
1499 if (cpu->cd.ppc.bits == 32)
1500 debug(": 0x%x", (int)
1501 cpu->cd.ppc.gpr[rs]);
1502 else
1503 debug(": 0x%llx", (long long)
1504 cpu->cd.ppc.gpr[rs]);
1505 }
1506 debug(">");
1507 break;
1508 case PPC_31_SYNC:
1509 debug("%s", power? "dcs" : "sync");
1510 break;
1511 case PPC_31_LSWI:
1512 case PPC_31_STSWI:
1513 rs = (iword >> 21) & 31; /* lwsi uses rt */
1514 ra = (iword >> 16) & 31;
1515 nb = (iword >> 11) & 31;
1516 switch (xo) {
1517 case PPC_31_LSWI:
1518 mnem = power? "lsi" : "lswi"; break;
1519 case PPC_31_STSWI:
1520 mnem = power? "stsi" : "stswi"; break;
1521 }
1522 debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1523 break;
1524 case PPC_31_SRAWI:
1525 rs = (iword >> 21) & 31;
1526 ra = (iword >> 16) & 31;
1527 sh = (iword >> 11) & 31;
1528 rc = iword & 1;
1529 mnem = power? "srai" : "srawi";
1530 debug("%s%s\tr%i,r%i,%i", mnem,
1531 rc? "." : "", ra, rs, sh);
1532 break;
1533 case PPC_31_DSSALL:
1534 debug("dssall");
1535 break;
1536 case PPC_31_EIEIO:
1537 debug("%s", power? "eieio?" : "eieio");
1538 break;
1539 case PPC_31_EXTSB:
1540 case PPC_31_EXTSH:
1541 case PPC_31_EXTSW:
1542 rs = (iword >> 21) & 31;
1543 ra = (iword >> 16) & 31;
1544 rc = iword & 1;
1545 switch (xo) {
1546 case PPC_31_EXTSB:
1547 mnem = power? "exts" : "extsb";
1548 break;
1549 case PPC_31_EXTSH:
1550 mnem = "extsh";
1551 break;
1552 case PPC_31_EXTSW:
1553 mnem = "extsw";
1554 break;
1555 }
1556 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1557 break;
1558 case PPC_31_LVX:
1559 case PPC_31_LVXL:
1560 case PPC_31_STVX:
1561 case PPC_31_STVXL:
1562 rs = (iword >> 21) & 31; /* vs for stores, */
1563 ra = (iword >> 16) & 31; /* rs=vl for loads */
1564 rb = (iword >> 11) & 31;
1565 rc = iword & 1;
1566 switch (xo) {
1567 case PPC_31_LVX: mnem = "lvx"; break;
1568 case PPC_31_LVXL: mnem = "lvxl"; break;
1569 case PPC_31_STVX: mnem = "stvx"; break;
1570 case PPC_31_STVXL: mnem = "stvxl"; break;
1571 }
1572 debug("%s%s\tv%i,r%i,r%i", mnem, rc? "." : "",
1573 rs, ra, rb);
1574 break;
1575 default:
1576 debug("unimplemented hi6_31, xo = 0x%x", xo);
1577 }
1578 break;
1579 case PPC_HI6_LD:
1580 case PPC_HI6_LWZ:
1581 case PPC_HI6_LWZU:
1582 case PPC_HI6_LHZ:
1583 case PPC_HI6_LHZU:
1584 case PPC_HI6_LHA:
1585 case PPC_HI6_LHAU:
1586 case PPC_HI6_LBZ:
1587 case PPC_HI6_LBZU:
1588 case PPC_HI6_LFD:
1589 case PPC_HI6_LFS:
1590 case PPC_HI6_LMW:
1591 case PPC_HI6_STD:
1592 case PPC_HI6_STW:
1593 case PPC_HI6_STWU:
1594 case PPC_HI6_STH:
1595 case PPC_HI6_STHU:
1596 case PPC_HI6_STB:
1597 case PPC_HI6_STBU:
1598 case PPC_HI6_STMW:
1599 case PPC_HI6_STFD:
1600 case PPC_HI6_STFS:
1601 /* NOTE: Loads use rt, not rs, but are otherwise similar
1602 to stores */
1603 load = 0; wlen = 0;
1604 rs = (iword >> 21) & 31;
1605 ra = (iword >> 16) & 31;
1606 imm = (int16_t)(iword & 0xffff);
1607 fpreg = 0;
1608 switch (hi6) {
1609 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1610 case PPC_HI6_LWZ: load=1; wlen = 4;
1611 mnem = power? "l" : "lwz"; break;
1612 case PPC_HI6_LWZU: load=1; wlen = 4;
1613 mnem = power? "lu" : "lwzu"; break;
1614 case PPC_HI6_LHZ: load=1; wlen = 2;
1615 mnem = "lhz"; break;
1616 case PPC_HI6_LHZU: load=1; wlen = 2;
1617 mnem = "lhzu"; break;
1618 case PPC_HI6_LHA: load=2; wlen = 2;
1619 mnem = "lha"; break;
1620 case PPC_HI6_LHAU: load=2; wlen = 2;
1621 mnem = "lhau"; break;
1622 case PPC_HI6_LBZ: load=1; wlen = 1;
1623 mnem = "lbz"; break;
1624 case PPC_HI6_LBZU: load=1; wlen = 1;
1625 mnem = "lbzu"; break;
1626 case PPC_HI6_LFD: load=1; fpreg=1; wlen=8; mnem = "lfd"; break;
1627 case PPC_HI6_LFS: load=1; fpreg=1; wlen=4; mnem = "lfs"; break;
1628 case PPC_HI6_STD: wlen=8; mnem = "std"; break;
1629 case PPC_HI6_STW: wlen=4; mnem = power? "st" : "stw"; break;
1630 case PPC_HI6_STWU: wlen=4; mnem = power? "stu" : "stwu"; break;
1631 case PPC_HI6_STH: wlen=2; mnem = "sth"; break;
1632 case PPC_HI6_STHU: wlen=2; mnem = "sthu"; break;
1633 case PPC_HI6_STB: wlen=1; mnem = "stb"; break;
1634 case PPC_HI6_STBU: wlen=1; mnem = "stbu"; break;
1635 case PPC_HI6_LMW: load=1; mnem = power? "lm" : "lmw"; break;
1636 case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1637 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1638 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1639 }
1640 debug("%s\t", mnem);
1641 if (fpreg)
1642 debug("f");
1643 else
1644 debug("r");
1645 debug("%i,%i(r%i)", rs, imm, ra);
1646 if (!running)
1647 break;
1648 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) + imm;
1649 if (cpu->cd.ppc.bits == 32)
1650 addr &= 0xffffffff;
1651 symbol = get_symbol_name(&cpu->machine->symbol_context,
1652 addr, &offset);
1653 if (symbol != NULL)
1654 debug(" \t<%s", symbol);
1655 else
1656 debug(" \t<0x%llx", (long long)addr);
1657 if (wlen > 0 && load && wlen > 0) {
1658 unsigned char tw[8];
1659 uint64_t tdata = 0;
1660 int i, res = cpu->memory_rw(cpu, cpu->mem, addr, tw,
1661 wlen, MEM_READ, NO_EXCEPTIONS);
1662 if (res) {
1663 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1664 for (i=0; i<wlen; i++) {
1665 tdata <<= 8;
1666 tdata |= tw[wlen-1-i];
1667 }
1668 else
1669 for (i=0; i<wlen; i++) {
1670 tdata <<= 8;
1671 tdata |= tw[i];
1672 }
1673 debug(": ");
1674 if (wlen >= 4) {
1675 symbol = get_symbol_name(&cpu->machine->
1676 symbol_context, tdata, &offset);
1677 if (symbol != NULL)
1678 debug("%s", symbol);
1679 else
1680 debug("0x%llx",
1681 (long long)tdata);
1682 } else {
1683 /* TODO: if load==2, then this is
1684 a _signed_ load. */
1685 debug("0x%llx", (long long)tdata);
1686 }
1687 } else
1688 debug(": unreadable");
1689 }
1690 if (wlen > 0 && !load && wlen > 0) {
1691 int64_t tdata = 0;
1692 int i;
1693 for (i=0; i<wlen; i++)
1694 tdata |= (cpu->cd.ppc.gpr[rs] &
1695 ((uint64_t)0xff << (i*8)));
1696 debug(": ");
1697 if (wlen >= 4) {
1698 symbol = get_symbol_name(&cpu->machine->
1699 symbol_context, tdata, &offset);
1700 if (symbol != NULL)
1701 debug("%s", symbol);
1702 else
1703 debug("0x%llx", (long long)tdata);
1704 } else {
1705 if (tdata > -256 && tdata < 256)
1706 debug("%i", (int)tdata);
1707 else
1708 debug("0x%llx", (long long)tdata);
1709 }
1710 }
1711 debug(">");
1712 break;
1713 case PPC_HI6_59:
1714 xo = (iword >> 1) & 1023;
1715 /* NOTE: Some floating point instructions only use the
1716 lowest 5 bits of xo, some use all 10 bits! */
1717 switch (xo & 31) {
1718 case PPC_59_FDIVS:
1719 case PPC_59_FSUBS:
1720 case PPC_59_FADDS:
1721 case PPC_59_FMULS:
1722 case PPC_59_FMADDS:
1723 rt = (iword >> 21) & 31;
1724 ra = (iword >> 16) & 31;
1725 rb = (iword >> 11) & 31;
1726 rs = (iword >> 6) & 31; /* actually frc */
1727 rc = iword & 1;
1728 switch (xo & 31) {
1729 case PPC_59_FDIVS: mnem = "fdivs"; break;
1730 case PPC_59_FSUBS: mnem = "fsubs"; break;
1731 case PPC_59_FADDS: mnem = "fadds"; break;
1732 case PPC_59_FMULS: mnem = "fmuls"; break;
1733 case PPC_59_FMADDS: mnem = "fmadds"; break;
1734 }
1735 debug("%s%s\t", mnem, rc? "." : "");
1736 switch (xo & 31) {
1737 case PPC_59_FMULS:
1738 debug("f%i,f%i,f%i", rt, ra, rs);
1739 break;
1740 case PPC_59_FMADDS:
1741 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1742 break;
1743 default:debug("f%i,f%i,f%i", rt, ra, rb);
1744 }
1745 break;
1746 default:/* TODO: similar to hi6_63 */
1747 debug("unimplemented hi6_59, xo = 0x%x", xo);
1748 }
1749 break;
1750 case PPC_HI6_63:
1751 xo = (iword >> 1) & 1023;
1752 /* NOTE: Some floating point instructions only use the
1753 lowest 5 bits of xo, some use all 10 bits! */
1754 switch (xo & 31) {
1755 case PPC_63_FDIV:
1756 case PPC_63_FSUB:
1757 case PPC_63_FADD:
1758 case PPC_63_FMUL:
1759 case PPC_63_FMSUB:
1760 case PPC_63_FMADD:
1761 rt = (iword >> 21) & 31;
1762 ra = (iword >> 16) & 31;
1763 rb = (iword >> 11) & 31;
1764 rs = (iword >> 6) & 31; /* actually frc */
1765 rc = iword & 1;
1766 switch (xo & 31) {
1767 case PPC_63_FDIV:
1768 mnem = power? "fd" : "fdiv"; break;
1769 case PPC_63_FSUB:
1770 mnem = power? "fs" : "fsub"; break;
1771 case PPC_63_FADD:
1772 mnem = power? "fa" : "fadd"; break;
1773 case PPC_63_FMUL:
1774 mnem = power? "fm" : "fmul"; break;
1775 case PPC_63_FMSUB:
1776 mnem = power? "fms" : "fmsub"; break;
1777 case PPC_63_FMADD:
1778 mnem = power? "fma" : "fmadd"; break;
1779 }
1780 debug("%s%s\t", mnem, rc? "." : "");
1781 switch (xo & 31) {
1782 case PPC_63_FMUL:
1783 debug("f%i,f%i,f%i", rt, ra, rs);
1784 break;
1785 case PPC_63_FMADD:
1786 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1787 break;
1788 default:debug("f%i,f%i,f%i", rt, ra, rb);
1789 }
1790 break;
1791 default:rt = (iword >> 21) & 31;
1792 ra = (iword >> 16) & 31;
1793 rb = (iword >> 11) & 31;
1794 rc = iword & 1;
1795 switch (xo) {
1796 case PPC_63_FCMPU:
1797 case PPC_63_FRSP:
1798 case PPC_63_FCTIWZ:
1799 case PPC_63_FNEG:
1800 case PPC_63_FMR:
1801 case PPC_63_FNABS:
1802 case PPC_63_FABS:
1803 switch (xo) {
1804 case PPC_63_FCMPU: mnem = "fcmpu"; break;
1805 case PPC_63_FCTIWZ:
1806 mnem = power? "fcirz" : "fctiwz"; break;
1807 case PPC_63_FRSP: mnem = "frsp"; break;
1808 case PPC_63_FNEG: mnem = "fneg"; break;
1809 case PPC_63_FMR: mnem = "fmr"; break;
1810 case PPC_63_FNABS: mnem = "fnabs"; break;
1811 case PPC_63_FABS: mnem = "fabs"; break;
1812 }
1813 debug("%s%s\t", mnem, rc? "." : "");
1814 switch (xo) {
1815 case PPC_63_FCMPU:
1816 debug("%i,f%i,f%i", rt >> 2, ra, rb);
1817 break;
1818 case PPC_63_FCTIWZ:
1819 case PPC_63_FRSP:
1820 case PPC_63_FNEG:
1821 case PPC_63_FMR:
1822 case PPC_63_FNABS:
1823 case PPC_63_FABS:
1824 debug("f%i,f%i", rt, rb);
1825 break;
1826 default:debug("f%i,f%i,f%i", rt, ra, rb);
1827 }
1828 break;
1829 case PPC_63_MFFS:
1830 debug("mffs%s\tf%i", rc?".":"", rt);
1831 break;
1832 case PPC_63_MTFSF:
1833 ra = (iword >> 17) & 255; /* flm */
1834 debug("mtfsf%s\t0x%02x,f%i", rc?".":"", ra, rb);
1835 break;
1836 default:debug("unimplemented hi6_63, xo = 0x%x", xo);
1837 }
1838 }
1839 break;
1840 default:
1841 /* TODO */
1842 debug("unimplemented hi6 = 0x%02x", hi6);
1843 }
1844
1845 debug("\n");
1846 return sizeof(iword);
1847 }
1848
1849
1850 /*
1851 * debug_spr_usage():
1852 *
1853 * Helper function. To speed up overall development speed of the emulator,
1854 * all SPR accesses are allowed. This function causes unknown/unimplemented
1855 * SPRs to give a warning.
1856 */
1857 static void debug_spr_usage(uint64_t pc, int spr)
1858 {
1859 static uint32_t spr_used[1024 / sizeof(uint32_t)];
1860 static int initialized = 0;
1861
1862 if (!initialized) {
1863 memset(spr_used, 0, sizeof(spr_used));
1864 initialized = 1;
1865 }
1866
1867 spr &= 1023;
1868 if (spr_used[spr >> 2] & (1 << (spr & 3)))
1869 return;
1870
1871 switch (spr) {
1872 /* Known/implemented SPRs: */
1873 case SPR_XER:
1874 case SPR_LR:
1875 case SPR_CTR:
1876 case SPR_DSISR:
1877 case SPR_DAR:
1878 case SPR_DEC:
1879 case SPR_SDR1:
1880 case SPR_SRR0:
1881 case SPR_SRR1:
1882 case SPR_SPRG0:
1883 case SPR_SPRG1:
1884 case SPR_SPRG2:
1885 case SPR_SPRG3:
1886 case SPR_PVR:
1887 case SPR_DMISS:
1888 case SPR_DCMP:
1889 case SPR_HASH1:
1890 case SPR_HASH2:
1891 case SPR_IMISS:
1892 case SPR_ICMP:
1893 case SPR_DBSR:
1894 case SPR_PIR:
1895 break;
1896 default:if (spr >= SPR_IBAT0U && spr <= SPR_DBAT3L) {
1897 break;
1898 } else
1899 fatal("[ using UNIMPLEMENTED spr %i (%s), pc = "
1900 "0x%llx ]\n", spr, ppc_spr_names[spr] == NULL?
1901 "UNKNOWN" : ppc_spr_names[spr], (long long)pc);
1902 }
1903
1904 spr_used[spr >> 2] |= (1 << (spr & 3));
1905 }
1906
1907
1908 /*
1909 * update_cr0():
1910 *
1911 * Sets the top 4 bits of the CR register.
1912 */
1913 void update_cr0(struct cpu *cpu, uint64_t value)
1914 {
1915 int c;
1916
1917 if (cpu->cd.ppc.bits == 64) {
1918 if ((int64_t)value < 0)
1919 c = 8;
1920 else if ((int64_t)value > 0)
1921 c = 4;
1922 else
1923 c = 2;
1924 } else {
1925 if ((int32_t)value < 0)
1926 c = 8;
1927 else if ((int32_t)value > 0)
1928 c = 4;
1929 else
1930 c = 2;
1931 }
1932
1933 /* SO bit, copied from XER: */
1934 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1935
1936 cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1937 cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1938 }
1939
1940
1941 #include "memory_ppc.c"
1942
1943
1944 #include "tmp_ppc_tail.c"
1945
1946

  ViewVC Help
Powered by ViewVC 1.1.26