/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 91889 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 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 34 * $Id: cpu_ppc_instr.c,v 1.73 2007/02/17 10:06:19 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 dpavlin 34 * lvx, stvx: Vector (16-byte) load/store (slow implementation)
2477     *
2478     * arg[0] = v-register nr of rs
2479     * arg[1] = pointer to ra
2480     * arg[2] = pointer to rb
2481     */
2482     X(lvx)
2483     {
2484     MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2485     uint8_t data[16];
2486     uint64_t hi, lo;
2487     int rs = ic->arg[0];
2488    
2489     if (cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
2490     MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
2491     /* exception */
2492     return;
2493     }
2494    
2495     hi = ((uint64_t)data[0] << 56) +
2496     ((uint64_t)data[1] << 48) +
2497     ((uint64_t)data[2] << 40) +
2498     ((uint64_t)data[3] << 32) +
2499     ((uint64_t)data[4] << 24) +
2500     ((uint64_t)data[5] << 16) +
2501     ((uint64_t)data[6] << 8) +
2502     ((uint64_t)data[7]);
2503     lo = ((uint64_t)data[8] << 56) +
2504     ((uint64_t)data[9] << 48) +
2505     ((uint64_t)data[10] << 40) +
2506     ((uint64_t)data[11] << 32) +
2507     ((uint64_t)data[12] << 24) +
2508     ((uint64_t)data[13] << 16) +
2509     ((uint64_t)data[14] << 8) +
2510     ((uint64_t)data[15]);
2511    
2512     cpu->cd.ppc.vr_hi[rs] = hi; cpu->cd.ppc.vr_lo[rs] = lo;
2513     }
2514     X(stvx)
2515     {
2516     uint8_t data[16];
2517     MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2518     int rs = ic->arg[0];
2519     uint64_t hi = cpu->cd.ppc.vr_hi[rs], lo = cpu->cd.ppc.vr_lo[rs];
2520    
2521     data[0] = hi >> 56;
2522     data[1] = hi >> 48;
2523     data[2] = hi >> 40;
2524     data[3] = hi >> 32;
2525     data[4] = hi >> 24;
2526     data[5] = hi >> 16;
2527     data[6] = hi >> 8;
2528     data[7] = hi;
2529     data[8] = lo >> 56;
2530     data[9] = lo >> 48;
2531     data[10] = lo >> 40;
2532     data[11] = lo >> 32;
2533     data[12] = lo >> 24;
2534     data[13] = lo >> 16;
2535     data[14] = lo >> 8;
2536     data[15] = lo;
2537    
2538     cpu->memory_rw(cpu, cpu->mem, addr, data,
2539     sizeof(data), MEM_WRITE, CACHE_DATA);
2540     }
2541    
2542    
2543     /*
2544     * vxor: Vector (16-byte) XOR
2545     *
2546     * arg[0] = v-register nr of source 1
2547     * arg[1] = v-register nr of source 2
2548     * arg[2] = v-register nr of destination
2549     */
2550     X(vxor)
2551     {
2552     cpu->cd.ppc.vr_hi[ic->arg[2]] =
2553     cpu->cd.ppc.vr_hi[ic->arg[0]] ^ cpu->cd.ppc.vr_hi[ic->arg[1]];
2554     cpu->cd.ppc.vr_lo[ic->arg[2]] =
2555     cpu->cd.ppc.vr_lo[ic->arg[0]] ^ cpu->cd.ppc.vr_lo[ic->arg[1]];
2556     }
2557    
2558    
2559     /*
2560 dpavlin 20 * tlbia: TLB invalidate all
2561     */
2562     X(tlbia)
2563     {
2564 dpavlin 24 fatal("[ tlbia ]\n");
2565 dpavlin 20 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2566     }
2567    
2568    
2569     /*
2570 dpavlin 14 * tlbie: TLB invalidate
2571     */
2572     X(tlbie)
2573     {
2574 dpavlin 24 /* fatal("[ tlbie ]\n"); */
2575 dpavlin 20 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2576     INVALIDATE_VADDR);
2577 dpavlin 14 }
2578    
2579    
2580     /*
2581 dpavlin 20 * sc: Syscall.
2582     */
2583     X(sc)
2584     {
2585     /* Synchronize the PC (pointing to _after_ this instruction) */
2586     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2587    
2588     ppc_exception(cpu, PPC_EXCEPTION_SC);
2589 dpavlin 22
2590     /* This caused an update to the PC register, so there is no need
2591     to worry about the next instruction being an end_of_page. */
2592 dpavlin 20 }
2593    
2594    
2595     /*
2596 dpavlin 14 * user_syscall: Userland syscall.
2597     *
2598     * arg[0] = syscall "level" (usually 0)
2599     */
2600     X(user_syscall)
2601     {
2602     useremul_syscall(cpu, ic->arg[0]);
2603 dpavlin 24
2604     if (!cpu->running) {
2605     cpu->n_translated_instrs --;
2606     cpu->cd.ppc.next_ic = &nothing_call;
2607     }
2608 dpavlin 14 }
2609    
2610    
2611     /*
2612     * openfirmware:
2613     */
2614     X(openfirmware)
2615     {
2616     of_emul(cpu);
2617 dpavlin 22 if (cpu->running == 0) {
2618 dpavlin 30 cpu->n_translated_instrs --;
2619     cpu->cd.ppc.next_ic = &nothing_call;
2620 dpavlin 22 }
2621 dpavlin 20 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2622 dpavlin 14 if (cpu->machine->show_trace_tree)
2623     cpu_functioncall_trace_return(cpu);
2624 dpavlin 22 quick_pc_to_pointers(cpu);
2625 dpavlin 14 }
2626    
2627    
2628 dpavlin 20 /*
2629 dpavlin 22 * tlbsx_dot: TLB scan
2630     */
2631     X(tlbsx_dot)
2632     {
2633     /* TODO */
2634     cpu->cd.ppc.cr &= ~(0xf0000000);
2635     cpu->cd.ppc.cr |= 0x20000000;
2636     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2637     }
2638    
2639    
2640     /*
2641 dpavlin 20 * tlbli:
2642     */
2643     X(tlbli)
2644     {
2645 dpavlin 22 fatal("tlbli\n");
2646     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2647 dpavlin 20 }
2648 dpavlin 14
2649    
2650     /*
2651 dpavlin 20 * tlbld:
2652 dpavlin 14 */
2653 dpavlin 20 X(tlbld)
2654 dpavlin 14 {
2655 dpavlin 20 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2656     MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2657 dpavlin 14
2658 dpavlin 22 fatal("tlbld\n");
2659     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2660 dpavlin 14 }
2661    
2662    
2663     /*****************************************************************************/
2664    
2665    
2666     X(end_of_page)
2667     {
2668     /* Update the PC: (offset 0, but on the next page) */
2669 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2670     cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2671 dpavlin 14
2672     /* Find the new physical page and update the translation pointers: */
2673 dpavlin 22 quick_pc_to_pointers(cpu);
2674 dpavlin 14
2675     /* end_of_page doesn't count as an executed instruction: */
2676     cpu->n_translated_instrs --;
2677     }
2678    
2679    
2680     /*****************************************************************************/
2681    
2682    
2683     /*
2684     * ppc_instr_to_be_translated():
2685     *
2686 dpavlin 24 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2687 dpavlin 14 * valid data for the translated instruction, or a "nothing" instruction if
2688     * there was a translation failure. The newly translated instruction is then
2689     * executed.
2690     */
2691     X(to_be_translated)
2692     {
2693     uint64_t addr, low_pc, tmp_addr;
2694 dpavlin 20 uint32_t iword, mask;
2695 dpavlin 14 unsigned char *page;
2696     unsigned char ib[4];
2697     int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
2698     xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,
2699 dpavlin 20 bfa, fp, byterev, nb, mb, me;
2700 dpavlin 14 void (*samepage_function)(struct cpu *, struct ppc_instr_call *);
2701     void (*rc_f)(struct cpu *, struct ppc_instr_call *);
2702    
2703     /* Figure out the (virtual) address of the instruction: */
2704     low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
2705     / sizeof(struct ppc_instr_call);
2706     addr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
2707     << PPC_INSTR_ALIGNMENT_SHIFT);
2708     addr += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2709     cpu->pc = addr;
2710     addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
2711    
2712     /* Read the instruction word from memory: */
2713 dpavlin 24 #ifdef MODE32
2714     page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12];
2715     #else
2716     {
2717     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2718     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2719     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2720     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2721     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2722     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2723     DYNTRANS_L3N)) & mask3;
2724     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1];
2725     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2726     page = l3->host_load[x3];
2727     }
2728     #endif
2729 dpavlin 14
2730     if (page != NULL) {
2731     /* fatal("TRANSLATION HIT!\n"); */
2732     memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2733     } else {
2734     /* fatal("TRANSLATION MISS!\n"); */
2735     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2736     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2737 dpavlin 20 fatal("PPC to_be_translated(): "
2738 dpavlin 14 "read failed: TODO\n");
2739 dpavlin 20 exit(1);
2740     /* goto bad; */
2741 dpavlin 14 }
2742     }
2743    
2744     iword = *((uint32_t *)&ib[0]);
2745 dpavlin 22 iword = BE32_TO_HOST(iword);
2746 dpavlin 14
2747    
2748     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2749     #include "cpu_dyntrans.c"
2750     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2751    
2752    
2753     /*
2754     * Translate the instruction:
2755     */
2756    
2757     main_opcode = iword >> 26;
2758    
2759     switch (main_opcode) {
2760    
2761 dpavlin 22 case 0x04:
2762 dpavlin 34 if (iword == 0x12739cc4) {
2763     /* vxor v19,v19,v19 */
2764     ic->f = instr(vxor);
2765     ic->arg[0] = 19;
2766     ic->arg[1] = 19;
2767     ic->arg[2] = 19;
2768     } else {
2769     fatal("[ TODO: Unimplemented ALTIVEC, iword"
2770     " = 0x%08"PRIx32"x ]\n", iword);
2771     goto bad;
2772     }
2773 dpavlin 22 break;
2774    
2775 dpavlin 14 case PPC_HI6_MULLI:
2776     rt = (iword >> 21) & 31;
2777     ra = (iword >> 16) & 31;
2778     imm = (int16_t)(iword & 0xffff);
2779     ic->f = instr(mulli);
2780     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2781     ic->arg[1] = (ssize_t)imm;
2782     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2783     break;
2784    
2785     case PPC_HI6_SUBFIC:
2786     rt = (iword >> 21) & 31;
2787     ra = (iword >> 16) & 31;
2788     imm = (int16_t)(iword & 0xffff);
2789     ic->f = instr(subfic);
2790     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2791     ic->arg[1] = (ssize_t)imm;
2792     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2793     break;
2794    
2795     case PPC_HI6_CMPLI:
2796     case PPC_HI6_CMPI:
2797     bf = (iword >> 23) & 7;
2798     l_bit = (iword >> 21) & 1;
2799     ra = (iword >> 16) & 31;
2800     if (main_opcode == PPC_HI6_CMPLI) {
2801     imm = iword & 0xffff;
2802     if (l_bit)
2803     ic->f = instr(cmpldi);
2804     else
2805     ic->f = instr(cmplwi);
2806     } else {
2807     imm = (int16_t)(iword & 0xffff);
2808     if (l_bit)
2809     ic->f = instr(cmpdi);
2810 dpavlin 22 else {
2811     if (bf == 0)
2812     ic->f = instr(cmpwi_cr0);
2813     else
2814     ic->f = instr(cmpwi);
2815     }
2816 dpavlin 14 }
2817     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2818     ic->arg[1] = (ssize_t)imm;
2819 dpavlin 20 ic->arg[2] = 28 - 4 * bf;
2820 dpavlin 14 break;
2821    
2822     case PPC_HI6_ADDIC:
2823     case PPC_HI6_ADDIC_DOT:
2824     if (cpu->cd.ppc.bits == 64) {
2825     fatal("addic for 64-bit: TODO\n");
2826     goto bad;
2827     }
2828     rt = (iword >> 21) & 31;
2829     ra = (iword >> 16) & 31;
2830     imm = (int16_t)(iword & 0xffff);
2831     if (main_opcode == PPC_HI6_ADDIC)
2832     ic->f = instr(addic);
2833     else
2834     ic->f = instr(addic_dot);
2835     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2836 dpavlin 20 ic->arg[1] = imm;
2837 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2838     break;
2839    
2840     case PPC_HI6_ADDI:
2841     case PPC_HI6_ADDIS:
2842     rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2843     ic->f = instr(addi);
2844     if (ra == 0)
2845 dpavlin 22 ic->f = instr(li);
2846 dpavlin 14 else
2847     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2848 dpavlin 20 ic->arg[1] = (int16_t)(iword & 0xffff);
2849 dpavlin 14 if (main_opcode == PPC_HI6_ADDIS)
2850     ic->arg[1] <<= 16;
2851 dpavlin 22 if (ra == 0 && ic->arg[1] == 0)
2852     ic->f = instr(li_0);
2853 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2854     break;
2855    
2856     case PPC_HI6_ANDI_DOT:
2857     case PPC_HI6_ANDIS_DOT:
2858     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2859     ic->f = instr(andi_dot);
2860     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2861     ic->arg[1] = iword & 0xffff;
2862     if (main_opcode == PPC_HI6_ANDIS_DOT)
2863     ic->arg[1] <<= 16;
2864     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2865     break;
2866    
2867     case PPC_HI6_ORI:
2868     case PPC_HI6_ORIS:
2869     case PPC_HI6_XORI:
2870     case PPC_HI6_XORIS:
2871     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2872     if (main_opcode == PPC_HI6_ORI ||
2873     main_opcode == PPC_HI6_ORIS)
2874     ic->f = instr(ori);
2875     else
2876     ic->f = instr(xori);
2877     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2878     ic->arg[1] = iword & 0xffff;
2879     if (main_opcode == PPC_HI6_ORIS ||
2880     main_opcode == PPC_HI6_XORIS)
2881     ic->arg[1] <<= 16;
2882     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2883     break;
2884    
2885     case PPC_HI6_LBZ:
2886     case PPC_HI6_LBZU:
2887     case PPC_HI6_LHZ:
2888     case PPC_HI6_LHZU:
2889 dpavlin 20 case PPC_HI6_LHA:
2890     case PPC_HI6_LHAU:
2891 dpavlin 14 case PPC_HI6_LWZ:
2892     case PPC_HI6_LWZU:
2893 dpavlin 24 case PPC_HI6_LD:
2894 dpavlin 14 case PPC_HI6_LFD:
2895 dpavlin 20 case PPC_HI6_LFS:
2896 dpavlin 14 case PPC_HI6_STB:
2897     case PPC_HI6_STBU:
2898     case PPC_HI6_STH:
2899     case PPC_HI6_STHU:
2900     case PPC_HI6_STW:
2901     case PPC_HI6_STWU:
2902 dpavlin 24 case PPC_HI6_STD:
2903 dpavlin 20 case PPC_HI6_STFD:
2904     case PPC_HI6_STFS:
2905 dpavlin 14 rs = (iword >> 21) & 31;
2906     ra = (iword >> 16) & 31;
2907 dpavlin 20 imm = (int16_t)iword;
2908 dpavlin 14 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2909 dpavlin 20 ic->f = NULL;
2910 dpavlin 14 switch (main_opcode) {
2911 dpavlin 20 case PPC_HI6_LBZ: load=1; break;
2912     case PPC_HI6_LBZU: load=1; update=1; break;
2913     case PPC_HI6_LHA: load=1; size=1; zero=0; break;
2914     case PPC_HI6_LHAU: load=1; size=1; zero=0; update=1; break;
2915     case PPC_HI6_LHZ: load=1; size=1; break;
2916     case PPC_HI6_LHZU: load=1; size=1; update=1; break;
2917     case PPC_HI6_LWZ: load=1; size=2; break;
2918     case PPC_HI6_LWZU: load=1; size=2; update=1; break;
2919 dpavlin 24 case PPC_HI6_LD: load=1; size=3; break;
2920 dpavlin 20 case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break;
2921     case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break;
2922 dpavlin 14 case PPC_HI6_STB: break;
2923 dpavlin 20 case PPC_HI6_STBU: update=1; break;
2924     case PPC_HI6_STH: size=1; break;
2925     case PPC_HI6_STHU: size=1; update=1; break;
2926     case PPC_HI6_STW: size=2; break;
2927     case PPC_HI6_STWU: size=2; update=1; break;
2928 dpavlin 24 case PPC_HI6_STD: size=3; break;
2929 dpavlin 20 case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;
2930     case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;
2931 dpavlin 14 }
2932 dpavlin 20 if (ic->f == NULL) {
2933 dpavlin 14 ic->f =
2934     #ifdef MODE32
2935     ppc32_loadstore
2936     #else
2937     ppc_loadstore
2938     #endif
2939     [size + 4*zero + 8*load + (imm==0? 16 : 0)
2940     + 32*update];
2941     }
2942     if (ra == 0 && update) {
2943     fatal("TODO: ra=0 && update?\n");
2944     goto bad;
2945     }
2946     if (fp)
2947     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
2948     else
2949     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2950     if (ra == 0)
2951     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
2952     else
2953     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2954     ic->arg[2] = (ssize_t)imm;
2955     break;
2956    
2957     case PPC_HI6_BC:
2958     aa_bit = (iword >> 1) & 1;
2959     lk_bit = iword & 1;
2960     bo = (iword >> 21) & 31;
2961     bi = (iword >> 16) & 31;
2962     tmp_addr = (int64_t)(int16_t)(iword & 0xfffc);
2963     if (aa_bit) {
2964     fatal("aa_bit: NOT YET\n");
2965     goto bad;
2966     }
2967 dpavlin 20 if (lk_bit) {
2968     ic->f = instr(bcl);
2969     samepage_function = instr(bcl_samepage);
2970     } else {
2971     ic->f = instr(bc);
2972 dpavlin 22 if ((bo & 0x14) == 0x04) {
2973     samepage_function = bo & 8?
2974     instr(bc_samepage_simple1) :
2975     instr(bc_samepage_simple0);
2976     } else
2977 dpavlin 20 samepage_function = instr(bc_samepage);
2978     }
2979 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2980 dpavlin 14 ic->arg[1] = bo;
2981 dpavlin 22 ic->arg[2] = 31-bi;
2982 dpavlin 14 /* Branches are calculated as cur PC + offset. */
2983     /* Special case: branch within the same page: */
2984     {
2985     uint64_t mask_within_page =
2986     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2987     uint64_t old_pc = addr;
2988 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2989 dpavlin 14 if ((old_pc & ~mask_within_page) ==
2990     (new_pc & ~mask_within_page)) {
2991     ic->f = samepage_function;
2992     ic->arg[0] = (size_t) (
2993     cpu->cd.ppc.cur_ic_page +
2994     ((new_pc & mask_within_page) >> 2));
2995     }
2996     }
2997     break;
2998    
2999     case PPC_HI6_SC:
3000     ic->arg[0] = (iword >> 5) & 0x7f;
3001 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
3002 dpavlin 14 if (cpu->machine->userland_emul != NULL)
3003     ic->f = instr(user_syscall);
3004 dpavlin 20 else if (iword == 0x44ee0002) {
3005 dpavlin 14 /* Special case/magic hack for OpenFirmware emul: */
3006 dpavlin 20 ic->f = instr(openfirmware);
3007     } else
3008     ic->f = instr(sc);
3009 dpavlin 14 break;
3010    
3011     case PPC_HI6_B:
3012     aa_bit = (iword & 2) >> 1;
3013     lk_bit = iword & 1;
3014     tmp_addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
3015     tmp_addr = (int64_t)tmp_addr >> 6;
3016     if (lk_bit) {
3017     if (cpu->machine->show_trace_tree) {
3018     ic->f = instr(bl_trace);
3019     samepage_function = instr(bl_samepage_trace);
3020     } else {
3021     ic->f = instr(bl);
3022     samepage_function = instr(bl_samepage);
3023     }
3024     } else {
3025     ic->f = instr(b);
3026     samepage_function = instr(b_samepage);
3027     }
3028 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
3029     ic->arg[1] = (addr & 0xffc) + 4;
3030 dpavlin 14 /* Branches are calculated as cur PC + offset. */
3031     /* Special case: branch within the same page: */
3032     {
3033     uint64_t mask_within_page =
3034     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
3035     uint64_t old_pc = addr;
3036 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
3037 dpavlin 14 if ((old_pc & ~mask_within_page) ==
3038     (new_pc & ~mask_within_page)) {
3039     ic->f = samepage_function;
3040     ic->arg[0] = (size_t) (
3041     cpu->cd.ppc.cur_ic_page +
3042     ((new_pc & mask_within_page) >> 2));
3043     }
3044     }
3045 dpavlin 20 if (aa_bit) {
3046     if (lk_bit) {
3047     if (cpu->machine->show_trace_tree) {
3048     ic->f = instr(bla_trace);
3049     } else {
3050     ic->f = instr(bla);
3051     }
3052     } else {
3053     ic->f = instr(ba);
3054     }
3055     ic->arg[0] = (ssize_t)tmp_addr;
3056     }
3057 dpavlin 14 break;
3058    
3059     case PPC_HI6_19:
3060     xo = (iword >> 1) & 1023;
3061     switch (xo) {
3062    
3063     case PPC_19_BCLR:
3064     case PPC_19_BCCTR:
3065     bo = (iword >> 21) & 31;
3066     bi = (iword >> 16) & 31;
3067     bh = (iword >> 11) & 3;
3068     lk_bit = iword & 1;
3069     if (xo == PPC_19_BCLR) {
3070     if (lk_bit)
3071     ic->f = instr(bclr_l);
3072 dpavlin 20 else {
3073 dpavlin 14 ic->f = instr(bclr);
3074 dpavlin 20 if (!cpu->machine->show_trace_tree &&
3075     (bo & 0x14) == 0x14)
3076     ic->f = instr(bclr_20);
3077     }
3078 dpavlin 14 } else {
3079     if (lk_bit)
3080     ic->f = instr(bcctr_l);
3081     else
3082     ic->f = instr(bcctr);
3083     }
3084     ic->arg[0] = bo;
3085 dpavlin 20 ic->arg[1] = 31 - bi;
3086 dpavlin 14 ic->arg[2] = bh;
3087     break;
3088    
3089     case PPC_19_ISYNC:
3090     /* TODO */
3091     ic->f = instr(nop);
3092     break;
3093    
3094     case PPC_19_RFI:
3095     ic->f = instr(rfi);
3096     break;
3097    
3098 dpavlin 24 case PPC_19_RFID:
3099     ic->f = instr(rfid);
3100     break;
3101    
3102 dpavlin 14 case PPC_19_MCRF:
3103     bf = (iword >> 23) & 7;
3104     bfa = (iword >> 18) & 7;
3105 dpavlin 20 ic->arg[0] = 28 - 4*bf;
3106     ic->arg[1] = 28 - 4*bfa;
3107 dpavlin 14 ic->f = instr(mcrf);
3108     break;
3109    
3110     case PPC_19_CRAND:
3111     case PPC_19_CRANDC:
3112     case PPC_19_CREQV:
3113     case PPC_19_CROR:
3114 dpavlin 22 case PPC_19_CRORC:
3115 dpavlin 20 case PPC_19_CRNOR:
3116 dpavlin 14 case PPC_19_CRXOR:
3117     switch (xo) {
3118     case PPC_19_CRAND: ic->f = instr(crand); break;
3119     case PPC_19_CRANDC: ic->f = instr(crandc); break;
3120     case PPC_19_CREQV: ic->f = instr(creqv); break;
3121     case PPC_19_CROR: ic->f = instr(cror); break;
3122 dpavlin 22 case PPC_19_CRORC: ic->f = instr(crorc); break;
3123 dpavlin 20 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3124 dpavlin 14 case PPC_19_CRXOR: ic->f = instr(crxor); break;
3125     }
3126     ic->arg[0] = iword;
3127     break;
3128    
3129     default:goto bad;
3130     }
3131     break;
3132    
3133 dpavlin 20 case PPC_HI6_RLWNM:
3134     case PPC_HI6_RLWINM:
3135     ra = (iword >> 16) & 31;
3136     mb = (iword >> 6) & 31;
3137     me = (iword >> 1) & 31;
3138     rc = iword & 1;
3139     mask = 0;
3140     for (;;) {
3141     mask |= ((uint32_t)0x80000000 >> mb);
3142     if (mb == me)
3143     break;
3144     mb ++; mb &= 31;
3145     }
3146     switch (main_opcode) {
3147     case PPC_HI6_RLWNM:
3148     ic->f = rc? instr(rlwnm_dot) : instr(rlwnm); break;
3149     case PPC_HI6_RLWINM:
3150     ic->f = rc? instr(rlwinm_dot) : instr(rlwinm); break;
3151     }
3152     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3153     ic->arg[1] = mask;
3154     ic->arg[2] = (uint32_t)iword;
3155     break;
3156    
3157 dpavlin 14 case PPC_HI6_RLWIMI:
3158     rs = (iword >> 21) & 31;
3159     ra = (iword >> 16) & 31;
3160 dpavlin 20 ic->f = instr(rlwimi);
3161 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3162     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3163     ic->arg[2] = (uint32_t)iword;
3164     break;
3165    
3166     case PPC_HI6_LMW:
3167     case PPC_HI6_STMW:
3168     /* NOTE: Loads use rt, not rs. */
3169     rs = (iword >> 21) & 31;
3170     ra = (iword >> 16) & 31;
3171     ic->arg[0] = rs;
3172     if (ra == 0)
3173     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3174     else
3175     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3176     ic->arg[2] = (int32_t)(int16_t)iword;
3177     switch (main_opcode) {
3178     case PPC_HI6_LMW:
3179     ic->f = instr(lmw);
3180     break;
3181     case PPC_HI6_STMW:
3182     ic->f = instr(stmw);
3183     break;
3184     }
3185     break;
3186    
3187     case PPC_HI6_30:
3188     xo = (iword >> 2) & 7;
3189     switch (xo) {
3190    
3191 dpavlin 24 case PPC_30_RLDICL:
3192 dpavlin 14 case PPC_30_RLDICR:
3193 dpavlin 24 case PPC_30_RLDIMI:
3194     switch (xo) {
3195     case PPC_30_RLDICL: ic->f = instr(rldicl); break;
3196     case PPC_30_RLDICR: ic->f = instr(rldicr); break;
3197     case PPC_30_RLDIMI: ic->f = instr(rldimi); break;
3198     }
3199 dpavlin 14 ic->arg[0] = iword;
3200     if (cpu->cd.ppc.bits == 32) {
3201 dpavlin 24 fatal("TODO: rld* in 32-bit mode?\n");
3202 dpavlin 14 goto bad;
3203     }
3204     break;
3205    
3206     default:goto bad;
3207     }
3208     break;
3209    
3210     case PPC_HI6_31:
3211     xo = (iword >> 1) & 1023;
3212     switch (xo) {
3213    
3214     case PPC_31_CMPL:
3215     case PPC_31_CMP:
3216     bf = (iword >> 23) & 7;
3217     l_bit = (iword >> 21) & 1;
3218     ra = (iword >> 16) & 31;
3219     rb = (iword >> 11) & 31;
3220     if (xo == PPC_31_CMPL) {
3221     if (l_bit)
3222     ic->f = instr(cmpld);
3223     else
3224     ic->f = instr(cmplw);
3225     } else {
3226     if (l_bit)
3227     ic->f = instr(cmpd);
3228 dpavlin 22 else {
3229     if (bf == 0)
3230     ic->f = instr(cmpw_cr0);
3231     else
3232     ic->f = instr(cmpw);
3233     }
3234 dpavlin 14 }
3235     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3236     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3237 dpavlin 20 ic->arg[2] = 28 - 4*bf;
3238 dpavlin 14 break;
3239    
3240     case PPC_31_CNTLZW:
3241     rs = (iword >> 21) & 31;
3242     ra = (iword >> 16) & 31;
3243     rc = iword & 1;
3244     if (rc) {
3245     fatal("TODO: rc\n");
3246     goto bad;
3247     }
3248     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3249     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3250     ic->f = instr(cntlzw);
3251     break;
3252    
3253     case PPC_31_MFSPR:
3254     rt = (iword >> 21) & 31;
3255     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3256 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3257 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3258 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3259 dpavlin 14 switch (spr) {
3260 dpavlin 20 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3261     default: ic->f = instr(mfspr);
3262 dpavlin 14 }
3263     break;
3264    
3265     case PPC_31_MTSPR:
3266     rs = (iword >> 21) & 31;
3267     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3268 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3269 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3270 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3271 dpavlin 22 switch (spr) {
3272     case SPR_LR:
3273     ic->f = instr(mtlr);
3274     break;
3275     case SPR_CTR:
3276     ic->f = instr(mtctr);
3277     break;
3278     default:ic->f = instr(mtspr);
3279     }
3280 dpavlin 14 break;
3281    
3282     case PPC_31_MFCR:
3283     rt = (iword >> 21) & 31;
3284     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3285     ic->f = instr(mfcr);
3286     break;
3287    
3288     case PPC_31_MFMSR:
3289     rt = (iword >> 21) & 31;
3290     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3291     ic->f = instr(mfmsr);
3292     break;
3293    
3294     case PPC_31_MTMSR:
3295 dpavlin 24 case PPC_31_MTMSRD:
3296 dpavlin 14 rs = (iword >> 21) & 31;
3297     l_bit = (iword >> 16) & 1;
3298     if (l_bit) {
3299     fatal("TODO: mtmsr l-bit\n");
3300     goto bad;
3301     }
3302     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3303 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
3304 dpavlin 24 ic->arg[2] = xo == PPC_31_MTMSRD;
3305 dpavlin 14 ic->f = instr(mtmsr);
3306     break;
3307    
3308     case PPC_31_MTCRF:
3309     rs = (iword >> 21) & 31;
3310     {
3311     int i, fxm = (iword >> 12) & 255;
3312     uint32_t tmp = 0;
3313     for (i=0; i<8; i++, fxm <<= 1) {
3314     tmp <<= 4;
3315     if (fxm & 128)
3316     tmp |= 0xf;
3317     }
3318     ic->arg[1] = (uint32_t)tmp;
3319     }
3320     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3321     ic->f = instr(mtcrf);
3322     break;
3323    
3324     case PPC_31_MFSRIN:
3325     case PPC_31_MTSRIN:
3326     rt = (iword >> 21) & 31;
3327     rb = (iword >> 11) & 31;
3328     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3329     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3330     switch (xo) {
3331     case PPC_31_MFSRIN: ic->f = instr(mfsrin); break;
3332     case PPC_31_MTSRIN: ic->f = instr(mtsrin); break;
3333     }
3334     if (cpu->cd.ppc.bits == 64) {
3335     fatal("Not yet for 64-bit mode\n");
3336     goto bad;
3337     }
3338     break;
3339    
3340 dpavlin 20 case PPC_31_MFSR:
3341 dpavlin 14 case PPC_31_MTSR:
3342     rt = (iword >> 21) & 31;
3343     ic->arg[0] = (iword >> 16) & 15;
3344     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3345 dpavlin 20 switch (xo) {
3346     case PPC_31_MFSR: ic->f = instr(mfsr); break;
3347     case PPC_31_MTSR: ic->f = instr(mtsr); break;
3348     }
3349 dpavlin 14 if (cpu->cd.ppc.bits == 64) {
3350     fatal("Not yet for 64-bit mode\n");
3351     goto bad;
3352     }
3353     break;
3354    
3355     case PPC_31_SRAWI:
3356     rs = (iword >> 21) & 31;
3357     ra = (iword >> 16) & 31;
3358     sh = (iword >> 11) & 31;
3359     rc = iword & 1;
3360     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3361     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3362     ic->arg[2] = sh;
3363     if (rc)
3364     ic->f = instr(srawi_dot);
3365     else
3366     ic->f = instr(srawi);
3367     break;
3368    
3369     case PPC_31_SYNC:
3370 dpavlin 24 case PPC_31_DSSALL:
3371 dpavlin 14 case PPC_31_EIEIO:
3372     case PPC_31_DCBST:
3373     case PPC_31_DCBTST:
3374     case PPC_31_DCBF:
3375     case PPC_31_DCBT:
3376     case PPC_31_ICBI:
3377     ic->f = instr(nop);
3378     break;
3379    
3380     case PPC_31_DCBZ:
3381     ra = (iword >> 16) & 31;
3382     rb = (iword >> 11) & 31;
3383     if (ra == 0)
3384     ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);
3385     else
3386     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3387     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3388 dpavlin 20 ic->arg[2] = addr & 0xfff;
3389 dpavlin 14 ic->f = instr(dcbz);
3390     break;
3391    
3392 dpavlin 20 case PPC_31_TLBIA:
3393     ic->f = instr(tlbia);
3394     break;
3395    
3396     case PPC_31_TLBSYNC:
3397     /* According to IBM, "Ensures that a tlbie and
3398     tlbia instruction executed by one processor has
3399     completed on all other processors.", which in
3400     GXemul means a nop :-) */
3401     ic->f = instr(nop);
3402     break;
3403    
3404 dpavlin 14 case PPC_31_TLBIE:
3405 dpavlin 20 /* TODO: POWER also uses ra? */
3406     rb = (iword >> 11) & 31;
3407     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3408 dpavlin 14 ic->f = instr(tlbie);
3409     break;
3410    
3411 dpavlin 20 case PPC_31_TLBLD: /* takes an arg */
3412     rb = (iword >> 11) & 31;
3413     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3414     ic->f = instr(tlbld);
3415     break;
3416    
3417     case PPC_31_TLBLI: /* takes an arg */
3418     rb = (iword >> 11) & 31;
3419     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3420     ic->f = instr(tlbli);
3421     break;
3422    
3423 dpavlin 22 case PPC_31_TLBSX_DOT:
3424     /* TODO */
3425     ic->f = instr(tlbsx_dot);
3426     break;
3427    
3428 dpavlin 14 case PPC_31_MFTB:
3429     rt = (iword >> 21) & 31;
3430     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3431     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3432     switch (spr) {
3433     case 268: ic->f = instr(mftb); break;
3434     case 269: ic->f = instr(mftbu); break;
3435     default:fatal("mftb spr=%i?\n", spr);
3436     goto bad;
3437     }
3438     break;
3439    
3440     case PPC_31_NEG:
3441     rt = (iword >> 21) & 31;
3442     ra = (iword >> 16) & 31;
3443     rc = iword & 1;
3444     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3445     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3446     if (rc)
3447     ic->f = instr(neg_dot);
3448     else
3449     ic->f = instr(neg);
3450     break;
3451    
3452     case PPC_31_LWARX:
3453     case PPC_31_LDARX:
3454     case PPC_31_STWCX_DOT:
3455     case PPC_31_STDCX_DOT:
3456     ic->arg[0] = iword;
3457     ic->f = instr(llsc);
3458     break;
3459    
3460 dpavlin 20 case PPC_31_LSWI:
3461     case PPC_31_STSWI:
3462     rs = (iword >> 21) & 31;
3463     ra = (iword >> 16) & 31;
3464     nb = (iword >> 11) & 31;
3465     ic->arg[0] = rs;
3466     if (ra == 0)
3467     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3468     else
3469     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3470     ic->arg[2] = nb == 0? 32 : nb;
3471     switch (xo) {
3472     case PPC_31_LSWI: ic->f = instr(lswi); break;
3473     case PPC_31_STSWI: ic->f = instr(stswi); break;
3474     }
3475     break;
3476    
3477 dpavlin 22 case PPC_31_WRTEEI:
3478     ic->arg[0] = iword & 0x8000;
3479     ic->f = instr(wrteei);
3480     break;
3481    
3482 dpavlin 20 case 0x1c3:
3483     fatal("[ mtdcr: TODO ]\n");
3484     ic->f = instr(nop);
3485     break;
3486    
3487 dpavlin 14 case PPC_31_LBZX:
3488     case PPC_31_LBZUX:
3489 dpavlin 20 case PPC_31_LHAX:
3490     case PPC_31_LHAUX:
3491 dpavlin 14 case PPC_31_LHZX:
3492     case PPC_31_LHZUX:
3493     case PPC_31_LWZX:
3494     case PPC_31_LWZUX:
3495 dpavlin 20 case PPC_31_LHBRX:
3496     case PPC_31_LWBRX:
3497     case PPC_31_LFDX:
3498     case PPC_31_LFSX:
3499 dpavlin 14 case PPC_31_STBX:
3500     case PPC_31_STBUX:
3501     case PPC_31_STHX:
3502     case PPC_31_STHUX:
3503     case PPC_31_STWX:
3504     case PPC_31_STWUX:
3505     case PPC_31_STDX:
3506     case PPC_31_STDUX:
3507 dpavlin 20 case PPC_31_STHBRX:
3508     case PPC_31_STWBRX:
3509     case PPC_31_STFDX:
3510     case PPC_31_STFSX:
3511 dpavlin 14 rs = (iword >> 21) & 31;
3512     ra = (iword >> 16) & 31;
3513     rb = (iword >> 11) & 31;
3514     if (ra == 0)
3515     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3516     else
3517     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3518     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3519     load = 0; zero = 1; size = 0; update = 0;
3520 dpavlin 20 byterev = 0; fp = 0;
3521     ic->f = NULL;
3522 dpavlin 14 switch (xo) {
3523     case PPC_31_LBZX: load = 1; break;
3524 dpavlin 20 case PPC_31_LBZUX: load=update=1; break;
3525     case PPC_31_LHAX: size=1; load=1; zero=0; break;
3526     case PPC_31_LHAUX: size=1; load=update=1; zero=0; break;
3527     case PPC_31_LHZX: size=1; load=1; break;
3528     case PPC_31_LHZUX: size=1; load=update = 1; break;
3529     case PPC_31_LWZX: size=2; load=1; break;
3530     case PPC_31_LWZUX: size=2; load=update = 1; break;
3531     case PPC_31_LHBRX: size=1; load=1; byterev=1;
3532     ic->f = instr(lhbrx); break;
3533     case PPC_31_LWBRX: size=2; load=1; byterev=1;
3534     ic->f = instr(lwbrx); break;
3535     case PPC_31_LFDX: size=3; load=1; fp=1;
3536     ic->f = instr(lfdx); break;
3537     case PPC_31_LFSX: size=2; load=1; fp=1;
3538     ic->f = instr(lfsx); break;
3539 dpavlin 14 case PPC_31_STBX: break;
3540     case PPC_31_STBUX: update = 1; break;
3541 dpavlin 20 case PPC_31_STHX: size=1; break;
3542     case PPC_31_STHUX: size=1; update = 1; break;
3543     case PPC_31_STWX: size=2; break;
3544     case PPC_31_STWUX: size=2; update = 1; break;
3545     case PPC_31_STDX: size=3; break;
3546     case PPC_31_STDUX: size=3; update = 1; break;
3547     case PPC_31_STHBRX:size=1; byterev = 1;
3548     ic->f = instr(sthbrx); break;
3549     case PPC_31_STWBRX:size=2; byterev = 1;
3550     ic->f = instr(stwbrx); break;
3551     case PPC_31_STFDX: size=3; fp=1;
3552     ic->f = instr(stfdx); break;
3553     case PPC_31_STFSX: size=2; fp=1;
3554     ic->f = instr(stfsx); break;
3555 dpavlin 14 }
3556 dpavlin 20 if (fp)
3557     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
3558     else
3559     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3560     if (!byterev && ic->f == NULL) {
3561     ic->f =
3562 dpavlin 14 #ifdef MODE32
3563 dpavlin 20 ppc32_loadstore_indexed
3564 dpavlin 14 #else
3565 dpavlin 20 ppc_loadstore_indexed
3566 dpavlin 14 #endif
3567 dpavlin 20 [size + 4*zero + 8*load + 16*update];
3568     }
3569 dpavlin 14 if (ra == 0 && update) {
3570     fatal("TODO: ra=0 && update?\n");
3571     goto bad;
3572     }
3573     break;
3574    
3575     case PPC_31_EXTSB:
3576     case PPC_31_EXTSH:
3577     case PPC_31_EXTSW:
3578     case PPC_31_SLW:
3579 dpavlin 24 case PPC_31_SLD:
3580 dpavlin 14 case PPC_31_SRAW:
3581     case PPC_31_SRW:
3582     case PPC_31_AND:
3583     case PPC_31_NAND:
3584     case PPC_31_ANDC:
3585     case PPC_31_NOR:
3586     case PPC_31_OR:
3587     case PPC_31_ORC:
3588     case PPC_31_XOR:
3589 dpavlin 24 case PPC_31_EQV:
3590 dpavlin 14 rs = (iword >> 21) & 31;
3591     ra = (iword >> 16) & 31;
3592     rb = (iword >> 11) & 31;
3593     rc = iword & 1;
3594     rc_f = NULL;
3595     switch (xo) {
3596     case PPC_31_EXTSB:ic->f = instr(extsb);
3597     rc_f = instr(extsb_dot); break;
3598     case PPC_31_EXTSH:ic->f = instr(extsh);
3599     rc_f = instr(extsh_dot); break;
3600     case PPC_31_EXTSW:ic->f = instr(extsw);
3601     rc_f = instr(extsw_dot); break;
3602     case PPC_31_SLW: ic->f = instr(slw);
3603     rc_f = instr(slw_dot); break;
3604 dpavlin 24 case PPC_31_SLD: ic->f = instr(sld);
3605     rc_f = instr(sld_dot); break;
3606 dpavlin 14 case PPC_31_SRAW: ic->f = instr(sraw);
3607     rc_f = instr(sraw_dot); break;
3608     case PPC_31_SRW: ic->f = instr(srw);
3609     rc_f = instr(srw_dot); break;
3610     case PPC_31_AND: ic->f = instr(and);
3611     rc_f = instr(and_dot); break;
3612     case PPC_31_NAND: ic->f = instr(nand);
3613     rc_f = instr(nand_dot); break;
3614     case PPC_31_ANDC: ic->f = instr(andc);
3615     rc_f = instr(andc_dot); break;
3616     case PPC_31_NOR: ic->f = instr(nor);
3617     rc_f = instr(nor_dot); break;
3618 dpavlin 22 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3619     : instr(or);
3620 dpavlin 14 rc_f = instr(or_dot); break;
3621     case PPC_31_ORC: ic->f = instr(orc);
3622     rc_f = instr(orc_dot); break;
3623     case PPC_31_XOR: ic->f = instr(xor);
3624     rc_f = instr(xor_dot); break;
3625 dpavlin 24 case PPC_31_EQV: ic->f = instr(eqv);
3626     rc_f = instr(eqv_dot); break;
3627 dpavlin 14 }
3628     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3629     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3630     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3631     if (rc)
3632     ic->f = rc_f;
3633     break;
3634    
3635     case PPC_31_MULLW:
3636     case PPC_31_MULHW:
3637     case PPC_31_MULHWU:
3638     case PPC_31_DIVW:
3639     case PPC_31_DIVWU:
3640     case PPC_31_ADD:
3641     case PPC_31_ADDC:
3642     case PPC_31_ADDE:
3643     case PPC_31_ADDME:
3644     case PPC_31_ADDZE:
3645     case PPC_31_SUBF:
3646     case PPC_31_SUBFC:
3647     case PPC_31_SUBFE:
3648 dpavlin 20 case PPC_31_SUBFME:
3649 dpavlin 14 case PPC_31_SUBFZE:
3650     rt = (iword >> 21) & 31;
3651     ra = (iword >> 16) & 31;
3652     rb = (iword >> 11) & 31;
3653     oe_bit = (iword >> 10) & 1;
3654     rc = iword & 1;
3655     if (oe_bit) {
3656     fatal("oe_bit not yet implemented\n");
3657     goto bad;
3658     }
3659     switch (xo) {
3660     case PPC_31_MULLW: ic->f = instr(mullw); break;
3661     case PPC_31_MULHW: ic->f = instr(mulhw); break;
3662     case PPC_31_MULHWU: ic->f = instr(mulhwu); break;
3663     case PPC_31_DIVW: ic->f = instr(divw); n64=1; break;
3664     case PPC_31_DIVWU: ic->f = instr(divwu); n64=1; break;
3665     case PPC_31_ADD: ic->f = instr(add); break;
3666     case PPC_31_ADDC: ic->f = instr(addc); n64=1; break;
3667     case PPC_31_ADDE: ic->f = instr(adde); n64=1; break;
3668     case PPC_31_ADDME: ic->f = instr(addme); n64=1; break;
3669     case PPC_31_ADDZE: ic->f = instr(addze); n64=1; break;
3670     case PPC_31_SUBF: ic->f = instr(subf); break;
3671     case PPC_31_SUBFC: ic->f = instr(subfc); break;
3672     case PPC_31_SUBFE: ic->f = instr(subfe); n64=1; break;
3673 dpavlin 20 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3674 dpavlin 14 case PPC_31_SUBFZE: ic->f = instr(subfze); n64=1;break;
3675     }
3676     if (rc) {
3677     switch (xo) {
3678     case PPC_31_ADD:
3679     ic->f = instr(add_dot); break;
3680     case PPC_31_ADDE:
3681     ic->f = instr(adde_dot); break;
3682     case PPC_31_ADDME:
3683     ic->f = instr(addme_dot); break;
3684     case PPC_31_ADDZE:
3685     ic->f = instr(addze_dot); break;
3686 dpavlin 20 case PPC_31_DIVW:
3687     ic->f = instr(divw_dot); break;
3688     case PPC_31_DIVWU:
3689     ic->f = instr(divwu_dot); break;
3690     case PPC_31_MULLW:
3691     ic->f = instr(mullw_dot); break;
3692     case PPC_31_MULHW:
3693     ic->f = instr(mulhw_dot); break;
3694     case PPC_31_MULHWU:
3695     ic->f = instr(mulhwu_dot); break;
3696 dpavlin 14 case PPC_31_SUBF:
3697     ic->f = instr(subf_dot); break;
3698     case PPC_31_SUBFC:
3699     ic->f = instr(subfc_dot); break;
3700     case PPC_31_SUBFE:
3701     ic->f = instr(subfe_dot); break;
3702 dpavlin 20 case PPC_31_SUBFME:
3703     ic->f = instr(subfme_dot); break;
3704 dpavlin 14 case PPC_31_SUBFZE:
3705     ic->f = instr(subfze_dot); break;
3706     default:fatal("RC bit not yet implemented\n");
3707     goto bad;
3708     }
3709     }
3710     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3711     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3712     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3713     if (cpu->cd.ppc.bits == 64 && n64) {
3714     fatal("Not yet for 64-bit mode\n");
3715     goto bad;
3716     }
3717     break;
3718    
3719 dpavlin 22 case PPC_31_LVX:
3720 dpavlin 24 case PPC_31_LVXL:
3721 dpavlin 22 case PPC_31_STVX:
3722     case PPC_31_STVXL:
3723 dpavlin 24 load = 0;
3724     switch (xo) {
3725     case PPC_31_LVX:
3726     case PPC_31_LVXL:
3727     load = 1; break;
3728     }
3729     rs = (iword >> 21) & 31;
3730     ra = (iword >> 16) & 31;
3731     rb = (iword >> 11) & 31;
3732 dpavlin 34 ic->arg[0] = rs;
3733 dpavlin 24 if (ra == 0)
3734     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3735     else
3736     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3737     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3738 dpavlin 34 ic->f = load? instr(lvx) : instr(stvx);
3739 dpavlin 22 break;
3740    
3741 dpavlin 14 default:goto bad;
3742     }
3743     break;
3744    
3745 dpavlin 20 case PPC_HI6_59:
3746     xo = (iword >> 1) & 1023;
3747 dpavlin 14 rt = (iword >> 21) & 31;
3748     ra = (iword >> 16) & 31;
3749     rb = (iword >> 11) & 31;
3750 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
3751 dpavlin 14 rc = iword & 1;
3752    
3753 dpavlin 20 if (rc) {
3754     fatal("Floating point (59) with rc bit! TODO\n");
3755     goto bad;
3756     }
3757 dpavlin 14
3758 dpavlin 20 /* NOTE: Some floating-point instructions are selected
3759     using only the lowest 5 bits, not all 10! */
3760     switch (xo & 31) {
3761     case PPC_59_FDIVS:
3762     case PPC_59_FSUBS:
3763     case PPC_59_FADDS:
3764     switch (xo & 31) {
3765     case PPC_59_FDIVS: ic->f = instr(fdivs); break;
3766     case PPC_59_FSUBS: ic->f = instr(fsubs); break;
3767     case PPC_59_FADDS: ic->f = instr(fadds); break;
3768 dpavlin 14 }
3769 dpavlin 20 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3770     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3771     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3772 dpavlin 14 break;
3773 dpavlin 20 case PPC_59_FMULS:
3774     ic->f = instr(fmuls);
3775     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3776     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3777     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3778     break;
3779     default:/* Use all 10 bits of xo: */
3780     switch (xo) {
3781     default:goto bad;
3782     }
3783     }
3784     break;
3785 dpavlin 14
3786 dpavlin 20 case PPC_HI6_63:
3787     xo = (iword >> 1) & 1023;
3788     rt = (iword >> 21) & 31;
3789     ra = (iword >> 16) & 31;
3790     rb = (iword >> 11) & 31;
3791     rs = (iword >> 6) & 31; /* actually frc */
3792     rc = iword & 1;
3793    
3794     if (rc) {
3795     fatal("Floating point (63) with rc bit! TODO\n");
3796     goto bad;
3797 dpavlin 14 }
3798 dpavlin 20
3799     /* NOTE: Some floating-point instructions are selected
3800     using only the lowest 5 bits, not all 10! */
3801     switch (xo & 31) {
3802     case PPC_63_FDIV:
3803     case PPC_63_FSUB:
3804     case PPC_63_FADD:
3805     switch (xo & 31) {
3806     case PPC_63_FDIV: ic->f = instr(fdiv); break;
3807     case PPC_63_FSUB: ic->f = instr(fsub); break;
3808     case PPC_63_FADD: ic->f = instr(fadd); break;
3809     }
3810     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3811     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3812     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3813     break;
3814     case PPC_63_FMUL:
3815     ic->f = instr(fmul);
3816     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3817     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3818     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3819     break;
3820     case PPC_63_FMSUB:
3821     case PPC_63_FMADD:
3822     switch (xo & 31) {
3823     case PPC_63_FMSUB: ic->f = instr(fmsub); break;
3824     case PPC_63_FMADD: ic->f = instr(fmadd); break;
3825     }
3826     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3827     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3828     ic->arg[2] = iword;
3829     break;
3830     default:/* Use all 10 bits of xo: */
3831     switch (xo) {
3832     case PPC_63_FCMPU:
3833     ic->f = instr(fcmpu);
3834     ic->arg[0] = 28 - 4*(rt >> 2);
3835     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3836     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3837     break;
3838     case PPC_63_FRSP:
3839     case PPC_63_FCTIWZ:
3840     case PPC_63_FNEG:
3841     case PPC_63_FMR:
3842     switch (xo) {
3843     case PPC_63_FRSP: ic->f = instr(frsp); break;
3844     case PPC_63_FCTIWZ: ic->f = instr(fctiwz);break;
3845     case PPC_63_FNEG: ic->f = instr(fneg); break;
3846     case PPC_63_FMR: ic->f = instr(fmr); break;
3847     }
3848     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3849     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3850     break;
3851     case PPC_63_MFFS:
3852     ic->f = instr(mffs);
3853     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3854     break;
3855     case PPC_63_MTFSF:
3856     ic->f = instr(mtfsf);
3857     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3858     ic->arg[1] = 0;
3859     for (bi=7; bi>=0; bi--) {
3860     ic->arg[1] <<= 8;
3861     if (iword & (1 << (17+bi)))
3862     ic->arg[1] |= 0xf;
3863     }
3864     break;
3865     default:goto bad;
3866     }
3867     }
3868 dpavlin 14 break;
3869    
3870     default:goto bad;
3871     }
3872    
3873    
3874     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3875     #include "cpu_dyntrans.c"
3876     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3877     }
3878    

  ViewVC Help
Powered by ViewVC 1.1.26