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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 86163 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26