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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc_instr.c,v 1.73 2007/02/17 10:06:19 debug Exp $
29 *
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 #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 update_cr0(cpu, reg(ic->arg[1])); }
46 #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47 update_cr0(cpu, reg(ic->arg[2])); }
48
49 #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
62
63
64 /*
65 * nop: Do nothing.
66 */
67 X(nop)
68 {
69 }
70
71
72 /*
73 * invalid: To catch bugs.
74 */
75 X(invalid)
76 {
77 fatal("PPC: invalid(): INTERNAL ERROR\n");
78 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 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
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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
131 tmp2 += (uint32_t)ic->arg[1];
132 if ((tmp2 >> 32) != (tmp >> 32))
133 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
134 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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
149 if (tmp >= reg(ic->arg[0]))
150 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
151 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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
168 tmp2 += (uint32_t)ic->arg[1];
169 if ((tmp2 >> 32) != (tmp >> 32))
170 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
171 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 * arg[1] = 31 - bi
181 * arg[2] = bh
182 */
183 X(bclr)
184 {
185 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
186 int ctr_ok, cond_ok;
187 uint64_t old_pc = cpu->pc;
188 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
189 if (!(bo & 4))
190 cpu->cd.ppc.spr[SPR_CTR] --;
191 ctr_ok = (bo >> 2) & 1;
192 tmp = cpu->cd.ppc.spr[SPR_CTR];
193 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
194 cond_ok = (bo >> 4) & 1;
195 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
196 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 quick_pc_to_pointers(cpu);
213 }
214 }
215 }
216 X(bclr_20)
217 {
218 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
219 quick_pc_to_pointers(cpu);
220 }
221 X(bclr_l)
222 {
223 uint64_t low_pc, old_pc = cpu->pc;
224 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /* ,bh = ic->arg[2]*/;
225 int ctr_ok, cond_ok;
226 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
227 if (!(bo & 4))
228 cpu->cd.ppc.spr[SPR_CTR] --;
229 ctr_ok = (bo >> 2) & 1;
230 tmp = cpu->cd.ppc.spr[SPR_CTR];
231 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
232 cond_ok = (bo >> 4) & 1;
233 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
234
235 /* Calculate return PC: */
236 low_pc = ((size_t)ic - (size_t)
237 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
238 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
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 quick_pc_to_pointers(cpu);
261 }
262 }
263 }
264
265
266 /*
267 * bcctr: Branch Conditional to Count register
268 *
269 * arg[0] = bo
270 * arg[1] = 31 - bi
271 * arg[2] = bh
272 */
273 X(bcctr)
274 {
275 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2]*/;
276 uint64_t old_pc = cpu->pc;
277 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
278 int cond_ok = (bo >> 4) & 1;
279 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
280 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 quick_pc_to_pointers(cpu);
297 }
298 }
299 }
300 X(bcctr_l)
301 {
302 uint64_t low_pc, old_pc = cpu->pc;
303 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2] */;
304 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
305 int cond_ok = (bo >> 4) & 1;
306 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
307
308 /* Calculate return PC: */
309 low_pc = ((size_t)ic - (size_t)
310 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
311 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
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 quick_pc_to_pointers(cpu);
332 }
333 }
334 }
335
336
337 /*
338 * b: Branch (to a different translated page)
339 *
340 * arg[0] = relative offset (as an int32_t) from start of page
341 */
342 X(b)
343 {
344 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
345 cpu->pc += (int32_t)ic->arg[0];
346
347 /* Find the new physical page and update the translation pointers: */
348 quick_pc_to_pointers(cpu);
349 }
350 X(ba)
351 {
352 cpu->pc = (int32_t)ic->arg[0];
353 quick_pc_to_pointers(cpu);
354 }
355
356
357 /*
358 * bc: Branch Conditional (to a different translated page)
359 *
360 * arg[0] = relative offset (as an int32_t) from start of page
361 * arg[1] = bo
362 * arg[2] = 31-bi
363 */
364 X(bc)
365 {
366 MODE_uint_t tmp;
367 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
368 if (!(bo & 4))
369 cpu->cd.ppc.spr[SPR_CTR] --;
370 ctr_ok = (bo >> 2) & 1;
371 tmp = cpu->cd.ppc.spr[SPR_CTR];
372 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
373 cond_ok = (bo >> 4) & 1;
374 cond_ok |= ( ((bo >> 3) & 1) ==
375 ((cpu->cd.ppc.cr >> (bi31m)) & 1) );
376 if (ctr_ok && cond_ok)
377 instr(b)(cpu,ic);
378 }
379 X(bcl)
380 {
381 MODE_uint_t tmp;
382 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
383 int low_pc;
384
385 /* Calculate LR: */
386 low_pc = ((size_t)ic - (size_t)
387 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
388 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
392 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 ((cpu->cd.ppc.cr >> bi31m) & 1) );
400 if (ctr_ok && cond_ok)
401 instr(b)(cpu,ic);
402 }
403
404
405 /*
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 * arg[2] = 31-bi
422 */
423 X(bc_samepage)
424 {
425 MODE_uint_t tmp;
426 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
427 if (!(bo & 4))
428 cpu->cd.ppc.spr[SPR_CTR] --;
429 ctr_ok = (bo >> 2) & 1;
430 tmp = cpu->cd.ppc.spr[SPR_CTR];
431 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
432 cond_ok = (bo >> 4) & 1;
433 cond_ok |= ( ((bo >> 3) & 1) ==
434 ((cpu->cd.ppc.cr >> bi31m) & 1) );
435 if (ctr_ok && cond_ok)
436 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
437 }
438 X(bc_samepage_simple0)
439 {
440 int bi31m = ic->arg[2];
441 if (!((cpu->cd.ppc.cr >> bi31m) & 1))
442 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
443 }
444 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 X(bcl_samepage)
451 {
452 MODE_uint_t tmp;
453 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
454 int low_pc;
455
456 /* Calculate LR: */
457 low_pc = ((size_t)ic - (size_t)
458 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
459 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
463 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 ((cpu->cd.ppc.cr >> bi31m) & 1) );
471 if (ctr_ok && cond_ok)
472 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
473 }
474
475
476 /*
477 * bl: Branch and Link (to a different translated page)
478 *
479 * arg[0] = relative offset (as an int32_t) from start of page
480 * arg[1] = lr offset (relative to start of current page)
481 */
482 X(bl)
483 {
484 /* 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 cpu->pc += (int32_t)ic->arg[0];
488
489 /* Find the new physical page and update the translation pointers: */
490 quick_pc_to_pointers(cpu);
491 }
492 X(bla)
493 {
494 /* 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 cpu->pc = (int32_t)ic->arg[0];
499 quick_pc_to_pointers(cpu);
500 }
501
502
503 /*
504 * bl_trace: Branch and Link (to a different translated page) (with trace)
505 *
506 * arg[0] = relative offset (as an int32_t) from start of page
507 * arg[1] = lr offset (relative to start of current page)
508 */
509 X(bl_trace)
510 {
511 /* Calculate LR: */
512 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
513 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
514
515 /* Calculate new PC from start of page + arg[0] */
516 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
517 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 quick_pc_to_pointers(cpu);
523 }
524 X(bla_trace)
525 {
526 /* 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 cpu->pc = (int32_t)ic->arg[0];
531 cpu_functioncall_trace(cpu, cpu->pc);
532 quick_pc_to_pointers(cpu);
533 }
534
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 * arg[1] = lr offset (relative to start of current page)
541 */
542 X(bl_samepage)
543 {
544 /* Calculate LR: */
545 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
546 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
547
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 * arg[1] = lr offset (relative to start of current page)
557 */
558 X(bl_samepage_trace)
559 {
560 uint32_t low_pc;
561
562 /* Calculate LR: */
563 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
564 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
565
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 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
572 cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
573 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 * arg[2] = 28 - 4*bf
602 */
603 X(cmpd)
604 {
605 int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
606 int bf_shift = ic->arg[2], c;
607 if (tmp < tmp2)
608 c = 8;
609 else if (tmp > tmp2)
610 c = 4;
611 else
612 c = 2;
613 /* 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 }
618
619
620 /*
621 * cmpld: Compare Doubleword, unsigned
622 *
623 * arg[0] = ptr to ra
624 * arg[1] = ptr to rb
625 * arg[2] = 28 - 4*bf
626 */
627 X(cmpld)
628 {
629 uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
630 int bf_shift = ic->arg[2], c;
631 if (tmp < tmp2)
632 c = 8;
633 else if (tmp > tmp2)
634 c = 4;
635 else
636 c = 2;
637 /* 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 }
642
643
644 /*
645 * cmpdi: Compare Doubleword immediate
646 *
647 * arg[0] = ptr to ra
648 * arg[1] = int32_t imm
649 * arg[2] = 28 - 4*bf
650 */
651 X(cmpdi)
652 {
653 int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
654 int bf_shift = ic->arg[2], c;
655 if (tmp < imm)
656 c = 8;
657 else if (tmp > imm)
658 c = 4;
659 else
660 c = 2;
661 /* 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 }
666
667
668 /*
669 * cmpldi: Compare Doubleword immediate, logical
670 *
671 * arg[0] = ptr to ra
672 * arg[1] = int32_t imm
673 * arg[2] = 28 - 4*bf
674 */
675 X(cmpldi)
676 {
677 uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
678 int bf_shift = ic->arg[2], c;
679 if (tmp < imm)
680 c = 8;
681 else if (tmp > imm)
682 c = 4;
683 else
684 c = 2;
685 /* 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 }
690
691
692 /*
693 * cmpw: Compare Word
694 *
695 * arg[0] = ptr to ra
696 * arg[1] = ptr to rb
697 * arg[2] = 28 - 4*bf
698 */
699 X(cmpw)
700 {
701 int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
702 int bf_shift = ic->arg[2], c;
703 if (tmp < tmp2)
704 c = 8;
705 else if (tmp > tmp2)
706 c = 4;
707 else
708 c = 2;
709 /* 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 }
714 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
728
729 /*
730 * cmplw: Compare Word, unsigned
731 *
732 * arg[0] = ptr to ra
733 * arg[1] = ptr to rb
734 * arg[2] = 28 - 4*bf
735 */
736 X(cmplw)
737 {
738 uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
739 int bf_shift = ic->arg[2], c;
740 if (tmp < tmp2)
741 c = 8;
742 else if (tmp > tmp2)
743 c = 4;
744 else
745 c = 2;
746 /* 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 }
751
752
753 /*
754 * cmpwi: Compare Word immediate
755 *
756 * arg[0] = ptr to ra
757 * arg[1] = int32_t imm
758 * arg[2] = 28 - 4*bf
759 */
760 X(cmpwi)
761 {
762 int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
763 int bf_shift = ic->arg[2], c;
764 if (tmp < imm)
765 c = 8;
766 else if (tmp > imm)
767 c = 4;
768 else
769 c = 2;
770 /* 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 }
775 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
789
790 /*
791 * cmplwi: Compare Word immediate, logical
792 *
793 * arg[0] = ptr to ra
794 * arg[1] = int32_t imm
795 * arg[2] = 28 - 4*bf
796 */
797 X(cmplwi)
798 {
799 uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
800 int bf_shift = ic->arg[2], c;
801 if (tmp < imm)
802 c = 8;
803 else if (tmp > imm)
804 c = 4;
805 else
806 c = 2;
807 /* 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 }
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 size_t cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;
825 size_t cleared = 0;
826
827 /* Synchronize the PC first: */
828 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
829
830 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 #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 /* exception */
845 return;
846 }
847
848 cleared += to_clear;
849 addr += to_clear;
850 }
851 }
852
853
854 /*
855 * mtfsf: Copy FPR into the FPSCR.
856 *
857 * arg[0] = ptr to frb
858 * arg[1] = mask
859 */
860 X(mtfsf)
861 {
862 CHECK_FOR_FPU_EXCEPTION;
863 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 CHECK_FOR_FPU_EXCEPTION;
876 (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;
877 }
878
879
880 /*
881 * fmr: Floating-point Move
882 *
883 * arg[0] = ptr to frb
884 * arg[1] = ptr to frt
885 */
886 X(fmr)
887 {
888 /*
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 *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
895 }
896
897
898 /*
899 * 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 CHECK_FOR_FPU_EXCEPTION;
908 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 CHECK_FOR_FPU_EXCEPTION;
926
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 CHECK_FOR_FPU_EXCEPTION;
960
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 uint32_t res = 0;
991
992 CHECK_FOR_FPU_EXCEPTION;
993
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 CHECK_FOR_FPU_EXCEPTION;
1022
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 CHECK_FOR_FPU_EXCEPTION;
1071
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 CHECK_FOR_FPU_EXCEPTION;
1116
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 CHECK_FOR_FPU_EXCEPTION;
1158
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 CHECK_FOR_FPU_EXCEPTION;
1195
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 CHECK_FOR_FPU_EXCEPTION;
1232
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 * 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 uint32_t old_so = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_SO;
1320 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 * mtsr, mtsrin: Move To Segment Register [Indirect]
1366 *
1367 * arg[0] = sr number, or for indirect mode: ptr to rb
1368 * arg[1] = ptr to rt
1369 *
1370 * TODO: These only work for 32-bit mode!
1371 */
1372 X(mtsr)
1373 {
1374 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
1378 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 }
1382 X(mtsrin)
1383 {
1384 int sr_num = reg(ic->arg[0]) >> 28;
1385 uint32_t old = cpu->cd.ppc.sr[sr_num];
1386 cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1387
1388 if (cpu->cd.ppc.sr[sr_num] != old)
1389 cpu->invalidate_translation_caches(cpu, sr_num << 28,
1390 INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1391 }
1392
1393
1394 /*
1395 * mfsrin, mtsrin: Move From/To Segment Register Indirect
1396 *
1397 * arg[0] = sr number, or for indirect mode: ptr to rb
1398 * arg[1] = ptr to rt
1399 */
1400 X(mfsr)
1401 {
1402 /* TODO: This only works for 32-bit mode */
1403 reg(ic->arg[1]) = cpu->cd.ppc.sr[ic->arg[0]];
1404 }
1405 X(mfsrin)
1406 {
1407 /* TODO: This only works for 32-bit mode */
1408 uint32_t sr_num = reg(ic->arg[0]) >> 28;
1409 reg(ic->arg[1]) = cpu->cd.ppc.sr[sr_num];
1410 }
1411
1412
1413 /*
1414 * 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 * 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 * 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 * 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 * rlwinm:
1522 *
1523 * arg[0] = ptr to ra
1524 * arg[1] = mask
1525 * arg[2] = copy of the instruction word
1526 */
1527 X(rlwinm)
1528 {
1529 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 }
1537 DOT0(rlwinm)
1538
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 int sh = (iword >> 11) & 31;
1552 int mb = (iword >> 6) & 31;
1553 int me = (iword >> 1) & 31;
1554 int rc = iword & 1;
1555
1556 tmp = (tmp << sh) | (tmp >> (32-sh));
1557
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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
1588 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 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
1599 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
1600 }
1601 DOT1(srawi)
1602
1603
1604 /*
1605 * mcrf: Move inside condition register
1606 *
1607 * arg[0] = 28-4*bf, arg[1] = 28-4*bfa
1608 */
1609 X(mcrf)
1610 {
1611 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 }
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 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 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 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 * mfspr: Move from SPR
1690 *
1691 * arg[0] = pointer to destination register
1692 * arg[1] = pointer to source SPR
1693 */
1694 X(mfspr) {
1695 /* TODO: Check permission */
1696 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
1716
1717 /*
1718 * mtspr: Move to SPR.
1719 *
1720 * arg[0] = pointer to source register
1721 * arg[1] = pointer to the SPR
1722 */
1723 X(mtspr) {
1724 /* TODO: Check permission */
1725 reg(ic->arg[1]) = reg(ic->arg[0]);
1726 }
1727 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
1734
1735 /*
1736 * rfi[d]: Return from Interrupt
1737 */
1738 X(rfi)
1739 {
1740 uint64_t tmp;
1741
1742 reg_access_msr(cpu, &tmp, 0, 0);
1743 tmp &= ~0xffff;
1744 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & 0xffff);
1745 reg_access_msr(cpu, &tmp, 1, 0);
1746
1747 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1748 quick_pc_to_pointers(cpu);
1749 }
1750 X(rfid)
1751 {
1752 uint64_t tmp, mask = 0x800000000000ff73ULL;
1753
1754 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
1759 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 /*
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 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0, 0);
1785 }
1786
1787
1788 /*
1789 * mtmsr: Move To MSR
1790 *
1791 * arg[0] = pointer to source register
1792 * arg[1] = page offset of the next instruction
1793 * arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd)
1794 */
1795 X(mtmsr)
1796 {
1797 MODE_uint_t old_pc;
1798 uint64_t x = reg(ic->arg[0]);
1799
1800 /* TODO: check permission! */
1801
1802 /* Synchronize the PC (pointing to _after_ this instruction) */
1803 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1804 old_pc = cpu->pc;
1805
1806 if (!ic->arg[2]) {
1807 uint64_t y;
1808 reg_access_msr(cpu, &y, 0, 0);
1809 x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL);
1810 }
1811
1812 reg_access_msr(cpu, &x, 1, 1);
1813
1814 /*
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 }
1822
1823
1824 /*
1825 * 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 * 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 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * (int32_t)ic->arg[1]);
1865 }
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 int rs = ic->arg[0];
1879
1880 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 while (rs <= 31) {
1887 if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1888 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1889 /* exception */
1890 return;
1891 }
1892
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 int rs = ic->arg[0];
1908
1909 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 while (rs <= 31) {
1916 uint32_t tmp = cpu->cd.ppc.gpr[rs];
1917 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 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1926 /* exception */
1927 return;
1928 }
1929
1930 rs ++;
1931 addr += sizeof(uint32_t);
1932 }
1933 }
1934
1935
1936 /*
1937 * 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 * 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 DOT2(extsb)
2024 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 DOT2(extsh)
2032 X(extsw) {
2033 #ifdef MODE32
2034 fatal("TODO: extsw: invalid instruction\n");
2035 #else
2036 reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);
2037 #endif
2038 }
2039 DOT2(extsw)
2040 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2041 << (reg(ic->arg[1]) & 31); }
2042 DOT2(slw)
2043 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 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 X(srw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2068 >> (reg(ic->arg[1]) & 31); }
2069 DOT2(srw)
2070 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
2071 DOT2(and)
2072 X(nand) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) & reg(ic->arg[1])); }
2073 DOT2(nand)
2074 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
2075 DOT2(andc)
2076 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
2077 DOT2(nor)
2078 X(mr) { reg(ic->arg[2]) = reg(ic->arg[1]); }
2079 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
2080 DOT2(or)
2081 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
2082 DOT2(orc)
2083 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
2084 DOT2(xor)
2085 X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); }
2086 DOT2(eqv)
2087
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 DOT1(neg)
2097
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 DOT2(mullw)
2112 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 DOT2(mulhw)
2120 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 DOT2(mulhwu)
2128 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 DOT2(divw)
2139 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 DOT2(divwu)
2150
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 DOT2(add)
2161
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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2176 tmp += (uint32_t)reg(ic->arg[1]);
2177 if ((tmp >> 32) != (tmp2 >> 32))
2178 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2179 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 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2194 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2195 uint64_t tmp2 = tmp;
2196 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2197 tmp += (uint32_t)reg(ic->arg[1]);
2198 if (old_ca)
2199 tmp ++;
2200 if ((tmp >> 32) != (tmp2 >> 32))
2201 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2202 reg(ic->arg[2]) = (uint32_t)tmp;
2203 }
2204 DOT2(adde)
2205 X(addme)
2206 {
2207 /* TODO: this only works in 32-bit mode */
2208 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2209 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2210 uint64_t tmp2 = tmp;
2211 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2212 if (old_ca)
2213 tmp ++;
2214 tmp += 0xffffffffULL;
2215 if ((tmp >> 32) != (tmp2 >> 32))
2216 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2217 reg(ic->arg[2]) = (uint32_t)tmp;
2218 }
2219 DOT2(addme)
2220 X(addze)
2221 {
2222 /* TODO: this only works in 32-bit mode */
2223 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2224 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2225 uint64_t tmp2 = tmp;
2226 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2227 if (old_ca)
2228 tmp ++;
2229 if ((tmp >> 32) != (tmp2 >> 32))
2230 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2231 reg(ic->arg[2]) = (uint32_t)tmp;
2232 }
2233 DOT2(addze)
2234
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 X(subf)
2244 {
2245 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2246 }
2247 DOT2(subf)
2248 X(subfc)
2249 {
2250 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2251 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2252 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2253 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2254 }
2255 DOT2(subfc)
2256 X(subfe)
2257 {
2258 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 if (reg(ic->arg[1]) == reg(ic->arg[0])) {
2261 if (old_ca)
2262 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2263 } else if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2264 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2265
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 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 X(subfze)
2288 {
2289 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2290 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2291 uint64_t tmp2 = tmp;
2292 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2293 if (old_ca)
2294 tmp ++;
2295 if ((tmp >> 32) != (tmp2 >> 32))
2296 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2297 reg(ic->arg[2]) = (uint32_t)tmp;
2298 }
2299 DOT2(subfze)
2300
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 #include "tmp_ppc_loadstore.c"
2314
2315
2316 /*
2317 * lfs, stfs: Load/Store Floating-point Single precision
2318 */
2319 X(lfs)
2320 {
2321 /* Sync. PC in case of an exception, and remember it: */
2322 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2323 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2324 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2325 PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2326 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 /* Sync. PC in case of an exception, and remember it: */
2352 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2353 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2354 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2355 PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2356 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 CHECK_FOR_FPU_EXCEPTION;
2382
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 CHECK_FOR_FPU_EXCEPTION;
2394
2395 /* 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 CHECK_FOR_FPU_EXCEPTION;
2410
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 CHECK_FOR_FPU_EXCEPTION;
2433
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 CHECK_FOR_FPU_EXCEPTION;
2452
2453 /* 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 CHECK_FOR_FPU_EXCEPTION;
2464
2465 /* 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 * 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 * tlbia: TLB invalidate all
2561 */
2562 X(tlbia)
2563 {
2564 fatal("[ tlbia ]\n");
2565 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2566 }
2567
2568
2569 /*
2570 * tlbie: TLB invalidate
2571 */
2572 X(tlbie)
2573 {
2574 /* fatal("[ tlbie ]\n"); */
2575 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2576 INVALIDATE_VADDR);
2577 }
2578
2579
2580 /*
2581 * 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
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 }
2593
2594
2595 /*
2596 * 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
2604 if (!cpu->running) {
2605 cpu->n_translated_instrs --;
2606 cpu->cd.ppc.next_ic = &nothing_call;
2607 }
2608 }
2609
2610
2611 /*
2612 * openfirmware:
2613 */
2614 X(openfirmware)
2615 {
2616 of_emul(cpu);
2617 if (cpu->running == 0) {
2618 cpu->n_translated_instrs --;
2619 cpu->cd.ppc.next_ic = &nothing_call;
2620 }
2621 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2622 if (cpu->machine->show_trace_tree)
2623 cpu_functioncall_trace_return(cpu);
2624 quick_pc_to_pointers(cpu);
2625 }
2626
2627
2628 /*
2629 * 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 * tlbli:
2642 */
2643 X(tlbli)
2644 {
2645 fatal("tlbli\n");
2646 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2647 }
2648
2649
2650 /*
2651 * tlbld:
2652 */
2653 X(tlbld)
2654 {
2655 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2656 MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2657
2658 fatal("tlbld\n");
2659 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2660 }
2661
2662
2663 /*****************************************************************************/
2664
2665
2666 X(end_of_page)
2667 {
2668 /* Update the PC: (offset 0, but on the next page) */
2669 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
2672 /* Find the new physical page and update the translation pointers: */
2673 quick_pc_to_pointers(cpu);
2674
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 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2687 * 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 uint32_t iword, mask;
2695 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 bfa, fp, byterev, nb, mb, me;
2700 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 #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
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 fatal("PPC to_be_translated(): "
2738 "read failed: TODO\n");
2739 exit(1);
2740 /* goto bad; */
2741 }
2742 }
2743
2744 iword = *((uint32_t *)&ib[0]);
2745 iword = BE32_TO_HOST(iword);
2746
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 case 0x04:
2762 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 break;
2774
2775 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 else {
2811 if (bf == 0)
2812 ic->f = instr(cmpwi_cr0);
2813 else
2814 ic->f = instr(cmpwi);
2815 }
2816 }
2817 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2818 ic->arg[1] = (ssize_t)imm;
2819 ic->arg[2] = 28 - 4 * bf;
2820 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 ic->arg[1] = imm;
2837 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 ic->f = instr(li);
2846 else
2847 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2848 ic->arg[1] = (int16_t)(iword & 0xffff);
2849 if (main_opcode == PPC_HI6_ADDIS)
2850 ic->arg[1] <<= 16;
2851 if (ra == 0 && ic->arg[1] == 0)
2852 ic->f = instr(li_0);
2853 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 case PPC_HI6_LHA:
2890 case PPC_HI6_LHAU:
2891 case PPC_HI6_LWZ:
2892 case PPC_HI6_LWZU:
2893 case PPC_HI6_LD:
2894 case PPC_HI6_LFD:
2895 case PPC_HI6_LFS:
2896 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 case PPC_HI6_STD:
2903 case PPC_HI6_STFD:
2904 case PPC_HI6_STFS:
2905 rs = (iword >> 21) & 31;
2906 ra = (iword >> 16) & 31;
2907 imm = (int16_t)iword;
2908 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2909 ic->f = NULL;
2910 switch (main_opcode) {
2911 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 case PPC_HI6_LD: load=1; size=3; break;
2920 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 case PPC_HI6_STB: break;
2923 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 case PPC_HI6_STD: size=3; break;
2929 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 }
2932 if (ic->f == NULL) {
2933 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 if (lk_bit) {
2968 ic->f = instr(bcl);
2969 samepage_function = instr(bcl_samepage);
2970 } else {
2971 ic->f = instr(bc);
2972 if ((bo & 0x14) == 0x04) {
2973 samepage_function = bo & 8?
2974 instr(bc_samepage_simple1) :
2975 instr(bc_samepage_simple0);
2976 } else
2977 samepage_function = instr(bc_samepage);
2978 }
2979 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2980 ic->arg[1] = bo;
2981 ic->arg[2] = 31-bi;
2982 /* 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 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2989 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 ic->arg[1] = (addr & 0xfff) + 4;
3002 if (cpu->machine->userland_emul != NULL)
3003 ic->f = instr(user_syscall);
3004 else if (iword == 0x44ee0002) {
3005 /* Special case/magic hack for OpenFirmware emul: */
3006 ic->f = instr(openfirmware);
3007 } else
3008 ic->f = instr(sc);
3009 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 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
3029 ic->arg[1] = (addr & 0xffc) + 4;
3030 /* 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 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
3037 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 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 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 else {
3073 ic->f = instr(bclr);
3074 if (!cpu->machine->show_trace_tree &&
3075 (bo & 0x14) == 0x14)
3076 ic->f = instr(bclr_20);
3077 }
3078 } 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 ic->arg[1] = 31 - bi;
3086 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 case PPC_19_RFID:
3099 ic->f = instr(rfid);
3100 break;
3101
3102 case PPC_19_MCRF:
3103 bf = (iword >> 23) & 7;
3104 bfa = (iword >> 18) & 7;
3105 ic->arg[0] = 28 - 4*bf;
3106 ic->arg[1] = 28 - 4*bfa;
3107 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 case PPC_19_CRORC:
3115 case PPC_19_CRNOR:
3116 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 case PPC_19_CRORC: ic->f = instr(crorc); break;
3123 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3124 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 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 case PPC_HI6_RLWIMI:
3158 rs = (iword >> 21) & 31;
3159 ra = (iword >> 16) & 31;
3160 ic->f = instr(rlwimi);
3161 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 case PPC_30_RLDICL:
3192 case PPC_30_RLDICR:
3193 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 ic->arg[0] = iword;
3200 if (cpu->cd.ppc.bits == 32) {
3201 fatal("TODO: rld* in 32-bit mode?\n");
3202 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 else {
3229 if (bf == 0)
3230 ic->f = instr(cmpw_cr0);
3231 else
3232 ic->f = instr(cmpw);
3233 }
3234 }
3235 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3236 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3237 ic->arg[2] = 28 - 4*bf;
3238 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 debug_spr_usage(cpu->pc, spr);
3257 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3258 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3259 switch (spr) {
3260 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3261 default: ic->f = instr(mfspr);
3262 }
3263 break;
3264
3265 case PPC_31_MTSPR:
3266 rs = (iword >> 21) & 31;
3267 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3268 debug_spr_usage(cpu->pc, spr);
3269 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3270 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3271 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 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 case PPC_31_MTMSRD:
3296 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 ic->arg[1] = (addr & 0xfff) + 4;
3304 ic->arg[2] = xo == PPC_31_MTMSRD;
3305 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 case PPC_31_MFSR:
3341 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 switch (xo) {
3346 case PPC_31_MFSR: ic->f = instr(mfsr); break;
3347 case PPC_31_MTSR: ic->f = instr(mtsr); break;
3348 }
3349 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 case PPC_31_DSSALL:
3371 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 ic->arg[2] = addr & 0xfff;
3389 ic->f = instr(dcbz);
3390 break;
3391
3392 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 case PPC_31_TLBIE:
3405 /* TODO: POWER also uses ra? */
3406 rb = (iword >> 11) & 31;
3407 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3408 ic->f = instr(tlbie);
3409 break;
3410
3411 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 case PPC_31_TLBSX_DOT:
3424 /* TODO */
3425 ic->f = instr(tlbsx_dot);
3426 break;
3427
3428 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 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 case PPC_31_WRTEEI:
3478 ic->arg[0] = iword & 0x8000;
3479 ic->f = instr(wrteei);
3480 break;
3481
3482 case 0x1c3:
3483 fatal("[ mtdcr: TODO ]\n");
3484 ic->f = instr(nop);
3485 break;
3486
3487 case PPC_31_LBZX:
3488 case PPC_31_LBZUX:
3489 case PPC_31_LHAX:
3490 case PPC_31_LHAUX:
3491 case PPC_31_LHZX:
3492 case PPC_31_LHZUX:
3493 case PPC_31_LWZX:
3494 case PPC_31_LWZUX:
3495 case PPC_31_LHBRX:
3496 case PPC_31_LWBRX:
3497 case PPC_31_LFDX:
3498 case PPC_31_LFSX:
3499 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 case PPC_31_STHBRX:
3508 case PPC_31_STWBRX:
3509 case PPC_31_STFDX:
3510 case PPC_31_STFSX:
3511 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 byterev = 0; fp = 0;
3521 ic->f = NULL;
3522 switch (xo) {
3523 case PPC_31_LBZX: load = 1; break;
3524 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 case PPC_31_STBX: break;
3540 case PPC_31_STBUX: update = 1; break;
3541 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 }
3556 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 #ifdef MODE32
3563 ppc32_loadstore_indexed
3564 #else
3565 ppc_loadstore_indexed
3566 #endif
3567 [size + 4*zero + 8*load + 16*update];
3568 }
3569 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 case PPC_31_SLD:
3580 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 case PPC_31_EQV:
3590 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 case PPC_31_SLD: ic->f = instr(sld);
3605 rc_f = instr(sld_dot); break;
3606 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 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3619 : instr(or);
3620 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 case PPC_31_EQV: ic->f = instr(eqv);
3626 rc_f = instr(eqv_dot); break;
3627 }
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 case PPC_31_SUBFME:
3649 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 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3674 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 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 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 case PPC_31_SUBFME:
3703 ic->f = instr(subfme_dot); break;
3704 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 case PPC_31_LVX:
3720 case PPC_31_LVXL:
3721 case PPC_31_STVX:
3722 case PPC_31_STVXL:
3723 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 ic->arg[0] = rs;
3733 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 ic->f = load? instr(lvx) : instr(stvx);
3739 break;
3740
3741 default:goto bad;
3742 }
3743 break;
3744
3745 case PPC_HI6_59:
3746 xo = (iword >> 1) & 1023;
3747 rt = (iword >> 21) & 31;
3748 ra = (iword >> 16) & 31;
3749 rb = (iword >> 11) & 31;
3750 rs = (iword >> 6) & 31; /* actually frc */
3751 rc = iword & 1;
3752
3753 if (rc) {
3754 fatal("Floating point (59) with rc bit! TODO\n");
3755 goto bad;
3756 }
3757
3758 /* 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 }
3769 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 break;
3773 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
3786 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 }
3798
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 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