/[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 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 87479 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26