/[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

Annotation of /trunk/src/cpus/cpu_ppc.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: 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 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_ppc.c,v 1.64 2006/09/21 11:53:26 debug Exp $
29 dpavlin 14 *
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 dpavlin 22 #include "of.h"
44 dpavlin 14 #include "opcodes_ppc.h"
45 dpavlin 20 #include "ppc_bat.h"
46     #include "ppc_pte.h"
47     #include "ppc_spr.h"
48     #include "ppc_spr_strings.h"
49 dpavlin 32 #include "settings.h"
50 dpavlin 14 #include "symbol.h"
51    
52     #define DYNTRANS_DUALMODE_32
53     #include "tmp_ppc_head.c"
54    
55    
56 dpavlin 20 void ppc_pc_to_pointers(struct cpu *);
57     void ppc32_pc_to_pointers(struct cpu *);
58    
59    
60 dpavlin 14 /*
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 dpavlin 32 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 dpavlin 14
95     /* Current operating mode: */
96     cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
97 dpavlin 20 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
98 dpavlin 14
99 dpavlin 24 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
100     PPC_MSR_SF | PPC_MSR_FP; */
101    
102 dpavlin 22 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 dpavlin 14 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
118    
119     if (cpu->is_32bit) {
120 dpavlin 28 cpu->run_instr = ppc32_run_instr;
121 dpavlin 14 cpu->update_translation_table = ppc32_update_translation_table;
122 dpavlin 18 cpu->invalidate_translation_caches =
123     ppc32_invalidate_translation_caches;
124 dpavlin 14 cpu->invalidate_code_translation =
125     ppc32_invalidate_code_translation;
126     } else {
127 dpavlin 28 cpu->run_instr = ppc_run_instr;
128 dpavlin 14 cpu->update_translation_table = ppc_update_translation_table;
129 dpavlin 18 cpu->invalidate_translation_caches =
130     ppc_invalidate_translation_caches;
131 dpavlin 14 cpu->invalidate_code_translation =
132     ppc_invalidate_code_translation;
133     }
134    
135 dpavlin 26 cpu->translate_v2p = ppc_translate_v2p;
136 dpavlin 14
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 dpavlin 20 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
162 dpavlin 14
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 dpavlin 32 /* 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 dpavlin 14 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 dpavlin 20 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
283     int check_for_interrupts)
284 dpavlin 14 {
285 dpavlin 20 uint64_t old = cpu->cd.ppc.msr;
286    
287 dpavlin 14 if (valuep == NULL) {
288     fatal("reg_access_msr(): NULL\n");
289     return;
290     }
291    
292 dpavlin 20 if (writeflag) {
293 dpavlin 14 cpu->cd.ppc.msr = *valuep;
294    
295 dpavlin 20 /* 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 dpavlin 14 /* 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 dpavlin 20
321     if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
322 dpavlin 30 if (cpu->cd.ppc.dec_intr_pending &&
323     !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
324 dpavlin 20 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 dpavlin 14 }
330    
331    
332     /*
333 dpavlin 20 * 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 dpavlin 24 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
348 dpavlin 20 (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 dpavlin 22 cpu->pc += 0xfff00000ULL;
357 dpavlin 20
358     if (cpu->is_32bit)
359     ppc32_pc_to_pointers(cpu);
360     else
361     ppc_pc_to_pointers(cpu);
362     }
363    
364    
365     /*
366 dpavlin 14 * 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 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->pc);
388 dpavlin 14 else
389 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->pc);
390 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
391    
392     debug("cpu%i: lr = 0x", x);
393     if (bits32)
394 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
395 dpavlin 14 else
396 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
397     debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
398 dpavlin 14
399     if (bits32)
400 dpavlin 22 debug(" ");
401     else
402     debug("\ncpu%i: ", x);
403     debug("ctr = 0x", x);
404     if (bits32)
405 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
406 dpavlin 14 else
407 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
408 dpavlin 14
409     debug(" xer = 0x", x);
410     if (bits32)
411 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
412 dpavlin 14 else
413 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
414 dpavlin 14
415 dpavlin 24 debug("\n");
416    
417 dpavlin 14 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 dpavlin 22 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 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
452 dpavlin 22 if (bits32)
453     debug("0x%08x ", (int)tmp);
454     else
455     debug("0x%016llx ", (long long)tmp);
456 dpavlin 20 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
457     (int)cpu->cd.ppc.spr[SPR_TBL]);
458 dpavlin 22 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 dpavlin 14 }
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 dpavlin 20 (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 dpavlin 14 }
525 dpavlin 20
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 dpavlin 32 debug(" sr%-2i = 0x%08x", i, (int)s);
531 dpavlin 20 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 dpavlin 14 }
560    
561    
562     /*
563 dpavlin 24 * 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 dpavlin 20 * ppc_cpu_interrupt():
661 dpavlin 14 *
662 dpavlin 20 * 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 dpavlin 14 *
665 dpavlin 20 * TODO: don't hardcode to BeBox!
666 dpavlin 14 */
667     int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
668     {
669 dpavlin 20 /* 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 dpavlin 14 }
682    
683    
684     /*
685     * ppc_cpu_interrupt_ack():
686     */
687     int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
688     {
689 dpavlin 20 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 dpavlin 14 }
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 dpavlin 24 int running, uint64_t dumpaddr)
715 dpavlin 14 {
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 dpavlin 22 case 0x4:
754     debug("ALTIVEC TODO");
755     /* vxor etc */
756     break;
757 dpavlin 14 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 dpavlin 20 case PPC_HI6_RLWNM:
950 dpavlin 14 case PPC_HI6_RLWIMI:
951     case PPC_HI6_RLWINM:
952     rs = (iword >> 21) & 31;
953     ra = (iword >> 16) & 31;
954 dpavlin 20 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
955 dpavlin 14 mb = (iword >> 6) & 31;
956     me = (iword >> 1) & 31;
957     rc = iword & 1;
958     switch (hi6) {
959 dpavlin 20 case PPC_HI6_RLWNM:
960     mnem = power? "rlnm" : "rlwnm"; break;
961 dpavlin 14 case PPC_HI6_RLWIMI:
962     mnem = power? "rlimi" : "rlwimi"; break;
963     case PPC_HI6_RLWINM:
964     mnem = power? "rlinm" : "rlwinm"; break;
965     }
966 dpavlin 20 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 dpavlin 14 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 dpavlin 24 case PPC_30_RLDICL:
1009 dpavlin 14 case PPC_30_RLDICR:
1010 dpavlin 24 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 dpavlin 14 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 dpavlin 24 debug("%s%s\tr%i,r%i,%i,%i",
1023     mnem, rc?".":"", ra, rs, sh, me);
1024 dpavlin 14 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 dpavlin 20 case PPC_31_LHAX:
1084     case PPC_31_LHAUX:
1085 dpavlin 14 case PPC_31_LHZX:
1086     case PPC_31_LHZUX:
1087     case PPC_31_LWZX:
1088     case PPC_31_LWZUX:
1089 dpavlin 20 case PPC_31_LHBRX:
1090     case PPC_31_LWBRX:
1091     case PPC_31_LFDX:
1092     case PPC_31_LFSX:
1093 dpavlin 14 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 dpavlin 20 case PPC_31_STHBRX:
1104     case PPC_31_STWBRX:
1105     case PPC_31_STFDX:
1106     case PPC_31_STFSX:
1107 dpavlin 14 /* rs for stores, rt for loads, actually */
1108 dpavlin 20 load = 0; wlen = 0; fpreg = 0;
1109 dpavlin 14 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 dpavlin 20 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1118     case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1119 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 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 dpavlin 14 }
1156 dpavlin 20 debug("%s\t%s%i,r%i,r%i", mnem,
1157     fpreg? "f" : "r", rs, ra, rb);
1158 dpavlin 14 if (!running)
1159     break;
1160     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1161     cpu->cd.ppc.gpr[rb];
1162 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1163     addr &= 0xffffffff;
1164 dpavlin 14 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 dpavlin 20 if (wlen > 0 && !fpreg /* && !reverse */) {
1171 dpavlin 14 /* 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 dpavlin 22 case PPC_31_WRTEEI:
1188     debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1189     break;
1190 dpavlin 24 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 dpavlin 14 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 dpavlin 20 case PPC_31_MFSR:
1216     /* Move to/from segment register */
1217 dpavlin 14 rt = (iword >> 21) & 31;
1218     ra = (iword >> 16) & 15; /* actually: sr */
1219 dpavlin 20 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 dpavlin 14 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 dpavlin 20 case PPC_31_SUBFME:
1255     case PPC_31_SUBFMEO:
1256 dpavlin 14 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 dpavlin 20 mnem = power? "sf" : "subfc"; break;
1302 dpavlin 14 case PPC_31_SUBFCO:
1303 dpavlin 20 mnem = power? "sfo" : "subfco"; break;
1304 dpavlin 14 case PPC_31_SUBFE:
1305 dpavlin 20 mnem = power? "sfe" : "subfe"; break;
1306 dpavlin 14 case PPC_31_SUBFEO:
1307 dpavlin 20 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 dpavlin 14 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 dpavlin 20 /* Some very common ones: */
1330 dpavlin 14 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 dpavlin 20 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 dpavlin 14 break;
1348 dpavlin 20 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 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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 dpavlin 24 case PPC_31_SLD:
1419 dpavlin 14 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 dpavlin 24 case PPC_31_EQV:
1425 dpavlin 14 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 dpavlin 24 case PPC_31_SLD: mnem = "sld"; break;
1440 dpavlin 14 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 dpavlin 24 case PPC_31_EQV: mnem = "eqv"; break;
1449 dpavlin 14 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 dpavlin 20 /* Some very common ones: */
1490 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 24 case PPC_31_DSSALL:
1534     debug("dssall");
1535     break;
1536 dpavlin 14 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 dpavlin 22 case PPC_31_LVX:
1559 dpavlin 24 case PPC_31_LVXL:
1560 dpavlin 22 case PPC_31_STVX:
1561     case PPC_31_STVXL:
1562 dpavlin 24 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 dpavlin 22 break;
1575 dpavlin 14 default:
1576     debug("unimplemented hi6_31, xo = 0x%x", xo);
1577     }
1578     break;
1579 dpavlin 20 case PPC_HI6_LD:
1580 dpavlin 14 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 dpavlin 20 case PPC_HI6_LFD:
1589     case PPC_HI6_LFS:
1590 dpavlin 14 case PPC_HI6_LMW:
1591 dpavlin 20 case PPC_HI6_STD:
1592 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFS:
1601 dpavlin 14 /* 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 dpavlin 20 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1610 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1638     case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1639 dpavlin 14 }
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 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1650     addr &= 0xffffffff;
1651 dpavlin 14 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 dpavlin 20 ((uint64_t)0xff << (i*8)));
1696 dpavlin 14 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 dpavlin 20 debug("0x%llx", (long long)tdata);
1704 dpavlin 14 } 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 dpavlin 20 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 dpavlin 14 case PPC_HI6_63:
1751     xo = (iword >> 1) & 1023;
1752 dpavlin 20 /* 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 dpavlin 14 rt = (iword >> 21) & 31;
1762     ra = (iword >> 16) & 31;
1763     rb = (iword >> 11) & 31;
1764 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
1765 dpavlin 14 rc = iword & 1;
1766 dpavlin 20 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 dpavlin 14 switch (xo) {
1796 dpavlin 20 case PPC_63_FCMPU:
1797     case PPC_63_FRSP:
1798     case PPC_63_FCTIWZ:
1799     case PPC_63_FNEG:
1800 dpavlin 14 case PPC_63_FMR:
1801 dpavlin 20 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 dpavlin 14 break;
1829 dpavlin 20 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 dpavlin 14 }
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 dpavlin 20 * 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 dpavlin 14 * 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 dpavlin 20 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1935 dpavlin 14
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 dpavlin 24

  ViewVC Help
Powered by ViewVC 1.1.26