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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 89836 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


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 24 * $Id: cpu_ppc_instr.c,v 1.70 2006/04/14 19:58:21 debug Exp $
29 dpavlin 14 *
30     * POWER/PowerPC instructions.
31     *
32     * Individual functions should keep track of cpu->n_translated_instrs.
33     * (If no instruction was executed, then it should be decreased. If, say, 4
34     * instructions were combined into one function and executed, then it should
35     * be increased by 3.)
36     */
37    
38    
39 dpavlin 20 #include "float_emul.h"
40    
41    
42     #define DOT0(n) X(n ## _dot) { instr(n)(cpu,ic); \
43     update_cr0(cpu, reg(ic->arg[0])); }
44     #define DOT1(n) X(n ## _dot) { instr(n)(cpu,ic); \
45 dpavlin 14 update_cr0(cpu, reg(ic->arg[1])); }
46 dpavlin 20 #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47     update_cr0(cpu, reg(ic->arg[2])); }
48 dpavlin 14
49 dpavlin 22 #ifndef CHECK_FOR_FPU_EXCEPTION
50     #define CHECK_FOR_FPU_EXCEPTION { if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) { \
51     /* Synchronize the PC, and cause an FPU exception: */ \
52     uint64_t low_pc = ((size_t)ic - \
53     (size_t)cpu->cd.ppc.cur_ic_page) \
54     / sizeof(struct ppc_instr_call); \
55     cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << \
56     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << \
57     PPC_INSTR_ALIGNMENT_SHIFT); \
58     ppc_exception(cpu, PPC_EXCEPTION_FPU); \
59     return; } }
60     #endif
61 dpavlin 14
62 dpavlin 22
63    
64 dpavlin 14 /*
65     * nop: Do nothing.
66     */
67     X(nop)
68     {
69     }
70    
71    
72     /*
73     * invalid: To catch bugs.
74     */
75     X(invalid)
76     {
77 dpavlin 20 fatal("PPC: invalid(): INTERNAL ERROR\n");
78 dpavlin 14 exit(1);
79     }
80    
81    
82     /*
83     * addi: Add immediate.
84     *
85     * arg[0] = pointer to source uint64_t
86     * arg[1] = immediate value (int32_t or larger)
87     * arg[2] = pointer to destination uint64_t
88     */
89     X(addi)
90     {
91     reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];
92     }
93 dpavlin 22 X(li)
94     {
95     reg(ic->arg[2]) = (int32_t)ic->arg[1];
96     }
97     X(li_0)
98     {
99     reg(ic->arg[2]) = 0;
100     }
101 dpavlin 14
102    
103     /*
104     * andi_dot: AND immediate, update CR.
105     *
106     * arg[0] = pointer to source uint64_t
107     * arg[1] = immediate value (uint32_t)
108     * arg[2] = pointer to destination uint64_t
109     */
110     X(andi_dot)
111     {
112     MODE_uint_t tmp = reg(ic->arg[0]) & (uint32_t)ic->arg[1];
113     reg(ic->arg[2]) = tmp;
114     update_cr0(cpu, tmp);
115     }
116    
117    
118     /*
119     * addic: Add immediate, Carry.
120     *
121     * arg[0] = pointer to source register
122     * arg[1] = immediate value (int32_t or larger)
123     * arg[2] = pointer to destination register
124     */
125     X(addic)
126     {
127     /* TODO/NOTE: Only for 32-bit mode, so far! */
128     uint64_t tmp = (uint32_t)reg(ic->arg[0]);
129     uint64_t tmp2 = tmp;
130 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
131 dpavlin 14 tmp2 += (uint32_t)ic->arg[1];
132     if ((tmp2 >> 32) != (tmp >> 32))
133 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
134 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp2;
135     }
136    
137    
138     /*
139     * subfic: Subtract from immediate, Carry.
140     *
141     * arg[0] = pointer to source uint64_t
142     * arg[1] = immediate value (int32_t or larger)
143     * arg[2] = pointer to destination uint64_t
144     */
145     X(subfic)
146     {
147     MODE_uint_t tmp = (int64_t)(int32_t)ic->arg[1];
148 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
149 dpavlin 14 if (tmp >= reg(ic->arg[0]))
150 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
151 dpavlin 14 reg(ic->arg[2]) = tmp - reg(ic->arg[0]);
152     }
153    
154    
155     /*
156     * addic_dot: Add immediate, Carry.
157     *
158     * arg[0] = pointer to source uint64_t
159     * arg[1] = immediate value (int32_t or larger)
160     * arg[2] = pointer to destination uint64_t
161     */
162     X(addic_dot)
163     {
164     /* TODO/NOTE: Only for 32-bit mode, so far! */
165     uint64_t tmp = (uint32_t)reg(ic->arg[0]);
166     uint64_t tmp2 = tmp;
167 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
168 dpavlin 14 tmp2 += (uint32_t)ic->arg[1];
169     if ((tmp2 >> 32) != (tmp >> 32))
170 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
171 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp2;
172     update_cr0(cpu, (uint32_t)tmp2);
173     }
174    
175    
176     /*
177     * bclr: Branch Conditional to Link Register
178     *
179     * arg[0] = bo
180 dpavlin 20 * arg[1] = 31 - bi
181 dpavlin 14 * arg[2] = bh
182     */
183     X(bclr)
184     {
185 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
186 dpavlin 14 int ctr_ok, cond_ok;
187     uint64_t old_pc = cpu->pc;
188 dpavlin 20 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
189 dpavlin 14 if (!(bo & 4))
190 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
191 dpavlin 14 ctr_ok = (bo >> 2) & 1;
192 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
193 dpavlin 14 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
194     cond_ok = (bo >> 4) & 1;
195 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
196 dpavlin 14 if (ctr_ok && cond_ok) {
197     uint64_t mask_within_page =
198     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
199     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
200     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
201     /* TODO: trace in separate (duplicate) function? */
202     if (cpu->machine->show_trace_tree)
203     cpu_functioncall_trace_return(cpu);
204     if ((old_pc & ~mask_within_page) ==
205     (cpu->pc & ~mask_within_page)) {
206     cpu->cd.ppc.next_ic =
207     cpu->cd.ppc.cur_ic_page +
208     ((cpu->pc & mask_within_page) >>
209     PPC_INSTR_ALIGNMENT_SHIFT);
210     } else {
211     /* Find the new physical page and update pointers: */
212 dpavlin 22 quick_pc_to_pointers(cpu);
213 dpavlin 14 }
214     }
215     }
216 dpavlin 20 X(bclr_20)
217     {
218     cpu->pc = cpu->cd.ppc.spr[SPR_LR];
219 dpavlin 22 quick_pc_to_pointers(cpu);
220 dpavlin 20 }
221 dpavlin 14 X(bclr_l)
222     {
223     uint64_t low_pc, old_pc = cpu->pc;
224 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /* ,bh = ic->arg[2]*/;
225 dpavlin 14 int ctr_ok, cond_ok;
226 dpavlin 20 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
227 dpavlin 14 if (!(bo & 4))
228 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
229 dpavlin 14 ctr_ok = (bo >> 2) & 1;
230 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
231 dpavlin 14 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
232     cond_ok = (bo >> 4) & 1;
233 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
234 dpavlin 14
235     /* Calculate return PC: */
236 dpavlin 20 low_pc = ((size_t)ic - (size_t)
237     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
238 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
239     << PPC_INSTR_ALIGNMENT_SHIFT);
240     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
241 dpavlin 14
242     if (ctr_ok && cond_ok) {
243     uint64_t mask_within_page =
244     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
245     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
246     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
247     /* TODO: trace in separate (duplicate) function? */
248     if (cpu->machine->show_trace_tree)
249     cpu_functioncall_trace_return(cpu);
250     if (cpu->machine->show_trace_tree)
251     cpu_functioncall_trace(cpu, cpu->pc);
252     if ((old_pc & ~mask_within_page) ==
253     (cpu->pc & ~mask_within_page)) {
254     cpu->cd.ppc.next_ic =
255     cpu->cd.ppc.cur_ic_page +
256     ((cpu->pc & mask_within_page) >>
257     PPC_INSTR_ALIGNMENT_SHIFT);
258     } else {
259     /* Find the new physical page and update pointers: */
260 dpavlin 22 quick_pc_to_pointers(cpu);
261 dpavlin 14 }
262     }
263     }
264    
265    
266     /*
267     * bcctr: Branch Conditional to Count register
268     *
269     * arg[0] = bo
270 dpavlin 20 * arg[1] = 31 - bi
271 dpavlin 14 * arg[2] = bh
272     */
273     X(bcctr)
274     {
275 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2]*/;
276 dpavlin 14 uint64_t old_pc = cpu->pc;
277 dpavlin 20 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
278 dpavlin 14 int cond_ok = (bo >> 4) & 1;
279 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
280 dpavlin 14 if (cond_ok) {
281     uint64_t mask_within_page =
282     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
283     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
284     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
285     /* TODO: trace in separate (duplicate) function? */
286     if (cpu->machine->show_trace_tree)
287     cpu_functioncall_trace_return(cpu);
288     if ((old_pc & ~mask_within_page) ==
289     (cpu->pc & ~mask_within_page)) {
290     cpu->cd.ppc.next_ic =
291     cpu->cd.ppc.cur_ic_page +
292     ((cpu->pc & mask_within_page) >>
293     PPC_INSTR_ALIGNMENT_SHIFT);
294     } else {
295     /* Find the new physical page and update pointers: */
296 dpavlin 22 quick_pc_to_pointers(cpu);
297 dpavlin 14 }
298     }
299     }
300     X(bcctr_l)
301     {
302     uint64_t low_pc, old_pc = cpu->pc;
303 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2] */;
304 dpavlin 20 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
305 dpavlin 14 int cond_ok = (bo >> 4) & 1;
306 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
307 dpavlin 14
308     /* Calculate return PC: */
309 dpavlin 20 low_pc = ((size_t)ic - (size_t)
310     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
311 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
312     << PPC_INSTR_ALIGNMENT_SHIFT);
313     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
314 dpavlin 14
315     if (cond_ok) {
316     uint64_t mask_within_page =
317     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
318     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
319     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
320     /* TODO: trace in separate (duplicate) function? */
321     if (cpu->machine->show_trace_tree)
322     cpu_functioncall_trace(cpu, cpu->pc);
323     if ((old_pc & ~mask_within_page) ==
324     (cpu->pc & ~mask_within_page)) {
325     cpu->cd.ppc.next_ic =
326     cpu->cd.ppc.cur_ic_page +
327     ((cpu->pc & mask_within_page) >>
328     PPC_INSTR_ALIGNMENT_SHIFT);
329     } else {
330     /* Find the new physical page and update pointers: */
331 dpavlin 22 quick_pc_to_pointers(cpu);
332 dpavlin 14 }
333     }
334     }
335    
336    
337     /*
338     * b: Branch (to a different translated page)
339     *
340 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
341 dpavlin 14 */
342     X(b)
343     {
344 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
345 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
346    
347     /* Find the new physical page and update the translation pointers: */
348 dpavlin 22 quick_pc_to_pointers(cpu);
349 dpavlin 14 }
350 dpavlin 20 X(ba)
351     {
352     cpu->pc = (int32_t)ic->arg[0];
353 dpavlin 22 quick_pc_to_pointers(cpu);
354 dpavlin 20 }
355 dpavlin 14
356    
357     /*
358     * bc: Branch Conditional (to a different translated page)
359     *
360 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
361 dpavlin 14 * arg[1] = bo
362 dpavlin 22 * arg[2] = 31-bi
363 dpavlin 14 */
364     X(bc)
365     {
366     MODE_uint_t tmp;
367 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
368 dpavlin 14 if (!(bo & 4))
369 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
370 dpavlin 14 ctr_ok = (bo >> 2) & 1;
371 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
372 dpavlin 14 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
373     cond_ok = (bo >> 4) & 1;
374     cond_ok |= ( ((bo >> 3) & 1) ==
375 dpavlin 22 ((cpu->cd.ppc.cr >> (bi31m)) & 1) );
376 dpavlin 14 if (ctr_ok && cond_ok)
377     instr(b)(cpu,ic);
378     }
379 dpavlin 20 X(bcl)
380     {
381     MODE_uint_t tmp;
382 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
383     int low_pc;
384 dpavlin 14
385 dpavlin 20 /* Calculate LR: */
386     low_pc = ((size_t)ic - (size_t)
387     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
388 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
389     << PPC_INSTR_ALIGNMENT_SHIFT);
390     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
391 dpavlin 14
392 dpavlin 20 if (!(bo & 4))
393     cpu->cd.ppc.spr[SPR_CTR] --;
394     ctr_ok = (bo >> 2) & 1;
395     tmp = cpu->cd.ppc.spr[SPR_CTR];
396     ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
397     cond_ok = (bo >> 4) & 1;
398     cond_ok |= ( ((bo >> 3) & 1) ==
399 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
400 dpavlin 20 if (ctr_ok && cond_ok)
401     instr(b)(cpu,ic);
402     }
403    
404    
405 dpavlin 14 /*
406     * b_samepage: Branch (to within the same translated page)
407     *
408     * arg[0] = pointer to new ppc_instr_call
409     */
410     X(b_samepage)
411     {
412     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
413     }
414    
415    
416     /*
417     * bc_samepage: Branch Conditional (to within the same page)
418     *
419     * arg[0] = new ic ptr
420     * arg[1] = bo
421 dpavlin 22 * arg[2] = 31-bi
422 dpavlin 14 */
423     X(bc_samepage)
424     {
425     MODE_uint_t tmp;
426 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
427 dpavlin 14 if (!(bo & 4))
428 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
429 dpavlin 14 ctr_ok = (bo >> 2) & 1;
430 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
431 dpavlin 14 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
432     cond_ok = (bo >> 4) & 1;
433     cond_ok |= ( ((bo >> 3) & 1) ==
434 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
435 dpavlin 14 if (ctr_ok && cond_ok)
436 dpavlin 20 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
437 dpavlin 14 }
438 dpavlin 22 X(bc_samepage_simple0)
439 dpavlin 20 {
440 dpavlin 22 int bi31m = ic->arg[2];
441     if (!((cpu->cd.ppc.cr >> bi31m) & 1))
442 dpavlin 20 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
443     }
444 dpavlin 22 X(bc_samepage_simple1)
445     {
446     int bi31m = ic->arg[2];
447     if ((cpu->cd.ppc.cr >> bi31m) & 1)
448     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
449     }
450 dpavlin 20 X(bcl_samepage)
451     {
452     MODE_uint_t tmp;
453 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
454     int low_pc;
455 dpavlin 14
456 dpavlin 20 /* Calculate LR: */
457     low_pc = ((size_t)ic - (size_t)
458     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
459 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
460     << PPC_INSTR_ALIGNMENT_SHIFT);
461     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
462 dpavlin 14
463 dpavlin 20 if (!(bo & 4))
464     cpu->cd.ppc.spr[SPR_CTR] --;
465     ctr_ok = (bo >> 2) & 1;
466     tmp = cpu->cd.ppc.spr[SPR_CTR];
467     ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
468     cond_ok = (bo >> 4) & 1;
469     cond_ok |= ( ((bo >> 3) & 1) ==
470 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
471 dpavlin 20 if (ctr_ok && cond_ok)
472     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
473     }
474    
475    
476 dpavlin 14 /*
477     * bl: Branch and Link (to a different translated page)
478     *
479 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
480     * arg[1] = lr offset (relative to start of current page)
481 dpavlin 14 */
482     X(bl)
483     {
484 dpavlin 22 /* Calculate LR and new PC: */
485     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
486     cpu->cd.ppc.spr[SPR_LR] = cpu->pc + ic->arg[1];
487 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
488    
489     /* Find the new physical page and update the translation pointers: */
490 dpavlin 22 quick_pc_to_pointers(cpu);
491 dpavlin 14 }
492 dpavlin 20 X(bla)
493     {
494 dpavlin 22 /* Calculate LR: */
495     cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
496     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
497    
498 dpavlin 20 cpu->pc = (int32_t)ic->arg[0];
499 dpavlin 22 quick_pc_to_pointers(cpu);
500 dpavlin 20 }
501 dpavlin 14
502    
503     /*
504     * bl_trace: Branch and Link (to a different translated page) (with trace)
505     *
506 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
507     * arg[1] = lr offset (relative to start of current page)
508 dpavlin 14 */
509     X(bl_trace)
510     {
511     /* Calculate LR: */
512 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
513     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
514 dpavlin 14
515 dpavlin 22 /* Calculate new PC from start of page + arg[0] */
516     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
517 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
518    
519     cpu_functioncall_trace(cpu, cpu->pc);
520    
521     /* Find the new physical page and update the translation pointers: */
522 dpavlin 22 quick_pc_to_pointers(cpu);
523 dpavlin 14 }
524 dpavlin 20 X(bla_trace)
525     {
526 dpavlin 22 /* Calculate LR: */
527     cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
528     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
529    
530 dpavlin 20 cpu->pc = (int32_t)ic->arg[0];
531     cpu_functioncall_trace(cpu, cpu->pc);
532 dpavlin 22 quick_pc_to_pointers(cpu);
533 dpavlin 20 }
534 dpavlin 14
535    
536     /*
537     * bl_samepage: Branch and Link (to within the same translated page)
538     *
539     * arg[0] = pointer to new ppc_instr_call
540 dpavlin 22 * arg[1] = lr offset (relative to start of current page)
541 dpavlin 14 */
542     X(bl_samepage)
543     {
544     /* Calculate LR: */
545 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
546     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
547 dpavlin 14
548     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
549     }
550    
551    
552     /*
553     * bl_samepage_trace: Branch and Link (to within the same translated page)
554     *
555     * arg[0] = pointer to new ppc_instr_call
556 dpavlin 22 * arg[1] = lr offset (relative to start of current page)
557 dpavlin 14 */
558     X(bl_samepage_trace)
559     {
560     uint32_t low_pc;
561    
562     /* Calculate LR: */
563 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
564     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
565 dpavlin 14
566     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
567    
568     /* Calculate new PC (for the trace) */
569     low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
570     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
571 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
572     cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
573 dpavlin 14 cpu_functioncall_trace(cpu, cpu->pc);
574     }
575    
576    
577     /*
578     * cntlzw: Count leading zeroes (32-bit word).
579     *
580     * arg[0] = ptr to rs
581     * arg[1] = ptr to ra
582     */
583     X(cntlzw)
584     {
585     uint32_t tmp = reg(ic->arg[0]);
586     int i;
587     for (i=0; i<32; i++) {
588     if (tmp & 0x80000000)
589     break;
590     tmp <<= 1;
591     }
592     reg(ic->arg[1]) = i;
593     }
594    
595    
596     /*
597     * cmpd: Compare Doubleword
598     *
599     * arg[0] = ptr to ra
600     * arg[1] = ptr to rb
601 dpavlin 20 * arg[2] = 28 - 4*bf
602 dpavlin 14 */
603     X(cmpd)
604     {
605     int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
606 dpavlin 20 int bf_shift = ic->arg[2], c;
607 dpavlin 14 if (tmp < tmp2)
608     c = 8;
609     else if (tmp > tmp2)
610     c = 4;
611     else
612     c = 2;
613 dpavlin 20 /* SO bit, copied from XER */
614     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
615     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
616     cpu->cd.ppc.cr |= (c << bf_shift);
617 dpavlin 14 }
618    
619    
620     /*
621     * cmpld: Compare Doubleword, unsigned
622     *
623     * arg[0] = ptr to ra
624     * arg[1] = ptr to rb
625 dpavlin 20 * arg[2] = 28 - 4*bf
626 dpavlin 14 */
627     X(cmpld)
628     {
629     uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
630 dpavlin 20 int bf_shift = ic->arg[2], c;
631 dpavlin 14 if (tmp < tmp2)
632     c = 8;
633     else if (tmp > tmp2)
634     c = 4;
635     else
636     c = 2;
637 dpavlin 20 /* SO bit, copied from XER */
638     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
639     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
640     cpu->cd.ppc.cr |= (c << bf_shift);
641 dpavlin 14 }
642    
643    
644     /*
645     * cmpdi: Compare Doubleword immediate
646     *
647     * arg[0] = ptr to ra
648     * arg[1] = int32_t imm
649 dpavlin 20 * arg[2] = 28 - 4*bf
650 dpavlin 14 */
651     X(cmpdi)
652     {
653     int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
654 dpavlin 20 int bf_shift = ic->arg[2], c;
655 dpavlin 14 if (tmp < imm)
656     c = 8;
657     else if (tmp > imm)
658     c = 4;
659     else
660     c = 2;
661 dpavlin 20 /* SO bit, copied from XER */
662     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
663     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
664     cpu->cd.ppc.cr |= (c << bf_shift);
665 dpavlin 14 }
666    
667    
668     /*
669     * cmpldi: Compare Doubleword immediate, logical
670     *
671     * arg[0] = ptr to ra
672     * arg[1] = int32_t imm
673 dpavlin 20 * arg[2] = 28 - 4*bf
674 dpavlin 14 */
675     X(cmpldi)
676     {
677     uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
678 dpavlin 20 int bf_shift = ic->arg[2], c;
679 dpavlin 14 if (tmp < imm)
680     c = 8;
681     else if (tmp > imm)
682     c = 4;
683     else
684     c = 2;
685 dpavlin 20 /* SO bit, copied from XER */
686     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
687     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
688     cpu->cd.ppc.cr |= (c << bf_shift);
689 dpavlin 14 }
690    
691    
692     /*
693     * cmpw: Compare Word
694     *
695     * arg[0] = ptr to ra
696     * arg[1] = ptr to rb
697 dpavlin 20 * arg[2] = 28 - 4*bf
698 dpavlin 14 */
699     X(cmpw)
700     {
701     int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
702 dpavlin 20 int bf_shift = ic->arg[2], c;
703 dpavlin 14 if (tmp < tmp2)
704     c = 8;
705     else if (tmp > tmp2)
706     c = 4;
707     else
708     c = 2;
709 dpavlin 20 /* SO bit, copied from XER */
710     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
711     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
712     cpu->cd.ppc.cr |= (c << bf_shift);
713 dpavlin 14 }
714 dpavlin 22 X(cmpw_cr0)
715     {
716     /* arg[2] is assumed to be 28 */
717     int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
718     cpu->cd.ppc.cr &= ~(0xf0000000);
719     if (tmp < tmp2)
720     cpu->cd.ppc.cr |= 0x80000000;
721     else if (tmp > tmp2)
722     cpu->cd.ppc.cr |= 0x40000000;
723     else
724     cpu->cd.ppc.cr |= 0x20000000;
725     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
726     }
727 dpavlin 14
728    
729     /*
730     * cmplw: Compare Word, unsigned
731     *
732     * arg[0] = ptr to ra
733     * arg[1] = ptr to rb
734 dpavlin 20 * arg[2] = 28 - 4*bf
735 dpavlin 14 */
736     X(cmplw)
737     {
738     uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
739 dpavlin 20 int bf_shift = ic->arg[2], c;
740 dpavlin 14 if (tmp < tmp2)
741     c = 8;
742     else if (tmp > tmp2)
743     c = 4;
744     else
745     c = 2;
746 dpavlin 20 /* SO bit, copied from XER */
747     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
748     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
749     cpu->cd.ppc.cr |= (c << bf_shift);
750 dpavlin 14 }
751    
752    
753     /*
754     * cmpwi: Compare Word immediate
755     *
756     * arg[0] = ptr to ra
757     * arg[1] = int32_t imm
758 dpavlin 20 * arg[2] = 28 - 4*bf
759 dpavlin 14 */
760     X(cmpwi)
761     {
762     int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
763 dpavlin 20 int bf_shift = ic->arg[2], c;
764 dpavlin 14 if (tmp < imm)
765     c = 8;
766     else if (tmp > imm)
767     c = 4;
768     else
769     c = 2;
770 dpavlin 20 /* SO bit, copied from XER */
771     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
772     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
773     cpu->cd.ppc.cr |= (c << bf_shift);
774 dpavlin 14 }
775 dpavlin 22 X(cmpwi_cr0)
776     {
777     /* arg[2] is assumed to be 28 */
778     int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
779     cpu->cd.ppc.cr &= ~(0xf0000000);
780     if (tmp < imm)
781     cpu->cd.ppc.cr |= 0x80000000;
782     else if (tmp > imm)
783     cpu->cd.ppc.cr |= 0x40000000;
784     else
785     cpu->cd.ppc.cr |= 0x20000000;
786     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
787     }
788 dpavlin 14
789    
790     /*
791     * cmplwi: Compare Word immediate, logical
792     *
793     * arg[0] = ptr to ra
794     * arg[1] = int32_t imm
795 dpavlin 20 * arg[2] = 28 - 4*bf
796 dpavlin 14 */
797     X(cmplwi)
798     {
799     uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
800 dpavlin 20 int bf_shift = ic->arg[2], c;
801 dpavlin 14 if (tmp < imm)
802     c = 8;
803     else if (tmp > imm)
804     c = 4;
805     else
806     c = 2;
807 dpavlin 20 /* SO bit, copied from XER */
808     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
809     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
810     cpu->cd.ppc.cr |= (c << bf_shift);
811 dpavlin 14 }
812    
813    
814     /*
815     * dcbz: Data-Cache Block Zero
816     *
817     * arg[0] = ptr to ra (or zero)
818     * arg[1] = ptr to rb
819     */
820     X(dcbz)
821     {
822     MODE_uint_t addr = reg(ic->arg[0]) + reg(ic->arg[1]);
823     unsigned char cacheline[128];
824 dpavlin 22 size_t cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;
825     size_t cleared = 0;
826 dpavlin 14
827 dpavlin 20 /* Synchronize the PC first: */
828     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
829    
830 dpavlin 14 addr &= ~(cacheline_size - 1);
831     memset(cacheline, 0, sizeof(cacheline));
832    
833     while (cleared < cacheline_size) {
834     int to_clear = cacheline_size < sizeof(cacheline)?
835     cacheline_size : sizeof(cacheline);
836 dpavlin 22 #ifdef MODE32
837     unsigned char *page = cpu->cd.ppc.host_store[addr >> 12];
838     if (page != NULL) {
839     memset(page + (addr & 0xfff), 0, to_clear);
840     } else
841     #endif
842     if (cpu->memory_rw(cpu, cpu->mem, addr, cacheline,
843     to_clear, MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
844 dpavlin 20 /* exception */
845     return;
846 dpavlin 14 }
847    
848     cleared += to_clear;
849     addr += to_clear;
850     }
851     }
852    
853    
854     /*
855 dpavlin 20 * mtfsf: Copy FPR into the FPSCR.
856     *
857     * arg[0] = ptr to frb
858     * arg[1] = mask
859     */
860     X(mtfsf)
861     {
862 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
863 dpavlin 20 cpu->cd.ppc.fpscr &= ~ic->arg[1];
864     cpu->cd.ppc.fpscr |= (ic->arg[1] & (*(uint64_t *)ic->arg[0]));
865     }
866    
867    
868     /*
869     * mffs: Copy FPSCR into a FPR.
870     *
871     * arg[0] = ptr to frt
872     */
873     X(mffs)
874     {
875 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
876 dpavlin 20 (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;
877     }
878    
879    
880     /*
881 dpavlin 14 * fmr: Floating-point Move
882     *
883     * arg[0] = ptr to frb
884     * arg[1] = ptr to frt
885     */
886     X(fmr)
887     {
888 dpavlin 22 /*
889     * This works like a normal register to register copy, but
890     * a) it can cause an FPU exception, and b) the move is always
891     * 64-bit, even when running in 32-bit mode.
892     */
893     CHECK_FOR_FPU_EXCEPTION;
894 dpavlin 14 *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
895     }
896    
897    
898     /*
899 dpavlin 20 * fneg: Floating-point Negate
900     *
901     * arg[0] = ptr to frb
902     * arg[1] = ptr to frt
903     */
904     X(fneg)
905     {
906     uint64_t v;
907 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
908 dpavlin 20 v = *(uint64_t *)ic->arg[0];
909     *(uint64_t *)ic->arg[1] = v ^ 0x8000000000000000ULL;
910     }
911    
912    
913     /*
914     * fcmpu: Floating-point Compare Unordered
915     *
916     * arg[0] = 28 - 4*bf (bitfield shift)
917     * arg[1] = ptr to fra
918     * arg[2] = ptr to frb
919     */
920     X(fcmpu)
921     {
922     struct ieee_float_value fra, frb;
923     int bf_shift = ic->arg[0], c = 0;
924    
925 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
926 dpavlin 20
927     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
928     ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frb, IEEE_FMT_D);
929     if (fra.nan | frb.nan) {
930     c = 1;
931     } else {
932     if (fra.f < frb.f)
933     c = 8;
934     else if (fra.f > frb.f)
935     c = 4;
936     else
937     c = 2;
938     }
939     /* TODO: Signaling vs Quiet NaN */
940     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
941     cpu->cd.ppc.cr |= ((c&0xe) << bf_shift);
942     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
943     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
944     }
945    
946    
947     /*
948     * frsp: Floating-point Round to Single Precision
949     *
950     * arg[0] = ptr to frb
951     * arg[1] = ptr to frt
952     */
953     X(frsp)
954     {
955     struct ieee_float_value frb;
956     float fl = 0.0;
957     int c = 0;
958    
959 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
960 dpavlin 20
961     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
962     if (frb.nan) {
963     c = 1;
964     } else {
965     fl = frb.f;
966     if (fl < 0.0)
967     c = 8;
968     else if (fl > 0.0)
969     c = 4;
970     else
971     c = 2;
972     }
973     /* TODO: Signaling vs Quiet NaN */
974     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
975     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
976     (*(uint64_t *)ic->arg[1]) =
977     ieee_store_float_value(fl, IEEE_FMT_D, frb.nan);
978     }
979    
980    
981     /*
982     * fctiwz: Floating-point Convert to Integer Word, Round to Zero
983     *
984     * arg[0] = ptr to frb
985     * arg[1] = ptr to frt
986     */
987     X(fctiwz)
988     {
989     struct ieee_float_value frb;
990 dpavlin 24 uint32_t res = 0;
991 dpavlin 20
992 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
993 dpavlin 20
994     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
995     if (!frb.nan) {
996     if (frb.f >= 2147483647.0)
997     res = 0x7fffffff;
998     else if (frb.f <= -2147483648.0)
999     res = 0x80000000;
1000     else
1001     res = frb.f;
1002     }
1003     *(uint64_t *)ic->arg[1] = (uint32_t)res;
1004     }
1005    
1006    
1007     /*
1008     * fmul: Floating-point Multiply
1009     *
1010     * arg[0] = ptr to frt
1011     * arg[1] = ptr to fra
1012     * arg[2] = ptr to frc
1013     */
1014     X(fmul)
1015     {
1016     struct ieee_float_value fra;
1017     struct ieee_float_value frc;
1018     double result = 0.0;
1019     int c, nan = 0;
1020    
1021 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1022 dpavlin 20
1023     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1024     ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frc, IEEE_FMT_D);
1025     if (fra.nan || frc.nan)
1026     nan = 1;
1027     else
1028     result = fra.f * frc.f;
1029     if (nan)
1030     c = 1;
1031     else {
1032     if (result < 0.0)
1033     c = 8;
1034     else if (result > 0.0)
1035     c = 4;
1036     else
1037     c = 2;
1038     }
1039     /* TODO: Signaling vs Quiet NaN */
1040     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1041     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1042    
1043     (*(uint64_t *)ic->arg[0]) =
1044     ieee_store_float_value(result, IEEE_FMT_D, nan);
1045     }
1046     X(fmuls)
1047     {
1048     /* TODO */
1049     instr(fmul)(cpu, ic);
1050     }
1051    
1052    
1053     /*
1054     * fmadd: Floating-point Multiply and Add
1055     *
1056     * arg[0] = ptr to frt
1057     * arg[1] = ptr to fra
1058     * arg[2] = copy of the instruction word
1059     */
1060     X(fmadd)
1061     {
1062     uint32_t iw = ic->arg[2];
1063     int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1064     struct ieee_float_value fra;
1065     struct ieee_float_value frb;
1066     struct ieee_float_value frc;
1067     double result = 0.0;
1068     int nan = 0, cc;
1069    
1070 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1071 dpavlin 20
1072     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1073     ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1074     ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1075     if (fra.nan || frb.nan || frc.nan)
1076     nan = 1;
1077     else
1078     result = fra.f * frc.f + frb.f;
1079     if (nan)
1080     cc = 1;
1081     else {
1082     if (result < 0.0)
1083     cc = 8;
1084     else if (result > 0.0)
1085     cc = 4;
1086     else
1087     cc = 2;
1088     }
1089     /* TODO: Signaling vs Quiet NaN */
1090     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1091     cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1092    
1093     (*(uint64_t *)ic->arg[0]) =
1094     ieee_store_float_value(result, IEEE_FMT_D, nan);
1095     }
1096    
1097    
1098     /*
1099     * fmsub: Floating-point Multiply and Sub
1100     *
1101     * arg[0] = ptr to frt
1102     * arg[1] = ptr to fra
1103     * arg[2] = copy of the instruction word
1104     */
1105     X(fmsub)
1106     {
1107     uint32_t iw = ic->arg[2];
1108     int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1109     struct ieee_float_value fra;
1110     struct ieee_float_value frb;
1111     struct ieee_float_value frc;
1112     double result = 0.0;
1113     int nan = 0, cc;
1114    
1115 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1116 dpavlin 20
1117     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1118     ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1119     ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1120     if (fra.nan || frb.nan || frc.nan)
1121     nan = 1;
1122     else
1123     result = fra.f * frc.f - frb.f;
1124     if (nan)
1125     cc = 1;
1126     else {
1127     if (result < 0.0)
1128     cc = 8;
1129     else if (result > 0.0)
1130     cc = 4;
1131     else
1132     cc = 2;
1133     }
1134     /* TODO: Signaling vs Quiet NaN */
1135     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1136     cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1137    
1138     (*(uint64_t *)ic->arg[0]) =
1139     ieee_store_float_value(result, IEEE_FMT_D, nan);
1140     }
1141    
1142    
1143     /*
1144     * fadd, fsub, fdiv: Various Floating-point operationgs
1145     *
1146     * arg[0] = ptr to fra
1147     * arg[1] = ptr to frb
1148     * arg[2] = ptr to frt
1149     */
1150     X(fadd)
1151     {
1152     struct ieee_float_value fra;
1153     struct ieee_float_value frb;
1154     double result = 0.0;
1155     int nan = 0, c;
1156    
1157 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1158 dpavlin 20
1159     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1160     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1161     if (fra.nan || frb.nan)
1162     nan = 1;
1163     else
1164     result = fra.f + frb.f;
1165     if (nan)
1166     c = 1;
1167     else {
1168     if (result < 0.0)
1169     c = 8;
1170     else if (result > 0.0)
1171     c = 4;
1172     else
1173     c = 2;
1174     }
1175     /* TODO: Signaling vs Quiet NaN */
1176     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1177     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1178    
1179     (*(uint64_t *)ic->arg[2]) =
1180     ieee_store_float_value(result, IEEE_FMT_D, nan);
1181     }
1182     X(fadds)
1183     {
1184     /* TODO */
1185     instr(fadd)(cpu, ic);
1186     }
1187     X(fsub)
1188     {
1189     struct ieee_float_value fra;
1190     struct ieee_float_value frb;
1191     double result = 0.0;
1192     int nan = 0, c;
1193    
1194 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1195 dpavlin 20
1196     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1197     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1198     if (fra.nan || frb.nan)
1199     nan = 1;
1200     else
1201     result = fra.f - frb.f;
1202     if (nan)
1203     c = 1;
1204     else {
1205     if (result < 0.0)
1206     c = 8;
1207     else if (result > 0.0)
1208     c = 4;
1209     else
1210     c = 2;
1211     }
1212     /* TODO: Signaling vs Quiet NaN */
1213     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1214     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1215    
1216     (*(uint64_t *)ic->arg[2]) =
1217     ieee_store_float_value(result, IEEE_FMT_D, nan);
1218     }
1219     X(fsubs)
1220     {
1221     /* TODO */
1222     instr(fsub)(cpu, ic);
1223     }
1224     X(fdiv)
1225     {
1226     struct ieee_float_value fra;
1227     struct ieee_float_value frb;
1228     double result = 0.0;
1229     int nan = 0, c;
1230    
1231 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1232 dpavlin 20
1233     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1234     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1235     if (fra.nan || frb.nan || frb.f == 0)
1236     nan = 1;
1237     else
1238     result = fra.f / frb.f;
1239     if (nan)
1240     c = 1;
1241     else {
1242     if (result < 0.0)
1243     c = 8;
1244     else if (result > 0.0)
1245     c = 4;
1246     else
1247     c = 2;
1248     }
1249     /* TODO: Signaling vs Quiet NaN */
1250     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1251     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1252    
1253     (*(uint64_t *)ic->arg[2]) =
1254     ieee_store_float_value(result, IEEE_FMT_D, nan);
1255     }
1256     X(fdivs)
1257     {
1258     /* TODO */
1259     instr(fdiv)(cpu, ic);
1260     }
1261    
1262    
1263     /*
1264 dpavlin 14 * llsc: Load-linked and store conditional
1265     *
1266     * arg[0] = copy of the instruction word.
1267     */
1268     X(llsc)
1269     {
1270     int iw = ic->arg[0], len = 4, load = 0, xo = (iw >> 1) & 1023;
1271     int i, rc = iw & 1, rt, ra, rb;
1272     uint64_t addr = 0, value;
1273     unsigned char d[8];
1274    
1275     switch (xo) {
1276     case PPC_31_LDARX:
1277     len = 8;
1278     case PPC_31_LWARX:
1279     load = 1;
1280     break;
1281     case PPC_31_STDCX_DOT:
1282     len = 8;
1283     case PPC_31_STWCX_DOT:
1284     break;
1285     }
1286    
1287     rt = (iw >> 21) & 31;
1288     ra = (iw >> 16) & 31;
1289     rb = (iw >> 11) & 31;
1290    
1291     if (ra != 0)
1292     addr = cpu->cd.ppc.gpr[ra];
1293     addr += cpu->cd.ppc.gpr[rb];
1294    
1295     if (load) {
1296     if (rc) {
1297     fatal("ll: rc-bit set?\n");
1298     exit(1);
1299     }
1300     if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1301     MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1302     fatal("ll: error: TODO\n");
1303     exit(1);
1304     }
1305    
1306     value = 0;
1307     for (i=0; i<len; i++) {
1308     value <<= 8;
1309     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1310     value |= d[i];
1311     else
1312     value |= d[len - 1 - i];
1313     }
1314    
1315     cpu->cd.ppc.gpr[rt] = value;
1316     cpu->cd.ppc.ll_addr = addr;
1317     cpu->cd.ppc.ll_bit = 1;
1318     } else {
1319 dpavlin 20 uint32_t old_so = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_SO;
1320 dpavlin 14 if (!rc) {
1321     fatal("sc: rc-bit not set?\n");
1322     exit(1);
1323     }
1324    
1325     value = cpu->cd.ppc.gpr[rt];
1326    
1327     /* "If the store is performed, bits 0-2 of Condition
1328     Register Field 0 are set to 0b001, otherwise, they are
1329     set to 0b000. The SO bit of the XER is copied to to bit
1330     4 of Condition Register Field 0. */
1331     if (!cpu->cd.ppc.ll_bit || cpu->cd.ppc.ll_addr != addr) {
1332     cpu->cd.ppc.cr &= 0x0fffffff;
1333     if (old_so)
1334     cpu->cd.ppc.cr |= 0x10000000;
1335     cpu->cd.ppc.ll_bit = 0;
1336     return;
1337     }
1338    
1339     for (i=0; i<len; i++) {
1340     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1341     d[len - 1 - i] = value >> (8*i);
1342     else
1343     d[i] = value >> (8*i);
1344     }
1345    
1346     if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1347     MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1348     fatal("sc: error: TODO\n");
1349     exit(1);
1350     }
1351    
1352     cpu->cd.ppc.cr &= 0x0fffffff;
1353     cpu->cd.ppc.cr |= 0x20000000; /* success! */
1354     if (old_so)
1355     cpu->cd.ppc.cr |= 0x10000000;
1356    
1357     /* Clear _all_ CPUs' ll_bits: */
1358     for (i=0; i<cpu->machine->ncpus; i++)
1359     cpu->machine->cpus[i]->cd.ppc.ll_bit = 0;
1360     }
1361     }
1362    
1363    
1364     /*
1365 dpavlin 22 * mtsr, mtsrin: Move To Segment Register [Indirect]
1366 dpavlin 14 *
1367 dpavlin 20 * arg[0] = sr number, or for indirect mode: ptr to rb
1368 dpavlin 14 * arg[1] = ptr to rt
1369 dpavlin 22 *
1370     * TODO: These only work for 32-bit mode!
1371 dpavlin 14 */
1372     X(mtsr)
1373     {
1374 dpavlin 22 int sr_num = ic->arg[0];
1375     uint32_t old = cpu->cd.ppc.sr[sr_num];
1376     cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1377 dpavlin 20
1378 dpavlin 22 if (cpu->cd.ppc.sr[sr_num] != old)
1379     cpu->invalidate_translation_caches(cpu, ic->arg[0] << 28,
1380     INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1381 dpavlin 14 }
1382 dpavlin 20 X(mtsrin)
1383     {
1384 dpavlin 22 int sr_num = reg(ic->arg[0]) >> 28;
1385     uint32_t old = cpu->cd.ppc.sr[sr_num];
1386 dpavlin 20 cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1387 dpavlin 14
1388 dpavlin 22 if (cpu->cd.ppc.sr[sr_num] != old)
1389     cpu->invalidate_translation_caches(cpu, sr_num << 28,
1390     INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1391 dpavlin 20 }
1392 dpavlin 14
1393 dpavlin 20
1394 dpavlin 14 /*
1395     * mfsrin, mtsrin: Move From/To Segment Register Indirect
1396     *
1397 dpavlin 20 * arg[0] = sr number, or for indirect mode: ptr to rb
1398 dpavlin 14 * arg[1] = ptr to rt
1399     */
1400 dpavlin 20 X(mfsr)
1401 dpavlin 14 {
1402     /* TODO: This only works for 32-bit mode */
1403 dpavlin 20 reg(ic->arg[1]) = cpu->cd.ppc.sr[ic->arg[0]];
1404 dpavlin 14 }
1405 dpavlin 20 X(mfsrin)
1406 dpavlin 14 {
1407     /* TODO: This only works for 32-bit mode */
1408     uint32_t sr_num = reg(ic->arg[0]) >> 28;
1409 dpavlin 20 reg(ic->arg[1]) = cpu->cd.ppc.sr[sr_num];
1410 dpavlin 14 }
1411    
1412    
1413     /*
1414 dpavlin 24 * rldicl:
1415     *
1416     * arg[0] = copy of the instruction word
1417     */
1418     X(rldicl)
1419     {
1420     int rs = (ic->arg[0] >> 21) & 31;
1421     int ra = (ic->arg[0] >> 16) & 31;
1422     int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4);
1423     int mb = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20);
1424     int rc = ic->arg[0] & 1;
1425     uint64_t tmp = cpu->cd.ppc.gpr[rs], tmp2;
1426     /* TODO: Fix this, its performance is awful: */
1427     while (sh-- != 0) {
1428     int b = (tmp >> 63) & 1;
1429     tmp = (tmp << 1) | b;
1430     }
1431     tmp2 = 0;
1432     while (mb <= 63) {
1433     tmp |= ((uint64_t)1 << (63-mb));
1434     mb ++;
1435     }
1436     cpu->cd.ppc.gpr[ra] = tmp & tmp2;
1437     if (rc)
1438     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1439     }
1440    
1441    
1442     /*
1443 dpavlin 14 * rldicr:
1444     *
1445     * arg[0] = copy of the instruction word
1446     */
1447     X(rldicr)
1448     {
1449     int rs = (ic->arg[0] >> 21) & 31;
1450     int ra = (ic->arg[0] >> 16) & 31;
1451     int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4);
1452     int me = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20);
1453     int rc = ic->arg[0] & 1;
1454     uint64_t tmp = cpu->cd.ppc.gpr[rs];
1455     /* TODO: Fix this, its performance is awful: */
1456     while (sh-- != 0) {
1457     int b = (tmp >> 63) & 1;
1458     tmp = (tmp << 1) | b;
1459     }
1460     while (me++ < 63)
1461     tmp &= ~((uint64_t)1 << (63-me));
1462     cpu->cd.ppc.gpr[ra] = tmp;
1463     if (rc)
1464     update_cr0(cpu, tmp);
1465     }
1466    
1467    
1468     /*
1469 dpavlin 24 * rldimi:
1470     *
1471     * arg[0] = copy of the instruction word
1472     */
1473     X(rldimi)
1474     {
1475     uint32_t iw = ic->arg[0];
1476     int rs = (iw >> 21) & 31, ra = (iw >> 16) & 31;
1477     int sh = ((iw >> 11) & 31) | ((iw & 2) << 4);
1478     int mb = ((iw >> 6) & 31) | (iw & 0x20);
1479     int rc = ic->arg[0] & 1;
1480     int m;
1481     uint64_t tmp, s = cpu->cd.ppc.gpr[rs];
1482     /* TODO: Fix this, its performance is awful: */
1483     while (sh-- != 0) {
1484     int b = (s >> 63) & 1;
1485     s = (s << 1) | b;
1486     }
1487     m = mb; tmp = 0;
1488     do {
1489     tmp |= ((uint64_t)1 << (63-m));
1490     m ++;
1491     } while (m != 63 - sh);
1492     cpu->cd.ppc.gpr[ra] &= ~tmp;
1493     cpu->cd.ppc.gpr[ra] |= (tmp & s);
1494     if (rc)
1495     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1496     }
1497    
1498    
1499     /*
1500 dpavlin 20 * rlwnm:
1501     *
1502     * arg[0] = ptr to ra
1503     * arg[1] = mask
1504     * arg[2] = copy of the instruction word
1505     */
1506     X(rlwnm)
1507     {
1508     uint32_t tmp, iword = ic->arg[2];
1509     int rs = (iword >> 21) & 31;
1510     int rb = (iword >> 11) & 31;
1511     int sh = cpu->cd.ppc.gpr[rb] & 0x1f;
1512     tmp = (uint32_t)cpu->cd.ppc.gpr[rs];
1513     tmp = (tmp << sh) | (tmp >> (32-sh));
1514     tmp &= (uint32_t)ic->arg[1];
1515     reg(ic->arg[0]) = tmp;
1516     }
1517     DOT0(rlwnm)
1518    
1519    
1520     /*
1521 dpavlin 14 * rlwinm:
1522     *
1523 dpavlin 20 * arg[0] = ptr to ra
1524     * arg[1] = mask
1525 dpavlin 14 * arg[2] = copy of the instruction word
1526     */
1527     X(rlwinm)
1528     {
1529 dpavlin 20 uint32_t tmp, iword = ic->arg[2];
1530     int rs = (iword >> 21) & 31;
1531     int sh = (iword >> 11) & 31;
1532     tmp = (uint32_t)cpu->cd.ppc.gpr[rs];
1533     tmp = (tmp << sh) | (tmp >> (32-sh));
1534     tmp &= (uint32_t)ic->arg[1];
1535     reg(ic->arg[0]) = tmp;
1536 dpavlin 14 }
1537 dpavlin 20 DOT0(rlwinm)
1538 dpavlin 14
1539    
1540     /*
1541     * rlwimi:
1542     *
1543     * arg[0] = ptr to rs
1544     * arg[1] = ptr to ra
1545     * arg[2] = copy of the instruction word
1546     */
1547     X(rlwimi)
1548     {
1549     MODE_uint_t tmp = reg(ic->arg[0]), ra = reg(ic->arg[1]);
1550     uint32_t iword = ic->arg[2];
1551 dpavlin 20 int sh = (iword >> 11) & 31;
1552     int mb = (iword >> 6) & 31;
1553     int me = (iword >> 1) & 31;
1554     int rc = iword & 1;
1555 dpavlin 14
1556 dpavlin 20 tmp = (tmp << sh) | (tmp >> (32-sh));
1557 dpavlin 14
1558     for (;;) {
1559     uint64_t mask;
1560     mask = (uint64_t)1 << (31-mb);
1561     ra &= ~mask;
1562     ra |= (tmp & mask);
1563     if (mb == me)
1564     break;
1565     mb ++;
1566     if (mb == 32)
1567     mb = 0;
1568     }
1569     reg(ic->arg[1]) = ra;
1570     if (rc)
1571     update_cr0(cpu, ra);
1572     }
1573    
1574    
1575     /*
1576     * srawi:
1577     *
1578     * arg[0] = ptr to rs
1579     * arg[1] = ptr to ra
1580     * arg[2] = sh (shift amount)
1581     */
1582     X(srawi)
1583     {
1584     uint32_t tmp = reg(ic->arg[0]);
1585     int i = 0, j = 0, sh = ic->arg[2];
1586    
1587 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
1588 dpavlin 14 if (tmp & 0x80000000)
1589     i = 1;
1590     while (sh-- > 0) {
1591     if (tmp & 1)
1592     j ++;
1593     tmp >>= 1;
1594     if (tmp & 0x40000000)
1595     tmp |= 0x80000000;
1596     }
1597     if (i && j>0)
1598 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
1599 dpavlin 14 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
1600     }
1601 dpavlin 20 DOT1(srawi)
1602 dpavlin 14
1603    
1604     /*
1605     * mcrf: Move inside condition register
1606     *
1607 dpavlin 20 * arg[0] = 28-4*bf, arg[1] = 28-4*bfa
1608 dpavlin 14 */
1609     X(mcrf)
1610     {
1611 dpavlin 20 int bf_shift = ic->arg[0], bfa_shift = ic->arg[1];
1612     uint32_t tmp = (cpu->cd.ppc.cr >> bfa_shift) & 0xf;
1613     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
1614     cpu->cd.ppc.cr |= (tmp << bf_shift);
1615 dpavlin 14 }
1616    
1617    
1618     /*
1619     * crand, crxor etc: Condition Register operations
1620     *
1621     * arg[0] = copy of the instruction word
1622     */
1623     X(crand) {
1624     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1625     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1626     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1627     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1628     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1629     if (ba & bb)
1630     cpu->cd.ppc.cr |= (1 << (31-bt));
1631     }
1632     X(crandc) {
1633     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1634     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1635     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1636     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1637     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1638     if (!(ba & bb))
1639     cpu->cd.ppc.cr |= (1 << (31-bt));
1640     }
1641     X(creqv) {
1642     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1643     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1644     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1645     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1646     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1647     if (!(ba ^ bb))
1648     cpu->cd.ppc.cr |= (1 << (31-bt));
1649     }
1650     X(cror) {
1651     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1652     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1653     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1654     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1655     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1656     if (ba | bb)
1657     cpu->cd.ppc.cr |= (1 << (31-bt));
1658     }
1659 dpavlin 22 X(crorc) {
1660     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1661     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1662     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1663     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1664     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1665     if (!(ba | bb))
1666     cpu->cd.ppc.cr |= (1 << (31-bt));
1667     }
1668 dpavlin 20 X(crnor) {
1669     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1670     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1671     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1672     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1673     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1674     if (!(ba | bb))
1675     cpu->cd.ppc.cr |= (1 << (31-bt));
1676     }
1677 dpavlin 14 X(crxor) {
1678     uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1679     int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1680     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1681     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1682     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1683     if (ba ^ bb)
1684     cpu->cd.ppc.cr |= (1 << (31-bt));
1685     }
1686    
1687    
1688     /*
1689 dpavlin 20 * mfspr: Move from SPR
1690 dpavlin 14 *
1691     * arg[0] = pointer to destination register
1692 dpavlin 20 * arg[1] = pointer to source SPR
1693 dpavlin 14 */
1694 dpavlin 20 X(mfspr) {
1695 dpavlin 22 /* TODO: Check permission */
1696 dpavlin 20 reg(ic->arg[0]) = reg(ic->arg[1]);
1697     }
1698     X(mfspr_pmc1) {
1699     /*
1700     * TODO: This is a temporary hack to make NetBSD/ppc detect
1701     * a CPU of the correct (emulated) speed.
1702     */
1703     reg(ic->arg[0]) = cpu->machine->emulated_hz / 10;
1704     }
1705     X(mftb) {
1706     /* NOTE/TODO: This increments the time base (slowly) if it
1707     is being polled. */
1708     if (++cpu->cd.ppc.spr[SPR_TBL] == 0)
1709     cpu->cd.ppc.spr[SPR_TBU] ++;
1710     reg(ic->arg[0]) = cpu->cd.ppc.spr[SPR_TBL];
1711     }
1712     X(mftbu) {
1713     reg(ic->arg[0]) = cpu->cd.ppc.spr[SPR_TBU];
1714     }
1715 dpavlin 14
1716    
1717     /*
1718 dpavlin 20 * mtspr: Move to SPR.
1719 dpavlin 14 *
1720     * arg[0] = pointer to source register
1721 dpavlin 20 * arg[1] = pointer to the SPR
1722 dpavlin 14 */
1723 dpavlin 20 X(mtspr) {
1724 dpavlin 22 /* TODO: Check permission */
1725 dpavlin 20 reg(ic->arg[1]) = reg(ic->arg[0]);
1726     }
1727 dpavlin 22 X(mtlr) {
1728     cpu->cd.ppc.spr[SPR_LR] = reg(ic->arg[0]);
1729     }
1730     X(mtctr) {
1731     cpu->cd.ppc.spr[SPR_CTR] = reg(ic->arg[0]);
1732     }
1733 dpavlin 14
1734    
1735     /*
1736 dpavlin 24 * rfi[d]: Return from Interrupt
1737 dpavlin 14 */
1738     X(rfi)
1739     {
1740     uint64_t tmp;
1741    
1742 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
1743 dpavlin 14 tmp &= ~0xffff;
1744 dpavlin 20 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & 0xffff);
1745     reg_access_msr(cpu, &tmp, 1, 0);
1746 dpavlin 14
1747 dpavlin 20 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1748 dpavlin 22 quick_pc_to_pointers(cpu);
1749 dpavlin 14 }
1750 dpavlin 24 X(rfid)
1751     {
1752     uint64_t tmp, mask = 0x800000000000ff73ULL;
1753 dpavlin 14
1754 dpavlin 24 reg_access_msr(cpu, &tmp, 0, 0);
1755     tmp &= ~mask;
1756     tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & mask);
1757     reg_access_msr(cpu, &tmp, 1, 0);
1758 dpavlin 14
1759 dpavlin 24 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1760     if (!(tmp & PPC_MSR_SF))
1761     cpu->pc = (uint32_t)cpu->pc;
1762     quick_pc_to_pointers(cpu);
1763     }
1764    
1765    
1766 dpavlin 14 /*
1767     * mfcr: Move From Condition Register
1768     *
1769     * arg[0] = pointer to destination register
1770     */
1771     X(mfcr)
1772     {
1773     reg(ic->arg[0]) = cpu->cd.ppc.cr;
1774     }
1775    
1776    
1777     /*
1778     * mfmsr: Move From MSR
1779     *
1780     * arg[0] = pointer to destination register
1781     */
1782     X(mfmsr)
1783     {
1784 dpavlin 20 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0, 0);
1785 dpavlin 14 }
1786    
1787    
1788     /*
1789     * mtmsr: Move To MSR
1790     *
1791     * arg[0] = pointer to source register
1792 dpavlin 24 * arg[1] = page offset of the next instruction
1793     * arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd)
1794 dpavlin 14 */
1795     X(mtmsr)
1796     {
1797 dpavlin 22 MODE_uint_t old_pc;
1798 dpavlin 24 uint64_t x = reg(ic->arg[0]);
1799 dpavlin 22
1800     /* TODO: check permission! */
1801    
1802 dpavlin 20 /* Synchronize the PC (pointing to _after_ this instruction) */
1803     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1804 dpavlin 22 old_pc = cpu->pc;
1805 dpavlin 20
1806 dpavlin 24 if (!ic->arg[2]) {
1807     uint64_t y;
1808     reg_access_msr(cpu, &y, 0, 0);
1809     x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL);
1810     }
1811 dpavlin 22
1812 dpavlin 24 reg_access_msr(cpu, &x, 1, 1);
1813    
1814 dpavlin 22 /*
1815     * Super-ugly hack: If the pc wasn't changed (i.e. if there was no
1816     * exception while accessing the msr), then we _decrease_ the PC by 4
1817     * again. This is because the next ic could be an end_of_page.
1818     */
1819     if ((MODE_uint_t)cpu->pc == old_pc)
1820     cpu->pc -= 4;
1821 dpavlin 14 }
1822    
1823    
1824     /*
1825 dpavlin 22 * wrteei: Write EE immediate (on PPC405GP)
1826     *
1827     * arg[0] = either 0 or 0x8000
1828     */
1829     X(wrteei)
1830     {
1831     /* TODO: check permission! */
1832     uint64_t x;
1833    
1834     /* Synchronize the PC (pointing to _after_ this instruction) */
1835     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1836    
1837     reg_access_msr(cpu, &x, 0, 0);
1838     x = (x & ~0x8000) | ic->arg[0];
1839     reg_access_msr(cpu, &x, 1, 1);
1840     }
1841    
1842    
1843     /*
1844 dpavlin 14 * mtcrf: Move To Condition Register Fields
1845     *
1846     * arg[0] = pointer to source register
1847     */
1848     X(mtcrf)
1849     {
1850     cpu->cd.ppc.cr &= ~ic->arg[1];
1851     cpu->cd.ppc.cr |= (reg(ic->arg[0]) & ic->arg[1]);
1852     }
1853    
1854    
1855     /*
1856     * mulli: Multiply Low Immediate.
1857     *
1858     * arg[0] = pointer to source register ra
1859     * arg[1] = int32_t immediate
1860     * arg[2] = pointer to destination register rt
1861     */
1862     X(mulli)
1863     {
1864 dpavlin 20 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * (int32_t)ic->arg[1]);
1865 dpavlin 14 }
1866    
1867    
1868     /*
1869     * Load/Store Multiple:
1870     *
1871     * arg[0] = rs (or rt for loads) NOTE: not a pointer
1872     * arg[1] = ptr to ra
1873     * arg[2] = int32_t immediate offset
1874     */
1875     X(lmw) {
1876     MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1877     unsigned char d[4];
1878 dpavlin 20 int rs = ic->arg[0];
1879 dpavlin 14
1880 dpavlin 20 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1881     / sizeof(struct ppc_instr_call);
1882     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1883     << PPC_INSTR_ALIGNMENT_SHIFT);
1884     cpu->pc |= (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1885    
1886 dpavlin 14 while (rs <= 31) {
1887     if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1888 dpavlin 20 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1889     /* exception */
1890     return;
1891     }
1892 dpavlin 14
1893     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1894     cpu->cd.ppc.gpr[rs] = (d[0] << 24) + (d[1] << 16)
1895     + (d[2] << 8) + d[3];
1896     else
1897     cpu->cd.ppc.gpr[rs] = (d[3] << 24) + (d[2] << 16)
1898     + (d[1] << 8) + d[0];
1899    
1900     rs ++;
1901     addr += sizeof(uint32_t);
1902     }
1903     }
1904     X(stmw) {
1905     MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1906     unsigned char d[4];
1907 dpavlin 20 int rs = ic->arg[0];
1908 dpavlin 14
1909 dpavlin 20 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1910     / sizeof(struct ppc_instr_call);
1911     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1912     << PPC_INSTR_ALIGNMENT_SHIFT);
1913     cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1914    
1915 dpavlin 14 while (rs <= 31) {
1916 dpavlin 20 uint32_t tmp = cpu->cd.ppc.gpr[rs];
1917 dpavlin 14 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1918     d[3] = tmp; d[2] = tmp >> 8;
1919     d[1] = tmp >> 16; d[0] = tmp >> 24;
1920     } else {
1921     d[0] = tmp; d[1] = tmp >> 8;
1922     d[2] = tmp >> 16; d[3] = tmp >> 24;
1923     }
1924     if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1925 dpavlin 20 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1926     /* exception */
1927     return;
1928 dpavlin 14 }
1929    
1930     rs ++;
1931     addr += sizeof(uint32_t);
1932     }
1933     }
1934    
1935    
1936     /*
1937 dpavlin 20 * Load/store string:
1938     *
1939     * arg[0] = rs (well, rt for lswi)
1940     * arg[1] = ptr to ra (or ptr to zero)
1941     * arg[2] = nb
1942     */
1943     X(lswi)
1944     {
1945     MODE_uint_t addr = reg(ic->arg[1]);
1946     int rt = ic->arg[0], nb = ic->arg[2];
1947     int sub = 0;
1948    
1949     int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1950     / sizeof(struct ppc_instr_call);
1951     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1952     << PPC_INSTR_ALIGNMENT_SHIFT);
1953     cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1954    
1955     while (nb > 0) {
1956     unsigned char d;
1957     if (cpu->memory_rw(cpu, cpu->mem, addr, &d, 1,
1958     MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1959     /* exception */
1960     return;
1961     }
1962    
1963     if (cpu->cd.ppc.mode == MODE_POWER && sub == 0)
1964     cpu->cd.ppc.gpr[rt] = 0;
1965     cpu->cd.ppc.gpr[rt] &= ~(0xff << (24-8*sub));
1966     cpu->cd.ppc.gpr[rt] |= (d << (24-8*sub));
1967     sub ++;
1968     if (sub == 4) {
1969     rt = (rt + 1) & 31;
1970     sub = 0;
1971     }
1972     addr ++;
1973     nb --;
1974     }
1975     }
1976     X(stswi)
1977     {
1978     MODE_uint_t addr = reg(ic->arg[1]);
1979     int rs = ic->arg[0], nb = ic->arg[2];
1980     uint32_t cur = cpu->cd.ppc.gpr[rs];
1981     int sub = 0;
1982    
1983     int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1984     / sizeof(struct ppc_instr_call);
1985     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1986     << PPC_INSTR_ALIGNMENT_SHIFT);
1987     cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1988    
1989     while (nb > 0) {
1990     unsigned char d = cur >> 24;
1991     if (cpu->memory_rw(cpu, cpu->mem, addr, &d, 1,
1992     MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1993     /* exception */
1994     return;
1995     }
1996     cur <<= 8;
1997     sub ++;
1998     if (sub == 4) {
1999     rs = (rs + 1) & 31;
2000     sub = 0;
2001     cur = cpu->cd.ppc.gpr[rs];
2002     }
2003     addr ++;
2004     nb --;
2005     }
2006     }
2007    
2008    
2009     /*
2010 dpavlin 14 * Shifts, and, or, xor, etc.
2011     *
2012     * arg[0] = pointer to source register rs
2013     * arg[1] = pointer to source register rb
2014     * arg[2] = pointer to destination register ra
2015     */
2016     X(extsb) {
2017     #ifdef MODE32
2018     reg(ic->arg[2]) = (int32_t)(int8_t)reg(ic->arg[0]);
2019     #else
2020     reg(ic->arg[2]) = (int64_t)(int8_t)reg(ic->arg[0]);
2021     #endif
2022     }
2023 dpavlin 20 DOT2(extsb)
2024 dpavlin 14 X(extsh) {
2025     #ifdef MODE32
2026     reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]);
2027     #else
2028     reg(ic->arg[2]) = (int64_t)(int16_t)reg(ic->arg[0]);
2029     #endif
2030     }
2031 dpavlin 20 DOT2(extsh)
2032 dpavlin 14 X(extsw) {
2033     #ifdef MODE32
2034 dpavlin 24 fatal("TODO: extsw: invalid instruction\n");
2035 dpavlin 14 #else
2036     reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);
2037     #endif
2038     }
2039 dpavlin 20 DOT2(extsw)
2040 dpavlin 14 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2041 dpavlin 20 << (reg(ic->arg[1]) & 31); }
2042     DOT2(slw)
2043 dpavlin 24 X(sld) {int sa = reg(ic->arg[1]) & 127;
2044     if (sa >= 64) reg(ic->arg[2]) = 0;
2045     else reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (sa & 63); }
2046     DOT2(sld)
2047 dpavlin 20 X(sraw)
2048     {
2049     uint32_t tmp = reg(ic->arg[0]);
2050     int i = 0, j = 0, sh = reg(ic->arg[1]) & 31;
2051    
2052     cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2053     if (tmp & 0x80000000)
2054     i = 1;
2055     while (sh-- > 0) {
2056     if (tmp & 1)
2057     j ++;
2058     tmp >>= 1;
2059     if (tmp & 0x40000000)
2060     tmp |= 0x80000000;
2061     }
2062     if (i && j>0)
2063     cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2064     reg(ic->arg[2]) = (int64_t)(int32_t)tmp;
2065     }
2066     DOT2(sraw)
2067 dpavlin 14 X(srw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2068 dpavlin 20 >> (reg(ic->arg[1]) & 31); }
2069     DOT2(srw)
2070 dpavlin 14 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
2071 dpavlin 20 DOT2(and)
2072 dpavlin 14 X(nand) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) & reg(ic->arg[1])); }
2073 dpavlin 20 DOT2(nand)
2074 dpavlin 14 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
2075 dpavlin 20 DOT2(andc)
2076 dpavlin 14 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
2077 dpavlin 20 DOT2(nor)
2078 dpavlin 22 X(mr) { reg(ic->arg[2]) = reg(ic->arg[1]); }
2079 dpavlin 14 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
2080 dpavlin 20 DOT2(or)
2081 dpavlin 14 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
2082 dpavlin 20 DOT2(orc)
2083 dpavlin 14 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
2084 dpavlin 20 DOT2(xor)
2085 dpavlin 24 X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); }
2086     DOT2(eqv)
2087 dpavlin 14
2088    
2089     /*
2090     * neg:
2091     *
2092     * arg[0] = pointer to source register ra
2093     * arg[1] = pointer to destination register rt
2094     */
2095     X(neg) { reg(ic->arg[1]) = -reg(ic->arg[0]); }
2096 dpavlin 20 DOT1(neg)
2097 dpavlin 14
2098    
2099     /*
2100     * mullw, mulhw[u], divw[u]:
2101     *
2102     * arg[0] = pointer to source register ra
2103     * arg[1] = pointer to source register rb
2104     * arg[2] = pointer to destination register rt
2105     */
2106     X(mullw)
2107     {
2108     int32_t sum = (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]);
2109     reg(ic->arg[2]) = (int32_t)sum;
2110     }
2111 dpavlin 20 DOT2(mullw)
2112 dpavlin 14 X(mulhw)
2113     {
2114     int64_t sum;
2115     sum = (int64_t)(int32_t)reg(ic->arg[0])
2116     * (int64_t)(int32_t)reg(ic->arg[1]);
2117     reg(ic->arg[2]) = sum >> 32;
2118     }
2119 dpavlin 20 DOT2(mulhw)
2120 dpavlin 14 X(mulhwu)
2121     {
2122     uint64_t sum;
2123     sum = (uint64_t)(uint32_t)reg(ic->arg[0])
2124     * (uint64_t)(uint32_t)reg(ic->arg[1]);
2125     reg(ic->arg[2]) = sum >> 32;
2126     }
2127 dpavlin 20 DOT2(mulhwu)
2128 dpavlin 14 X(divw)
2129     {
2130     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
2131     int32_t sum;
2132     if (b == 0)
2133     sum = 0;
2134     else
2135     sum = a / b;
2136     reg(ic->arg[2]) = (uint32_t)sum;
2137     }
2138 dpavlin 20 DOT2(divw)
2139 dpavlin 14 X(divwu)
2140     {
2141     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
2142     uint32_t sum;
2143     if (b == 0)
2144     sum = 0;
2145     else
2146     sum = a / b;
2147     reg(ic->arg[2]) = sum;
2148     }
2149 dpavlin 20 DOT2(divwu)
2150 dpavlin 14
2151    
2152     /*
2153     * add: Add.
2154     *
2155     * arg[0] = pointer to source register ra
2156     * arg[1] = pointer to source register rb
2157     * arg[2] = pointer to destination register rt
2158     */
2159     X(add) { reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
2160 dpavlin 20 DOT2(add)
2161 dpavlin 14
2162    
2163     /*
2164     * addc: Add carrying.
2165     *
2166     * arg[0] = pointer to source register ra
2167     * arg[1] = pointer to source register rb
2168     * arg[2] = pointer to destination register rt
2169     */
2170     X(addc)
2171     {
2172     /* TODO: this only works in 32-bit mode */
2173     uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2174     uint64_t tmp2 = tmp;
2175 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2176 dpavlin 14 tmp += (uint32_t)reg(ic->arg[1]);
2177     if ((tmp >> 32) != (tmp2 >> 32))
2178 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2179 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2180     }
2181    
2182    
2183     /*
2184     * adde: Add extended, etc.
2185     *
2186     * arg[0] = pointer to source register ra
2187     * arg[1] = pointer to source register rb
2188     * arg[2] = pointer to destination register rt
2189     */
2190     X(adde)
2191     {
2192     /* TODO: this only works in 32-bit mode */
2193 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2194 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2195     uint64_t tmp2 = tmp;
2196 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2197 dpavlin 14 tmp += (uint32_t)reg(ic->arg[1]);
2198     if (old_ca)
2199     tmp ++;
2200     if ((tmp >> 32) != (tmp2 >> 32))
2201 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2202 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2203     }
2204 dpavlin 20 DOT2(adde)
2205 dpavlin 14 X(addme)
2206     {
2207     /* TODO: this only works in 32-bit mode */
2208 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2209 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2210     uint64_t tmp2 = tmp;
2211 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2212 dpavlin 14 if (old_ca)
2213     tmp ++;
2214     tmp += 0xffffffffULL;
2215     if ((tmp >> 32) != (tmp2 >> 32))
2216 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2217 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2218     }
2219 dpavlin 20 DOT2(addme)
2220 dpavlin 14 X(addze)
2221     {
2222     /* TODO: this only works in 32-bit mode */
2223 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2224 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2225     uint64_t tmp2 = tmp;
2226 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2227 dpavlin 14 if (old_ca)
2228     tmp ++;
2229     if ((tmp >> 32) != (tmp2 >> 32))
2230 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2231 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2232     }
2233 dpavlin 20 DOT2(addze)
2234 dpavlin 14
2235    
2236     /*
2237     * subf: Subf, etc.
2238     *
2239     * arg[0] = pointer to source register ra
2240     * arg[1] = pointer to source register rb
2241     * arg[2] = pointer to destination register rt
2242     */
2243 dpavlin 20 X(subf)
2244     {
2245     reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2246     }
2247     DOT2(subf)
2248 dpavlin 14 X(subfc)
2249     {
2250 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2251 dpavlin 14 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2252 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2253 dpavlin 14 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2254     }
2255 dpavlin 20 DOT2(subfc)
2256 dpavlin 14 X(subfe)
2257     {
2258 dpavlin 20 int old_ca = (cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA)? 1 : 0;
2259     cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2260 dpavlin 14 if (reg(ic->arg[1]) == reg(ic->arg[0])) {
2261     if (old_ca)
2262 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2263 dpavlin 14 } else if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2264 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2265 dpavlin 14
2266     /*
2267     * TODO: The register value calculation should be correct,
2268     * but the CA bit calculation above is probably not.
2269     */
2270    
2271     reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]) - (old_ca? 0 : 1);
2272     }
2273 dpavlin 20 DOT2(subfe)
2274     X(subfme)
2275     {
2276     int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2277     uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2278     tmp += 0xffffffffULL;
2279     cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2280     if (old_ca)
2281     tmp ++;
2282     if ((tmp >> 32) != 0)
2283     cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2284     reg(ic->arg[2]) = (uint32_t)tmp;
2285     }
2286     DOT2(subfme)
2287 dpavlin 14 X(subfze)
2288     {
2289 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2290 dpavlin 14 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2291     uint64_t tmp2 = tmp;
2292 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2293 dpavlin 14 if (old_ca)
2294     tmp ++;
2295     if ((tmp >> 32) != (tmp2 >> 32))
2296 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2297 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2298     }
2299 dpavlin 20 DOT2(subfze)
2300 dpavlin 14
2301    
2302     /*
2303     * ori, xori etc.:
2304     *
2305     * arg[0] = pointer to source uint64_t
2306     * arg[1] = immediate value (uint32_t or larger)
2307     * arg[2] = pointer to destination uint64_t
2308     */
2309     X(ori) { reg(ic->arg[2]) = reg(ic->arg[0]) | (uint32_t)ic->arg[1]; }
2310     X(xori) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[1]; }
2311    
2312    
2313 dpavlin 20 #include "tmp_ppc_loadstore.c"
2314    
2315    
2316 dpavlin 14 /*
2317 dpavlin 20 * lfs, stfs: Load/Store Floating-point Single precision
2318     */
2319     X(lfs)
2320     {
2321 dpavlin 22 /* Sync. PC in case of an exception, and remember it: */
2322 dpavlin 20 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2323     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2324 dpavlin 22 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2325     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2326 dpavlin 20 if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2327     ppc_exception(cpu, PPC_EXCEPTION_FPU);
2328     return;
2329     }
2330    
2331     /* Perform a 32-bit load: */
2332     #ifdef MODE32
2333     ppc32_loadstore
2334     #else
2335     ppc_loadstore
2336     #endif
2337     [2 + 4 + 8](cpu, ic);
2338    
2339     if (old_pc == cpu->pc) {
2340     /* The load succeeded. Let's convert the value: */
2341     struct ieee_float_value val;
2342     (*(uint64_t *)ic->arg[0]) &= 0xffffffff;
2343     ieee_interpret_float_value(*(uint64_t *)ic->arg[0],
2344     &val, IEEE_FMT_S);
2345     (*(uint64_t *)ic->arg[0]) =
2346     ieee_store_float_value(val.f, IEEE_FMT_D, val.nan);
2347     }
2348     }
2349     X(lfsx)
2350     {
2351 dpavlin 22 /* Sync. PC in case of an exception, and remember it: */
2352 dpavlin 20 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2353     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2354 dpavlin 22 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2355     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2356 dpavlin 20 if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2357     ppc_exception(cpu, PPC_EXCEPTION_FPU);
2358     return;
2359     }
2360    
2361     /* Perform a 32-bit load: */
2362     #ifdef MODE32
2363     ppc32_loadstore_indexed
2364     #else
2365     ppc_loadstore_indexed
2366     #endif
2367     [2 + 4 + 8](cpu, ic);
2368    
2369     if (old_pc == cpu->pc) {
2370     /* The load succeeded. Let's convert the value: */
2371     struct ieee_float_value val;
2372     (*(uint64_t *)ic->arg[0]) &= 0xffffffff;
2373     ieee_interpret_float_value(*(uint64_t *)ic->arg[0],
2374     &val, IEEE_FMT_S);
2375     (*(uint64_t *)ic->arg[0]) =
2376     ieee_store_float_value(val.f, IEEE_FMT_D, val.nan);
2377     }
2378     }
2379     X(lfd)
2380     {
2381 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2382 dpavlin 20
2383     /* Perform a 64-bit load: */
2384     #ifdef MODE32
2385     ppc32_loadstore
2386     #else
2387     ppc_loadstore
2388     #endif
2389     [3 + 4 + 8](cpu, ic);
2390     }
2391     X(lfdx)
2392     {
2393 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2394    
2395 dpavlin 20 /* Perform a 64-bit load: */
2396     #ifdef MODE32
2397     ppc32_loadstore_indexed
2398     #else
2399     ppc_loadstore_indexed
2400     #endif
2401     [3 + 4 + 8](cpu, ic);
2402     }
2403     X(stfs)
2404     {
2405     uint64_t *old_arg0 = (void *)ic->arg[0];
2406     struct ieee_float_value val;
2407     uint64_t tmp_val;
2408    
2409 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2410 dpavlin 20
2411     ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2412     tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
2413    
2414     ic->arg[0] = (size_t)&tmp_val;
2415    
2416     /* Perform a 32-bit store: */
2417     #ifdef MODE32
2418     ppc32_loadstore
2419     #else
2420     ppc_loadstore
2421     #endif
2422     [2 + 4](cpu, ic);
2423    
2424     ic->arg[0] = (size_t)old_arg0;
2425     }
2426     X(stfsx)
2427     {
2428     uint64_t *old_arg0 = (void *)ic->arg[0];
2429     struct ieee_float_value val;
2430     uint64_t tmp_val;
2431    
2432 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2433 dpavlin 20
2434     ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2435     tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
2436    
2437     ic->arg[0] = (size_t)&tmp_val;
2438    
2439     /* Perform a 32-bit store: */
2440     #ifdef MODE32
2441     ppc32_loadstore_indexed
2442     #else
2443     ppc_loadstore_indexed
2444     #endif
2445     [2 + 4](cpu, ic);
2446    
2447     ic->arg[0] = (size_t)old_arg0;
2448     }
2449     X(stfd)
2450     {
2451 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2452    
2453 dpavlin 20 /* Perform a 64-bit store: */
2454     #ifdef MODE32
2455     ppc32_loadstore
2456     #else
2457     ppc_loadstore
2458     #endif
2459     [3 + 4](cpu, ic);
2460     }
2461     X(stfdx)
2462     {
2463 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2464    
2465 dpavlin 20 /* Perform a 64-bit store: */
2466     #ifdef MODE32
2467     ppc32_loadstore_indexed
2468     #else
2469     ppc_loadstore_indexed
2470     #endif
2471     [3 + 4](cpu, ic);
2472     }
2473    
2474    
2475     /*
2476     * tlbia: TLB invalidate all
2477     */
2478     X(tlbia)
2479     {
2480 dpavlin 24 fatal("[ tlbia ]\n");
2481 dpavlin 20 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2482     }
2483    
2484    
2485     /*
2486 dpavlin 14 * tlbie: TLB invalidate
2487     */
2488     X(tlbie)
2489     {
2490 dpavlin 24 /* fatal("[ tlbie ]\n"); */
2491 dpavlin 20 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2492     INVALIDATE_VADDR);
2493 dpavlin 14 }
2494    
2495    
2496     /*
2497 dpavlin 20 * sc: Syscall.
2498     */
2499     X(sc)
2500     {
2501     /* Synchronize the PC (pointing to _after_ this instruction) */
2502     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2503    
2504     ppc_exception(cpu, PPC_EXCEPTION_SC);
2505 dpavlin 22
2506     /* This caused an update to the PC register, so there is no need
2507     to worry about the next instruction being an end_of_page. */
2508 dpavlin 20 }
2509    
2510    
2511     /*
2512 dpavlin 14 * user_syscall: Userland syscall.
2513     *
2514     * arg[0] = syscall "level" (usually 0)
2515     */
2516     X(user_syscall)
2517     {
2518     useremul_syscall(cpu, ic->arg[0]);
2519 dpavlin 24
2520     if (!cpu->running) {
2521     cpu->running_translated = 0;
2522     cpu->n_translated_instrs --;
2523     cpu->cd.ppc.next_ic = &nothing_call;
2524     }
2525 dpavlin 14 }
2526    
2527    
2528     /*
2529     * openfirmware:
2530     */
2531     X(openfirmware)
2532     {
2533     of_emul(cpu);
2534 dpavlin 22 if (cpu->running == 0) {
2535     cpu->running_translated = 0;
2536     }
2537 dpavlin 20 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2538 dpavlin 14 if (cpu->machine->show_trace_tree)
2539     cpu_functioncall_trace_return(cpu);
2540 dpavlin 22 quick_pc_to_pointers(cpu);
2541 dpavlin 14 }
2542    
2543    
2544 dpavlin 20 /*
2545 dpavlin 22 * tlbsx_dot: TLB scan
2546     */
2547     X(tlbsx_dot)
2548     {
2549     /* TODO */
2550     cpu->cd.ppc.cr &= ~(0xf0000000);
2551     cpu->cd.ppc.cr |= 0x20000000;
2552     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2553     }
2554    
2555    
2556     /*
2557 dpavlin 20 * tlbli:
2558     */
2559     X(tlbli)
2560     {
2561 dpavlin 22 fatal("tlbli\n");
2562     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2563 dpavlin 20 }
2564 dpavlin 14
2565    
2566     /*
2567 dpavlin 20 * tlbld:
2568 dpavlin 14 */
2569 dpavlin 20 X(tlbld)
2570 dpavlin 14 {
2571 dpavlin 20 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2572     MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2573 dpavlin 14
2574 dpavlin 22 fatal("tlbld\n");
2575     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2576 dpavlin 14 }
2577    
2578    
2579     /*****************************************************************************/
2580    
2581    
2582     X(end_of_page)
2583     {
2584     /* Update the PC: (offset 0, but on the next page) */
2585 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2586     cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2587 dpavlin 14
2588     /* Find the new physical page and update the translation pointers: */
2589 dpavlin 22 quick_pc_to_pointers(cpu);
2590 dpavlin 14
2591     /* end_of_page doesn't count as an executed instruction: */
2592     cpu->n_translated_instrs --;
2593     }
2594    
2595    
2596     /*****************************************************************************/
2597    
2598    
2599     /*
2600     * ppc_instr_to_be_translated():
2601     *
2602 dpavlin 24 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2603 dpavlin 14 * valid data for the translated instruction, or a "nothing" instruction if
2604     * there was a translation failure. The newly translated instruction is then
2605     * executed.
2606     */
2607     X(to_be_translated)
2608     {
2609     uint64_t addr, low_pc, tmp_addr;
2610 dpavlin 20 uint32_t iword, mask;
2611 dpavlin 14 unsigned char *page;
2612     unsigned char ib[4];
2613     int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
2614     xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,
2615 dpavlin 20 bfa, fp, byterev, nb, mb, me;
2616 dpavlin 14 void (*samepage_function)(struct cpu *, struct ppc_instr_call *);
2617     void (*rc_f)(struct cpu *, struct ppc_instr_call *);
2618    
2619     /* Figure out the (virtual) address of the instruction: */
2620     low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
2621     / sizeof(struct ppc_instr_call);
2622     addr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
2623     << PPC_INSTR_ALIGNMENT_SHIFT);
2624     addr += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2625     cpu->pc = addr;
2626     addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
2627    
2628     /* Read the instruction word from memory: */
2629 dpavlin 24 #ifdef MODE32
2630     page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12];
2631     #else
2632     {
2633     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2634     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2635     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2636     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2637     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2638     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2639     DYNTRANS_L3N)) & mask3;
2640     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1];
2641     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2642     page = l3->host_load[x3];
2643     }
2644     #endif
2645 dpavlin 14
2646     if (page != NULL) {
2647     /* fatal("TRANSLATION HIT!\n"); */
2648     memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2649     } else {
2650     /* fatal("TRANSLATION MISS!\n"); */
2651     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2652     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2653 dpavlin 20 fatal("PPC to_be_translated(): "
2654 dpavlin 14 "read failed: TODO\n");
2655 dpavlin 20 exit(1);
2656     /* goto bad; */
2657 dpavlin 14 }
2658     }
2659    
2660     iword = *((uint32_t *)&ib[0]);
2661 dpavlin 22 iword = BE32_TO_HOST(iword);
2662 dpavlin 14
2663    
2664     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2665     #include "cpu_dyntrans.c"
2666     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2667    
2668    
2669     /*
2670     * Translate the instruction:
2671     */
2672    
2673     main_opcode = iword >> 26;
2674    
2675     switch (main_opcode) {
2676    
2677 dpavlin 22 case 0x04:
2678     fatal("[ TODO: ALTIVEC ]\n");
2679     ic->f = instr(nop);
2680     break;
2681    
2682 dpavlin 14 case PPC_HI6_MULLI:
2683     rt = (iword >> 21) & 31;
2684     ra = (iword >> 16) & 31;
2685     imm = (int16_t)(iword & 0xffff);
2686     ic->f = instr(mulli);
2687     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2688     ic->arg[1] = (ssize_t)imm;
2689     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2690     break;
2691    
2692     case PPC_HI6_SUBFIC:
2693     rt = (iword >> 21) & 31;
2694     ra = (iword >> 16) & 31;
2695     imm = (int16_t)(iword & 0xffff);
2696     ic->f = instr(subfic);
2697     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2698     ic->arg[1] = (ssize_t)imm;
2699     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2700     break;
2701    
2702     case PPC_HI6_CMPLI:
2703     case PPC_HI6_CMPI:
2704     bf = (iword >> 23) & 7;
2705     l_bit = (iword >> 21) & 1;
2706     ra = (iword >> 16) & 31;
2707     if (main_opcode == PPC_HI6_CMPLI) {
2708     imm = iword & 0xffff;
2709     if (l_bit)
2710     ic->f = instr(cmpldi);
2711     else
2712     ic->f = instr(cmplwi);
2713     } else {
2714     imm = (int16_t)(iword & 0xffff);
2715     if (l_bit)
2716     ic->f = instr(cmpdi);
2717 dpavlin 22 else {
2718     if (bf == 0)
2719     ic->f = instr(cmpwi_cr0);
2720     else
2721     ic->f = instr(cmpwi);
2722     }
2723 dpavlin 14 }
2724     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2725     ic->arg[1] = (ssize_t)imm;
2726 dpavlin 20 ic->arg[2] = 28 - 4 * bf;
2727 dpavlin 14 break;
2728    
2729     case PPC_HI6_ADDIC:
2730     case PPC_HI6_ADDIC_DOT:
2731     if (cpu->cd.ppc.bits == 64) {
2732     fatal("addic for 64-bit: TODO\n");
2733     goto bad;
2734     }
2735     rt = (iword >> 21) & 31;
2736     ra = (iword >> 16) & 31;
2737     imm = (int16_t)(iword & 0xffff);
2738     if (main_opcode == PPC_HI6_ADDIC)
2739     ic->f = instr(addic);
2740     else
2741     ic->f = instr(addic_dot);
2742     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2743 dpavlin 20 ic->arg[1] = imm;
2744 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2745     break;
2746    
2747     case PPC_HI6_ADDI:
2748     case PPC_HI6_ADDIS:
2749     rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2750     ic->f = instr(addi);
2751     if (ra == 0)
2752 dpavlin 22 ic->f = instr(li);
2753 dpavlin 14 else
2754     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2755 dpavlin 20 ic->arg[1] = (int16_t)(iword & 0xffff);
2756 dpavlin 14 if (main_opcode == PPC_HI6_ADDIS)
2757     ic->arg[1] <<= 16;
2758 dpavlin 22 if (ra == 0 && ic->arg[1] == 0)
2759     ic->f = instr(li_0);
2760 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2761     break;
2762    
2763     case PPC_HI6_ANDI_DOT:
2764     case PPC_HI6_ANDIS_DOT:
2765     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2766     ic->f = instr(andi_dot);
2767     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2768     ic->arg[1] = iword & 0xffff;
2769     if (main_opcode == PPC_HI6_ANDIS_DOT)
2770     ic->arg[1] <<= 16;
2771     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2772     break;
2773    
2774     case PPC_HI6_ORI:
2775     case PPC_HI6_ORIS:
2776     case PPC_HI6_XORI:
2777     case PPC_HI6_XORIS:
2778     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2779     if (main_opcode == PPC_HI6_ORI ||
2780     main_opcode == PPC_HI6_ORIS)
2781     ic->f = instr(ori);
2782     else
2783     ic->f = instr(xori);
2784     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2785     ic->arg[1] = iword & 0xffff;
2786     if (main_opcode == PPC_HI6_ORIS ||
2787     main_opcode == PPC_HI6_XORIS)
2788     ic->arg[1] <<= 16;
2789     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2790     break;
2791    
2792     case PPC_HI6_LBZ:
2793     case PPC_HI6_LBZU:
2794     case PPC_HI6_LHZ:
2795     case PPC_HI6_LHZU:
2796 dpavlin 20 case PPC_HI6_LHA:
2797     case PPC_HI6_LHAU:
2798 dpavlin 14 case PPC_HI6_LWZ:
2799     case PPC_HI6_LWZU:
2800 dpavlin 24 case PPC_HI6_LD:
2801 dpavlin 14 case PPC_HI6_LFD:
2802 dpavlin 20 case PPC_HI6_LFS:
2803 dpavlin 14 case PPC_HI6_STB:
2804     case PPC_HI6_STBU:
2805     case PPC_HI6_STH:
2806     case PPC_HI6_STHU:
2807     case PPC_HI6_STW:
2808     case PPC_HI6_STWU:
2809 dpavlin 24 case PPC_HI6_STD:
2810 dpavlin 20 case PPC_HI6_STFD:
2811     case PPC_HI6_STFS:
2812 dpavlin 14 rs = (iword >> 21) & 31;
2813     ra = (iword >> 16) & 31;
2814 dpavlin 20 imm = (int16_t)iword;
2815 dpavlin 14 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2816 dpavlin 20 ic->f = NULL;
2817 dpavlin 14 switch (main_opcode) {
2818 dpavlin 20 case PPC_HI6_LBZ: load=1; break;
2819     case PPC_HI6_LBZU: load=1; update=1; break;
2820     case PPC_HI6_LHA: load=1; size=1; zero=0; break;
2821     case PPC_HI6_LHAU: load=1; size=1; zero=0; update=1; break;
2822     case PPC_HI6_LHZ: load=1; size=1; break;
2823     case PPC_HI6_LHZU: load=1; size=1; update=1; break;
2824     case PPC_HI6_LWZ: load=1; size=2; break;
2825     case PPC_HI6_LWZU: load=1; size=2; update=1; break;
2826 dpavlin 24 case PPC_HI6_LD: load=1; size=3; break;
2827 dpavlin 20 case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break;
2828     case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break;
2829 dpavlin 14 case PPC_HI6_STB: break;
2830 dpavlin 20 case PPC_HI6_STBU: update=1; break;
2831     case PPC_HI6_STH: size=1; break;
2832     case PPC_HI6_STHU: size=1; update=1; break;
2833     case PPC_HI6_STW: size=2; break;
2834     case PPC_HI6_STWU: size=2; update=1; break;
2835 dpavlin 24 case PPC_HI6_STD: size=3; break;
2836 dpavlin 20 case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;
2837     case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;
2838 dpavlin 14 }
2839 dpavlin 20 if (ic->f == NULL) {
2840 dpavlin 14 ic->f =
2841     #ifdef MODE32
2842     ppc32_loadstore
2843     #else
2844     ppc_loadstore
2845     #endif
2846     [size + 4*zero + 8*load + (imm==0? 16 : 0)
2847     + 32*update];
2848     }
2849     if (ra == 0 && update) {
2850     fatal("TODO: ra=0 && update?\n");
2851     goto bad;
2852     }
2853     if (fp)
2854     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
2855     else
2856     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2857     if (ra == 0)
2858     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
2859     else
2860     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2861     ic->arg[2] = (ssize_t)imm;
2862     break;
2863    
2864     case PPC_HI6_BC:
2865     aa_bit = (iword >> 1) & 1;
2866     lk_bit = iword & 1;
2867     bo = (iword >> 21) & 31;
2868     bi = (iword >> 16) & 31;
2869     tmp_addr = (int64_t)(int16_t)(iword & 0xfffc);
2870     if (aa_bit) {
2871     fatal("aa_bit: NOT YET\n");
2872     goto bad;
2873     }
2874 dpavlin 20 if (lk_bit) {
2875     ic->f = instr(bcl);
2876     samepage_function = instr(bcl_samepage);
2877     } else {
2878     ic->f = instr(bc);
2879 dpavlin 22 if ((bo & 0x14) == 0x04) {
2880     samepage_function = bo & 8?
2881     instr(bc_samepage_simple1) :
2882     instr(bc_samepage_simple0);
2883     } else
2884 dpavlin 20 samepage_function = instr(bc_samepage);
2885     }
2886 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2887 dpavlin 14 ic->arg[1] = bo;
2888 dpavlin 22 ic->arg[2] = 31-bi;
2889 dpavlin 14 /* Branches are calculated as cur PC + offset. */
2890     /* Special case: branch within the same page: */
2891     {
2892     uint64_t mask_within_page =
2893     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2894     uint64_t old_pc = addr;
2895 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2896 dpavlin 14 if ((old_pc & ~mask_within_page) ==
2897     (new_pc & ~mask_within_page)) {
2898     ic->f = samepage_function;
2899     ic->arg[0] = (size_t) (
2900     cpu->cd.ppc.cur_ic_page +
2901     ((new_pc & mask_within_page) >> 2));
2902     }
2903     }
2904     break;
2905    
2906     case PPC_HI6_SC:
2907     ic->arg[0] = (iword >> 5) & 0x7f;
2908 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
2909 dpavlin 14 if (cpu->machine->userland_emul != NULL)
2910     ic->f = instr(user_syscall);
2911 dpavlin 20 else if (iword == 0x44ee0002) {
2912 dpavlin 14 /* Special case/magic hack for OpenFirmware emul: */
2913 dpavlin 20 ic->f = instr(openfirmware);
2914     } else
2915     ic->f = instr(sc);
2916 dpavlin 14 break;
2917    
2918     case PPC_HI6_B:
2919     aa_bit = (iword & 2) >> 1;
2920     lk_bit = iword & 1;
2921     tmp_addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
2922     tmp_addr = (int64_t)tmp_addr >> 6;
2923     if (lk_bit) {
2924     if (cpu->machine->show_trace_tree) {
2925     ic->f = instr(bl_trace);
2926     samepage_function = instr(bl_samepage_trace);
2927     } else {
2928     ic->f = instr(bl);
2929     samepage_function = instr(bl_samepage);
2930     }
2931     } else {
2932     ic->f = instr(b);
2933     samepage_function = instr(b_samepage);
2934     }
2935 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2936     ic->arg[1] = (addr & 0xffc) + 4;
2937 dpavlin 14 /* Branches are calculated as cur PC + offset. */
2938     /* Special case: branch within the same page: */
2939     {
2940     uint64_t mask_within_page =
2941     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2942     uint64_t old_pc = addr;
2943 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2944 dpavlin 14 if ((old_pc & ~mask_within_page) ==
2945     (new_pc & ~mask_within_page)) {
2946     ic->f = samepage_function;
2947     ic->arg[0] = (size_t) (
2948     cpu->cd.ppc.cur_ic_page +
2949     ((new_pc & mask_within_page) >> 2));
2950     }
2951     }
2952 dpavlin 20 if (aa_bit) {
2953     if (lk_bit) {
2954     if (cpu->machine->show_trace_tree) {
2955     ic->f = instr(bla_trace);
2956     } else {
2957     ic->f = instr(bla);
2958     }
2959     } else {
2960     ic->f = instr(ba);
2961     }
2962     ic->arg[0] = (ssize_t)tmp_addr;
2963     }
2964 dpavlin 14 break;
2965    
2966     case PPC_HI6_19:
2967     xo = (iword >> 1) & 1023;
2968     switch (xo) {
2969    
2970     case PPC_19_BCLR:
2971     case PPC_19_BCCTR:
2972     bo = (iword >> 21) & 31;
2973     bi = (iword >> 16) & 31;
2974     bh = (iword >> 11) & 3;
2975     lk_bit = iword & 1;
2976     if (xo == PPC_19_BCLR) {
2977     if (lk_bit)
2978     ic->f = instr(bclr_l);
2979 dpavlin 20 else {
2980 dpavlin 14 ic->f = instr(bclr);
2981 dpavlin 20 if (!cpu->machine->show_trace_tree &&
2982     (bo & 0x14) == 0x14)
2983     ic->f = instr(bclr_20);
2984     }
2985 dpavlin 14 } else {
2986     if (lk_bit)
2987     ic->f = instr(bcctr_l);
2988     else
2989     ic->f = instr(bcctr);
2990     }
2991     ic->arg[0] = bo;
2992 dpavlin 20 ic->arg[1] = 31 - bi;
2993 dpavlin 14 ic->arg[2] = bh;
2994     break;
2995    
2996     case PPC_19_ISYNC:
2997     /* TODO */
2998     ic->f = instr(nop);
2999     break;
3000    
3001     case PPC_19_RFI:
3002     ic->f = instr(rfi);
3003     break;
3004    
3005 dpavlin 24 case PPC_19_RFID:
3006     ic->f = instr(rfid);
3007     break;
3008    
3009 dpavlin 14 case PPC_19_MCRF:
3010     bf = (iword >> 23) & 7;
3011     bfa = (iword >> 18) & 7;
3012 dpavlin 20 ic->arg[0] = 28 - 4*bf;
3013     ic->arg[1] = 28 - 4*bfa;
3014 dpavlin 14 ic->f = instr(mcrf);
3015     break;
3016    
3017     case PPC_19_CRAND:
3018     case PPC_19_CRANDC:
3019     case PPC_19_CREQV:
3020     case PPC_19_CROR:
3021 dpavlin 22 case PPC_19_CRORC:
3022 dpavlin 20 case PPC_19_CRNOR:
3023 dpavlin 14 case PPC_19_CRXOR:
3024     switch (xo) {
3025     case PPC_19_CRAND: ic->f = instr(crand); break;
3026     case PPC_19_CRANDC: ic->f = instr(crandc); break;
3027     case PPC_19_CREQV: ic->f = instr(creqv); break;
3028     case PPC_19_CROR: ic->f = instr(cror); break;
3029 dpavlin 22 case PPC_19_CRORC: ic->f = instr(crorc); break;
3030 dpavlin 20 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3031 dpavlin 14 case PPC_19_CRXOR: ic->f = instr(crxor); break;
3032     }
3033     ic->arg[0] = iword;
3034     break;
3035    
3036     default:goto bad;
3037     }
3038     break;
3039    
3040 dpavlin 20 case PPC_HI6_RLWNM:
3041     case PPC_HI6_RLWINM:
3042     ra = (iword >> 16) & 31;
3043     mb = (iword >> 6) & 31;
3044     me = (iword >> 1) & 31;
3045     rc = iword & 1;
3046     mask = 0;
3047     for (;;) {
3048     mask |= ((uint32_t)0x80000000 >> mb);
3049     if (mb == me)
3050     break;
3051     mb ++; mb &= 31;
3052     }
3053     switch (main_opcode) {
3054     case PPC_HI6_RLWNM:
3055     ic->f = rc? instr(rlwnm_dot) : instr(rlwnm); break;
3056     case PPC_HI6_RLWINM:
3057     ic->f = rc? instr(rlwinm_dot) : instr(rlwinm); break;
3058     }
3059     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3060     ic->arg[1] = mask;
3061     ic->arg[2] = (uint32_t)iword;
3062     break;
3063    
3064 dpavlin 14 case PPC_HI6_RLWIMI:
3065     rs = (iword >> 21) & 31;
3066     ra = (iword >> 16) & 31;
3067 dpavlin 20 ic->f = instr(rlwimi);
3068 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3069     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3070     ic->arg[2] = (uint32_t)iword;
3071     break;
3072    
3073     case PPC_HI6_LMW:
3074     case PPC_HI6_STMW:
3075     /* NOTE: Loads use rt, not rs. */
3076     rs = (iword >> 21) & 31;
3077     ra = (iword >> 16) & 31;
3078     ic->arg[0] = rs;
3079     if (ra == 0)
3080     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3081     else
3082     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3083     ic->arg[2] = (int32_t)(int16_t)iword;
3084     switch (main_opcode) {
3085     case PPC_HI6_LMW:
3086     ic->f = instr(lmw);
3087     break;
3088     case PPC_HI6_STMW:
3089     ic->f = instr(stmw);
3090     break;
3091     }
3092     break;
3093    
3094     case PPC_HI6_30:
3095     xo = (iword >> 2) & 7;
3096     switch (xo) {
3097    
3098 dpavlin 24 case PPC_30_RLDICL:
3099 dpavlin 14 case PPC_30_RLDICR:
3100 dpavlin 24 case PPC_30_RLDIMI:
3101     switch (xo) {
3102     case PPC_30_RLDICL: ic->f = instr(rldicl); break;
3103     case PPC_30_RLDICR: ic->f = instr(rldicr); break;
3104     case PPC_30_RLDIMI: ic->f = instr(rldimi); break;
3105     }
3106 dpavlin 14 ic->arg[0] = iword;
3107     if (cpu->cd.ppc.bits == 32) {
3108 dpavlin 24 fatal("TODO: rld* in 32-bit mode?\n");
3109 dpavlin 14 goto bad;
3110     }
3111     break;
3112    
3113     default:goto bad;
3114     }
3115     break;
3116    
3117     case PPC_HI6_31:
3118     xo = (iword >> 1) & 1023;
3119     switch (xo) {
3120    
3121     case PPC_31_CMPL:
3122     case PPC_31_CMP:
3123     bf = (iword >> 23) & 7;
3124     l_bit = (iword >> 21) & 1;
3125     ra = (iword >> 16) & 31;
3126     rb = (iword >> 11) & 31;
3127     if (xo == PPC_31_CMPL) {
3128     if (l_bit)
3129     ic->f = instr(cmpld);
3130     else
3131     ic->f = instr(cmplw);
3132     } else {
3133     if (l_bit)
3134     ic->f = instr(cmpd);
3135 dpavlin 22 else {
3136     if (bf == 0)
3137     ic->f = instr(cmpw_cr0);
3138     else
3139     ic->f = instr(cmpw);
3140     }
3141 dpavlin 14 }
3142     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3143     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3144 dpavlin 20 ic->arg[2] = 28 - 4*bf;
3145 dpavlin 14 break;
3146    
3147     case PPC_31_CNTLZW:
3148     rs = (iword >> 21) & 31;
3149     ra = (iword >> 16) & 31;
3150     rc = iword & 1;
3151     if (rc) {
3152     fatal("TODO: rc\n");
3153     goto bad;
3154     }
3155     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3156     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3157     ic->f = instr(cntlzw);
3158     break;
3159    
3160     case PPC_31_MFSPR:
3161     rt = (iword >> 21) & 31;
3162     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3163 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3164 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3165 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3166 dpavlin 14 switch (spr) {
3167 dpavlin 20 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3168     default: ic->f = instr(mfspr);
3169 dpavlin 14 }
3170     break;
3171    
3172     case PPC_31_MTSPR:
3173     rs = (iword >> 21) & 31;
3174     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3175 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3176 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3177 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3178 dpavlin 22 switch (spr) {
3179     case SPR_LR:
3180     ic->f = instr(mtlr);
3181     break;
3182     case SPR_CTR:
3183     ic->f = instr(mtctr);
3184     break;
3185     default:ic->f = instr(mtspr);
3186     }
3187 dpavlin 14 break;
3188    
3189     case PPC_31_MFCR:
3190     rt = (iword >> 21) & 31;
3191     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3192     ic->f = instr(mfcr);
3193     break;
3194    
3195     case PPC_31_MFMSR:
3196     rt = (iword >> 21) & 31;
3197     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3198     ic->f = instr(mfmsr);
3199     break;
3200    
3201     case PPC_31_MTMSR:
3202 dpavlin 24 case PPC_31_MTMSRD:
3203 dpavlin 14 rs = (iword >> 21) & 31;
3204     l_bit = (iword >> 16) & 1;
3205     if (l_bit) {
3206     fatal("TODO: mtmsr l-bit\n");
3207     goto bad;
3208     }
3209     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3210 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
3211 dpavlin 24 ic->arg[2] = xo == PPC_31_MTMSRD;
3212 dpavlin 14 ic->f = instr(mtmsr);
3213     break;
3214    
3215     case PPC_31_MTCRF:
3216     rs = (iword >> 21) & 31;
3217     {
3218     int i, fxm = (iword >> 12) & 255;
3219     uint32_t tmp = 0;
3220     for (i=0; i<8; i++, fxm <<= 1) {
3221     tmp <<= 4;
3222     if (fxm & 128)
3223     tmp |= 0xf;
3224     }
3225     ic->arg[1] = (uint32_t)tmp;
3226     }
3227     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3228     ic->f = instr(mtcrf);
3229     break;
3230    
3231     case PPC_31_MFSRIN:
3232     case PPC_31_MTSRIN:
3233     rt = (iword >> 21) & 31;
3234     rb = (iword >> 11) & 31;
3235     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3236     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3237     switch (xo) {
3238     case PPC_31_MFSRIN: ic->f = instr(mfsrin); break;
3239     case PPC_31_MTSRIN: ic->f = instr(mtsrin); break;
3240     }
3241     if (cpu->cd.ppc.bits == 64) {
3242     fatal("Not yet for 64-bit mode\n");
3243     goto bad;
3244     }
3245     break;
3246    
3247 dpavlin 20 case PPC_31_MFSR:
3248 dpavlin 14 case PPC_31_MTSR:
3249     rt = (iword >> 21) & 31;
3250     ic->arg[0] = (iword >> 16) & 15;
3251     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3252 dpavlin 20 switch (xo) {
3253     case PPC_31_MFSR: ic->f = instr(mfsr); break;
3254     case PPC_31_MTSR: ic->f = instr(mtsr); break;
3255     }
3256 dpavlin 14 if (cpu->cd.ppc.bits == 64) {
3257     fatal("Not yet for 64-bit mode\n");
3258     goto bad;
3259     }
3260     break;
3261    
3262     case PPC_31_SRAWI:
3263     rs = (iword >> 21) & 31;
3264     ra = (iword >> 16) & 31;
3265     sh = (iword >> 11) & 31;
3266     rc = iword & 1;
3267     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3268     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3269     ic->arg[2] = sh;
3270     if (rc)
3271     ic->f = instr(srawi_dot);
3272     else
3273     ic->f = instr(srawi);
3274     break;
3275    
3276     case PPC_31_SYNC:
3277 dpavlin 24 case PPC_31_DSSALL:
3278 dpavlin 14 case PPC_31_EIEIO:
3279     case PPC_31_DCBST:
3280     case PPC_31_DCBTST:
3281     case PPC_31_DCBF:
3282     case PPC_31_DCBT:
3283     case PPC_31_ICBI:
3284     ic->f = instr(nop);
3285     break;
3286    
3287     case PPC_31_DCBZ:
3288     ra = (iword >> 16) & 31;
3289     rb = (iword >> 11) & 31;
3290     if (ra == 0)
3291     ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);
3292     else
3293     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3294     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3295 dpavlin 20 ic->arg[2] = addr & 0xfff;
3296 dpavlin 14 ic->f = instr(dcbz);
3297     break;
3298    
3299 dpavlin 20 case PPC_31_TLBIA:
3300     ic->f = instr(tlbia);
3301     break;
3302    
3303     case PPC_31_TLBSYNC:
3304     /* According to IBM, "Ensures that a tlbie and
3305     tlbia instruction executed by one processor has
3306     completed on all other processors.", which in
3307     GXemul means a nop :-) */
3308     ic->f = instr(nop);
3309     break;
3310    
3311 dpavlin 14 case PPC_31_TLBIE:
3312 dpavlin 20 /* TODO: POWER also uses ra? */
3313     rb = (iword >> 11) & 31;
3314     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3315 dpavlin 14 ic->f = instr(tlbie);
3316     break;
3317    
3318 dpavlin 20 case PPC_31_TLBLD: /* takes an arg */
3319     rb = (iword >> 11) & 31;
3320     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3321     ic->f = instr(tlbld);
3322     break;
3323    
3324     case PPC_31_TLBLI: /* takes an arg */
3325     rb = (iword >> 11) & 31;
3326     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3327     ic->f = instr(tlbli);
3328     break;
3329    
3330 dpavlin 22 case PPC_31_TLBSX_DOT:
3331     /* TODO */
3332     ic->f = instr(tlbsx_dot);
3333     break;
3334    
3335 dpavlin 14 case PPC_31_MFTB:
3336     rt = (iword >> 21) & 31;
3337     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3338     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3339     switch (spr) {
3340     case 268: ic->f = instr(mftb); break;
3341     case 269: ic->f = instr(mftbu); break;
3342     default:fatal("mftb spr=%i?\n", spr);
3343     goto bad;
3344     }
3345     break;
3346    
3347     case PPC_31_NEG:
3348     rt = (iword >> 21) & 31;
3349     ra = (iword >> 16) & 31;
3350     rc = iword & 1;
3351     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3352     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3353     if (rc)
3354     ic->f = instr(neg_dot);
3355     else
3356     ic->f = instr(neg);
3357     break;
3358    
3359     case PPC_31_LWARX:
3360     case PPC_31_LDARX:
3361     case PPC_31_STWCX_DOT:
3362     case PPC_31_STDCX_DOT:
3363     ic->arg[0] = iword;
3364     ic->f = instr(llsc);
3365     break;
3366    
3367 dpavlin 20 case PPC_31_LSWI:
3368     case PPC_31_STSWI:
3369     rs = (iword >> 21) & 31;
3370     ra = (iword >> 16) & 31;
3371     nb = (iword >> 11) & 31;
3372     ic->arg[0] = rs;
3373     if (ra == 0)
3374     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3375     else
3376     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3377     ic->arg[2] = nb == 0? 32 : nb;
3378     switch (xo) {
3379     case PPC_31_LSWI: ic->f = instr(lswi); break;
3380     case PPC_31_STSWI: ic->f = instr(stswi); break;
3381     }
3382     break;
3383    
3384 dpavlin 22 case PPC_31_WRTEEI:
3385     ic->arg[0] = iword & 0x8000;
3386     ic->f = instr(wrteei);
3387     break;
3388    
3389 dpavlin 20 case 0x1c3:
3390     fatal("[ mtdcr: TODO ]\n");
3391     ic->f = instr(nop);
3392     break;
3393    
3394 dpavlin 14 case PPC_31_LBZX:
3395     case PPC_31_LBZUX:
3396 dpavlin 20 case PPC_31_LHAX:
3397     case PPC_31_LHAUX:
3398 dpavlin 14 case PPC_31_LHZX:
3399     case PPC_31_LHZUX:
3400     case PPC_31_LWZX:
3401     case PPC_31_LWZUX:
3402 dpavlin 20 case PPC_31_LHBRX:
3403     case PPC_31_LWBRX:
3404     case PPC_31_LFDX:
3405     case PPC_31_LFSX:
3406 dpavlin 14 case PPC_31_STBX:
3407     case PPC_31_STBUX:
3408     case PPC_31_STHX:
3409     case PPC_31_STHUX:
3410     case PPC_31_STWX:
3411     case PPC_31_STWUX:
3412     case PPC_31_STDX:
3413     case PPC_31_STDUX:
3414 dpavlin 20 case PPC_31_STHBRX:
3415     case PPC_31_STWBRX:
3416     case PPC_31_STFDX:
3417     case PPC_31_STFSX:
3418 dpavlin 14 rs = (iword >> 21) & 31;
3419     ra = (iword >> 16) & 31;
3420     rb = (iword >> 11) & 31;
3421     if (ra == 0)
3422     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3423     else
3424     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3425     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3426     load = 0; zero = 1; size = 0; update = 0;
3427 dpavlin 20 byterev = 0; fp = 0;
3428     ic->f = NULL;
3429 dpavlin 14 switch (xo) {
3430     case PPC_31_LBZX: load = 1; break;
3431 dpavlin 20 case PPC_31_LBZUX: load=update=1; break;
3432     case PPC_31_LHAX: size=1; load=1; zero=0; break;
3433     case PPC_31_LHAUX: size=1; load=update=1; zero=0; break;
3434     case PPC_31_LHZX: size=1; load=1; break;
3435     case PPC_31_LHZUX: size=1; load=update = 1; break;
3436     case PPC_31_LWZX: size=2; load=1; break;
3437     case PPC_31_LWZUX: size=2; load=update = 1; break;
3438     case PPC_31_LHBRX: size=1; load=1; byterev=1;
3439     ic->f = instr(lhbrx); break;
3440     case PPC_31_LWBRX: size=2; load=1; byterev=1;
3441     ic->f = instr(lwbrx); break;
3442     case PPC_31_LFDX: size=3; load=1; fp=1;
3443     ic->f = instr(lfdx); break;
3444     case PPC_31_LFSX: size=2; load=1; fp=1;
3445     ic->f = instr(lfsx); break;
3446 dpavlin 14 case PPC_31_STBX: break;
3447     case PPC_31_STBUX: update = 1; break;
3448 dpavlin 20 case PPC_31_STHX: size=1; break;
3449     case PPC_31_STHUX: size=1; update = 1; break;
3450     case PPC_31_STWX: size=2; break;
3451     case PPC_31_STWUX: size=2; update = 1; break;
3452     case PPC_31_STDX: size=3; break;
3453     case PPC_31_STDUX: size=3; update = 1; break;
3454     case PPC_31_STHBRX:size=1; byterev = 1;
3455     ic->f = instr(sthbrx); break;
3456     case PPC_31_STWBRX:size=2; byterev = 1;
3457     ic->f = instr(stwbrx); break;
3458     case PPC_31_STFDX: size=3; fp=1;
3459     ic->f = instr(stfdx); break;
3460     case PPC_31_STFSX: size=2; fp=1;
3461     ic->f = instr(stfsx); break;
3462 dpavlin 14 }
3463 dpavlin 20 if (fp)
3464     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
3465     else
3466     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3467     if (!byterev && ic->f == NULL) {
3468     ic->f =
3469 dpavlin 14 #ifdef MODE32
3470 dpavlin 20 ppc32_loadstore_indexed
3471 dpavlin 14 #else
3472 dpavlin 20 ppc_loadstore_indexed
3473 dpavlin 14 #endif
3474 dpavlin 20 [size + 4*zero + 8*load + 16*update];
3475     }
3476 dpavlin 14 if (ra == 0 && update) {
3477     fatal("TODO: ra=0 && update?\n");
3478     goto bad;
3479     }
3480     break;
3481    
3482     case PPC_31_EXTSB:
3483     case PPC_31_EXTSH:
3484     case PPC_31_EXTSW:
3485     case PPC_31_SLW:
3486 dpavlin 24 case PPC_31_SLD:
3487 dpavlin 14 case PPC_31_SRAW:
3488     case PPC_31_SRW:
3489     case PPC_31_AND:
3490     case PPC_31_NAND:
3491     case PPC_31_ANDC:
3492     case PPC_31_NOR:
3493     case PPC_31_OR:
3494     case PPC_31_ORC:
3495     case PPC_31_XOR:
3496 dpavlin 24 case PPC_31_EQV:
3497 dpavlin 14 rs = (iword >> 21) & 31;
3498     ra = (iword >> 16) & 31;
3499     rb = (iword >> 11) & 31;
3500     rc = iword & 1;
3501     rc_f = NULL;
3502     switch (xo) {
3503     case PPC_31_EXTSB:ic->f = instr(extsb);
3504     rc_f = instr(extsb_dot); break;
3505     case PPC_31_EXTSH:ic->f = instr(extsh);
3506     rc_f = instr(extsh_dot); break;
3507     case PPC_31_EXTSW:ic->f = instr(extsw);
3508     rc_f = instr(extsw_dot); break;
3509     case PPC_31_SLW: ic->f = instr(slw);
3510     rc_f = instr(slw_dot); break;
3511 dpavlin 24 case PPC_31_SLD: ic->f = instr(sld);
3512     rc_f = instr(sld_dot); break;
3513 dpavlin 14 case PPC_31_SRAW: ic->f = instr(sraw);
3514     rc_f = instr(sraw_dot); break;
3515     case PPC_31_SRW: ic->f = instr(srw);
3516     rc_f = instr(srw_dot); break;
3517     case PPC_31_AND: ic->f = instr(and);
3518     rc_f = instr(and_dot); break;
3519     case PPC_31_NAND: ic->f = instr(nand);
3520     rc_f = instr(nand_dot); break;
3521     case PPC_31_ANDC: ic->f = instr(andc);
3522     rc_f = instr(andc_dot); break;
3523     case PPC_31_NOR: ic->f = instr(nor);
3524     rc_f = instr(nor_dot); break;
3525 dpavlin 22 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3526     : instr(or);
3527 dpavlin 14 rc_f = instr(or_dot); break;
3528     case PPC_31_ORC: ic->f = instr(orc);
3529     rc_f = instr(orc_dot); break;
3530     case PPC_31_XOR: ic->f = instr(xor);
3531     rc_f = instr(xor_dot); break;
3532 dpavlin 24 case PPC_31_EQV: ic->f = instr(eqv);
3533     rc_f = instr(eqv_dot); break;
3534 dpavlin 14 }
3535     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3536     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3537     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3538     if (rc)
3539     ic->f = rc_f;
3540     break;
3541    
3542     case PPC_31_MULLW:
3543     case PPC_31_MULHW:
3544     case PPC_31_MULHWU:
3545     case PPC_31_DIVW:
3546     case PPC_31_DIVWU:
3547     case PPC_31_ADD:
3548     case PPC_31_ADDC:
3549     case PPC_31_ADDE:
3550     case PPC_31_ADDME:
3551     case PPC_31_ADDZE:
3552     case PPC_31_SUBF:
3553     case PPC_31_SUBFC:
3554     case PPC_31_SUBFE:
3555 dpavlin 20 case PPC_31_SUBFME:
3556 dpavlin 14 case PPC_31_SUBFZE:
3557     rt = (iword >> 21) & 31;
3558     ra = (iword >> 16) & 31;
3559     rb = (iword >> 11) & 31;
3560     oe_bit = (iword >> 10) & 1;
3561     rc = iword & 1;
3562     if (oe_bit) {
3563     fatal("oe_bit not yet implemented\n");
3564     goto bad;
3565     }
3566     switch (xo) {
3567     case PPC_31_MULLW: ic->f = instr(mullw); break;
3568     case PPC_31_MULHW: ic->f = instr(mulhw); break;
3569     case PPC_31_MULHWU: ic->f = instr(mulhwu); break;
3570     case PPC_31_DIVW: ic->f = instr(divw); n64=1; break;
3571     case PPC_31_DIVWU: ic->f = instr(divwu); n64=1; break;
3572     case PPC_31_ADD: ic->f = instr(add); break;
3573     case PPC_31_ADDC: ic->f = instr(addc); n64=1; break;
3574     case PPC_31_ADDE: ic->f = instr(adde); n64=1; break;
3575     case PPC_31_ADDME: ic->f = instr(addme); n64=1; break;
3576     case PPC_31_ADDZE: ic->f = instr(addze); n64=1; break;
3577     case PPC_31_SUBF: ic->f = instr(subf); break;
3578     case PPC_31_SUBFC: ic->f = instr(subfc); break;
3579     case PPC_31_SUBFE: ic->f = instr(subfe); n64=1; break;
3580 dpavlin 20 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3581 dpavlin 14 case PPC_31_SUBFZE: ic->f = instr(subfze); n64=1;break;
3582     }
3583     if (rc) {
3584     switch (xo) {
3585     case PPC_31_ADD:
3586     ic->f = instr(add_dot); break;
3587     case PPC_31_ADDE:
3588     ic->f = instr(adde_dot); break;
3589     case PPC_31_ADDME:
3590     ic->f = instr(addme_dot); break;
3591     case PPC_31_ADDZE:
3592     ic->f = instr(addze_dot); break;
3593 dpavlin 20 case PPC_31_DIVW:
3594     ic->f = instr(divw_dot); break;
3595     case PPC_31_DIVWU:
3596     ic->f = instr(divwu_dot); break;
3597     case PPC_31_MULLW:
3598     ic->f = instr(mullw_dot); break;
3599     case PPC_31_MULHW:
3600     ic->f = instr(mulhw_dot); break;
3601     case PPC_31_MULHWU:
3602     ic->f = instr(mulhwu_dot); break;
3603 dpavlin 14 case PPC_31_SUBF:
3604     ic->f = instr(subf_dot); break;
3605     case PPC_31_SUBFC:
3606     ic->f = instr(subfc_dot); break;
3607     case PPC_31_SUBFE:
3608     ic->f = instr(subfe_dot); break;
3609 dpavlin 20 case PPC_31_SUBFME:
3610     ic->f = instr(subfme_dot); break;
3611 dpavlin 14 case PPC_31_SUBFZE:
3612     ic->f = instr(subfze_dot); break;
3613     default:fatal("RC bit not yet implemented\n");
3614     goto bad;
3615     }
3616     }
3617     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3618     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3619     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3620     if (cpu->cd.ppc.bits == 64 && n64) {
3621     fatal("Not yet for 64-bit mode\n");
3622     goto bad;
3623     }
3624     break;
3625    
3626 dpavlin 22 case PPC_31_LVX:
3627 dpavlin 24 case PPC_31_LVXL:
3628 dpavlin 22 case PPC_31_STVX:
3629     case PPC_31_STVXL:
3630 dpavlin 24 fatal("[ TODO: altivec load/store ]\n");
3631     load = 0;
3632     switch (xo) {
3633     case PPC_31_LVX:
3634     case PPC_31_LVXL:
3635     load = 1; break;
3636     }
3637     rs = (iword >> 21) & 31;
3638     ra = (iword >> 16) & 31;
3639     rb = (iword >> 11) & 31;
3640     ic->arg[0] = (size_t)(&cpu->cd.ppc.vr_hi[rs]);
3641     if (ra == 0)
3642     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3643     else
3644     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3645     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3646     ic->f =
3647     #ifdef MODE32
3648     ppc32_loadstore_indexed
3649     #else
3650     ppc_loadstore_indexed
3651     #endif
3652     [3 + 4 * load];
3653 dpavlin 22 break;
3654    
3655 dpavlin 14 default:goto bad;
3656     }
3657     break;
3658    
3659 dpavlin 20 case PPC_HI6_59:
3660     xo = (iword >> 1) & 1023;
3661 dpavlin 14 rt = (iword >> 21) & 31;
3662     ra = (iword >> 16) & 31;
3663     rb = (iword >> 11) & 31;
3664 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
3665 dpavlin 14 rc = iword & 1;
3666    
3667 dpavlin 20 if (rc) {
3668     fatal("Floating point (59) with rc bit! TODO\n");
3669     goto bad;
3670     }
3671 dpavlin 14
3672 dpavlin 20 /* NOTE: Some floating-point instructions are selected
3673     using only the lowest 5 bits, not all 10! */
3674     switch (xo & 31) {
3675     case PPC_59_FDIVS:
3676     case PPC_59_FSUBS:
3677     case PPC_59_FADDS:
3678     switch (xo & 31) {
3679     case PPC_59_FDIVS: ic->f = instr(fdivs); break;
3680     case PPC_59_FSUBS: ic->f = instr(fsubs); break;
3681     case PPC_59_FADDS: ic->f = instr(fadds); break;
3682 dpavlin 14 }
3683 dpavlin 20 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3684     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3685     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3686 dpavlin 14 break;
3687 dpavlin 20 case PPC_59_FMULS:
3688     ic->f = instr(fmuls);
3689     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3690     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3691     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3692     break;
3693     default:/* Use all 10 bits of xo: */
3694     switch (xo) {
3695     default:goto bad;
3696     }
3697     }
3698     break;
3699 dpavlin 14
3700 dpavlin 20 case PPC_HI6_63:
3701     xo = (iword >> 1) & 1023;
3702     rt = (iword >> 21) & 31;
3703     ra = (iword >> 16) & 31;
3704     rb = (iword >> 11) & 31;
3705     rs = (iword >> 6) & 31; /* actually frc */
3706     rc = iword & 1;
3707    
3708     if (rc) {
3709     fatal("Floating point (63) with rc bit! TODO\n");
3710     goto bad;
3711 dpavlin 14 }
3712 dpavlin 20
3713     /* NOTE: Some floating-point instructions are selected
3714     using only the lowest 5 bits, not all 10! */
3715     switch (xo & 31) {
3716     case PPC_63_FDIV:
3717     case PPC_63_FSUB:
3718     case PPC_63_FADD:
3719     switch (xo & 31) {
3720     case PPC_63_FDIV: ic->f = instr(fdiv); break;
3721     case PPC_63_FSUB: ic->f = instr(fsub); break;
3722     case PPC_63_FADD: ic->f = instr(fadd); break;
3723     }
3724     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3725     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3726     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3727     break;
3728     case PPC_63_FMUL:
3729     ic->f = instr(fmul);
3730     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3731     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3732     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3733     break;
3734     case PPC_63_FMSUB:
3735     case PPC_63_FMADD:
3736     switch (xo & 31) {
3737     case PPC_63_FMSUB: ic->f = instr(fmsub); break;
3738     case PPC_63_FMADD: ic->f = instr(fmadd); break;
3739     }
3740     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3741     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3742     ic->arg[2] = iword;
3743     break;
3744     default:/* Use all 10 bits of xo: */
3745     switch (xo) {
3746     case PPC_63_FCMPU:
3747     ic->f = instr(fcmpu);
3748     ic->arg[0] = 28 - 4*(rt >> 2);
3749     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3750     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3751     break;
3752     case PPC_63_FRSP:
3753     case PPC_63_FCTIWZ:
3754     case PPC_63_FNEG:
3755     case PPC_63_FMR:
3756     switch (xo) {
3757     case PPC_63_FRSP: ic->f = instr(frsp); break;
3758     case PPC_63_FCTIWZ: ic->f = instr(fctiwz);break;
3759     case PPC_63_FNEG: ic->f = instr(fneg); break;
3760     case PPC_63_FMR: ic->f = instr(fmr); break;
3761     }
3762     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3763     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3764     break;
3765     case PPC_63_MFFS:
3766     ic->f = instr(mffs);
3767     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3768     break;
3769     case PPC_63_MTFSF:
3770     ic->f = instr(mtfsf);
3771     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3772     ic->arg[1] = 0;
3773     for (bi=7; bi>=0; bi--) {
3774     ic->arg[1] <<= 8;
3775     if (iword & (1 << (17+bi)))
3776     ic->arg[1] |= 0xf;
3777     }
3778     break;
3779     default:goto bad;
3780     }
3781     }
3782 dpavlin 14 break;
3783    
3784     default:goto bad;
3785     }
3786    
3787    
3788     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3789     #include "cpu_dyntrans.c"
3790     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3791     }
3792    

  ViewVC Help
Powered by ViewVC 1.1.26