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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (show 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 /*
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 * $Id: cpu_ppc_instr.c,v 1.44 2005/11/24 01:31:54 debug Exp $
29 *
30 * POWER/PowerPC instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 #include "float_emul.h"
40
41
42 #define DOT0(n) X(n ## _dot) { instr(n)(cpu,ic); \
43 update_cr0(cpu, reg(ic->arg[0])); }
44 #define DOT1(n) X(n ## _dot) { instr(n)(cpu,ic); \
45 update_cr0(cpu, reg(ic->arg[1])); }
46 #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47 update_cr0(cpu, reg(ic->arg[2])); }
48
49
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 fatal("PPC: invalid(): INTERNAL ERROR\n");
64 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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
109 tmp2 += (uint32_t)ic->arg[1];
110 if ((tmp2 >> 32) != (tmp >> 32))
111 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
112 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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
127 if (tmp >= reg(ic->arg[0]))
128 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
129 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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
146 tmp2 += (uint32_t)ic->arg[1];
147 if ((tmp2 >> 32) != (tmp >> 32))
148 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
149 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 * arg[1] = 31 - bi
159 * arg[2] = bh
160 */
161 X(bclr)
162 {
163 int bo = ic->arg[0], bi31m = ic->arg[1] /* , bh = ic->arg[2] */;
164 int ctr_ok, cond_ok;
165 uint64_t old_pc = cpu->pc;
166 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
167 if (!(bo & 4))
168 cpu->cd.ppc.spr[SPR_CTR] --;
169 ctr_ok = (bo >> 2) & 1;
170 tmp = cpu->cd.ppc.spr[SPR_CTR];
171 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
172 cond_ok = (bo >> 4) & 1;
173 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
174 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 X(bclr_20)
195 {
196 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
197 DYNTRANS_PC_TO_POINTERS(cpu);
198 }
199 X(bclr_l)
200 {
201 uint64_t low_pc, old_pc = cpu->pc;
202 int bo = ic->arg[0], bi31m = ic->arg[1] /* , bh = ic->arg[2] */;
203 int ctr_ok, cond_ok;
204 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
205 if (!(bo & 4))
206 cpu->cd.ppc.spr[SPR_CTR] --;
207 ctr_ok = (bo >> 2) & 1;
208 tmp = cpu->cd.ppc.spr[SPR_CTR];
209 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
210 cond_ok = (bo >> 4) & 1;
211 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
212
213 /* Calculate return PC: */
214 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
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 * arg[1] = 31 - bi
248 * arg[2] = bh
249 */
250 X(bcctr)
251 {
252 int bo = ic->arg[0], bi31m = ic->arg[1] /* , bh = ic->arg[2] */;
253 uint64_t old_pc = cpu->pc;
254 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
255 int cond_ok = (bo >> 4) & 1;
256 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
257 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 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 int cond_ok = (bo >> 4) & 1;
283 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
284
285 /* Calculate return PC: */
286 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
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 X(ba)
333 {
334 cpu->pc = (int32_t)ic->arg[0];
335 DYNTRANS_PC_TO_POINTERS(cpu);
336 }
337
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 cpu->cd.ppc.spr[SPR_CTR] --;
352 ctr_ok = (bo >> 2) & 1;
353 tmp = cpu->cd.ppc.spr[SPR_CTR];
354 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 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
366 /* 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
372 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 /*
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 cpu->cd.ppc.spr[SPR_CTR] --;
409 ctr_ok = (bo >> 2) & 1;
410 tmp = cpu->cd.ppc.spr[SPR_CTR];
411 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 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
417 }
418 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
431 /* 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
437 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 /*
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 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
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 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
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 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
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 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
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 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
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 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
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 * arg[2] = 28 - 4*bf
595 */
596 X(cmpd)
597 {
598 int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
599 int bf_shift = ic->arg[2], c;
600 if (tmp < tmp2)
601 c = 8;
602 else if (tmp > tmp2)
603 c = 4;
604 else
605 c = 2;
606 /* 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 }
611
612
613 /*
614 * cmpld: Compare Doubleword, unsigned
615 *
616 * arg[0] = ptr to ra
617 * arg[1] = ptr to rb
618 * arg[2] = 28 - 4*bf
619 */
620 X(cmpld)
621 {
622 uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
623 int bf_shift = ic->arg[2], c;
624 if (tmp < tmp2)
625 c = 8;
626 else if (tmp > tmp2)
627 c = 4;
628 else
629 c = 2;
630 /* 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 }
635
636
637 /*
638 * cmpdi: Compare Doubleword immediate
639 *
640 * arg[0] = ptr to ra
641 * arg[1] = int32_t imm
642 * arg[2] = 28 - 4*bf
643 */
644 X(cmpdi)
645 {
646 int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
647 int bf_shift = ic->arg[2], c;
648 if (tmp < imm)
649 c = 8;
650 else if (tmp > imm)
651 c = 4;
652 else
653 c = 2;
654 /* 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 }
659
660
661 /*
662 * cmpldi: Compare Doubleword immediate, logical
663 *
664 * arg[0] = ptr to ra
665 * arg[1] = int32_t imm
666 * arg[2] = 28 - 4*bf
667 */
668 X(cmpldi)
669 {
670 uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
671 int bf_shift = ic->arg[2], c;
672 if (tmp < imm)
673 c = 8;
674 else if (tmp > imm)
675 c = 4;
676 else
677 c = 2;
678 /* 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 }
683
684
685 /*
686 * cmpw: Compare Word
687 *
688 * arg[0] = ptr to ra
689 * arg[1] = ptr to rb
690 * arg[2] = 28 - 4*bf
691 */
692 X(cmpw)
693 {
694 int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
695 int bf_shift = ic->arg[2], c;
696 if (tmp < tmp2)
697 c = 8;
698 else if (tmp > tmp2)
699 c = 4;
700 else
701 c = 2;
702 /* 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 }
707
708
709 /*
710 * cmplw: Compare Word, unsigned
711 *
712 * arg[0] = ptr to ra
713 * arg[1] = ptr to rb
714 * arg[2] = 28 - 4*bf
715 */
716 X(cmplw)
717 {
718 uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
719 int bf_shift = ic->arg[2], c;
720 if (tmp < tmp2)
721 c = 8;
722 else if (tmp > tmp2)
723 c = 4;
724 else
725 c = 2;
726 /* 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 }
731
732
733 /*
734 * cmpwi: Compare Word immediate
735 *
736 * arg[0] = ptr to ra
737 * arg[1] = int32_t imm
738 * arg[2] = 28 - 4*bf
739 */
740 X(cmpwi)
741 {
742 int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
743 int bf_shift = ic->arg[2], c;
744 if (tmp < imm)
745 c = 8;
746 else if (tmp > imm)
747 c = 4;
748 else
749 c = 2;
750 /* 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 }
755
756
757 /*
758 * cmplwi: Compare Word immediate, logical
759 *
760 * arg[0] = ptr to ra
761 * arg[1] = int32_t imm
762 * arg[2] = 28 - 4*bf
763 */
764 X(cmplwi)
765 {
766 uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
767 int bf_shift = ic->arg[2], c;
768 if (tmp < imm)
769 c = 8;
770 else if (tmp > imm)
771 c = 4;
772 else
773 c = 2;
774 /* 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 }
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 /* Synchronize the PC first: */
795 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
796
797 addr &= ~(cacheline_size - 1);
798 memset(cacheline, 0, sizeof(cacheline));
799
800 /* TODO: Don't use memory_rw() unless it is necessary. */
801 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 /* exception */
807 return;
808 }
809
810 cleared += to_clear;
811 addr += to_clear;
812 }
813 }
814
815
816 /*
817 * 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 * fmr: Floating-point Move
861 *
862 * arg[0] = ptr to frb
863 * arg[1] = ptr to frt
864 */
865 X(fmr)
866 {
867 /* 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 *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
877 }
878
879
880 /*
881 * 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 * 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 uint32_t old_so = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_SO;
1378 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 * arg[0] = sr number, or for indirect mode: ptr to rb
1426 * 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
1433 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1434 }
1435 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
1441 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1442 }
1443
1444
1445 /*
1446 * mfsrin, mtsrin: Move From/To Segment Register Indirect
1447 *
1448 * arg[0] = sr number, or for indirect mode: ptr to rb
1449 * arg[1] = ptr to rt
1450 */
1451 X(mfsr)
1452 {
1453 /* TODO: This only works for 32-bit mode */
1454 reg(ic->arg[1]) = cpu->cd.ppc.sr[ic->arg[0]];
1455 }
1456 X(mfsrin)
1457 {
1458 /* TODO: This only works for 32-bit mode */
1459 uint32_t sr_num = reg(ic->arg[0]) >> 28;
1460 reg(ic->arg[1]) = cpu->cd.ppc.sr[sr_num];
1461 }
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 * 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 * rlwinm:
1513 *
1514 * arg[0] = ptr to ra
1515 * arg[1] = mask
1516 * arg[2] = copy of the instruction word
1517 */
1518 X(rlwinm)
1519 {
1520 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 }
1528 DOT0(rlwinm)
1529
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 int sh = (iword >> 11) & 31;
1543 int mb = (iword >> 6) & 31;
1544 int me = (iword >> 1) & 31;
1545 int rc = iword & 1;
1546
1547 tmp = (tmp << sh) | (tmp >> (32-sh));
1548
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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
1579 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 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
1590 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
1591 }
1592 DOT1(srawi)
1593
1594
1595 /*
1596 * mcrf: Move inside condition register
1597 *
1598 * arg[0] = 28-4*bf, arg[1] = 28-4*bfa
1599 */
1600 X(mcrf)
1601 {
1602 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 }
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 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 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 * mfspr: Move from SPR
1672 *
1673 * arg[0] = pointer to destination register
1674 * arg[1] = pointer to source SPR
1675 */
1676 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
1697
1698 /*
1699 * mtspr: Move to SPR.
1700 *
1701 * arg[0] = pointer to source register
1702 * arg[1] = pointer to the SPR
1703 */
1704 X(mtspr) {
1705 reg(ic->arg[1]) = reg(ic->arg[0]);
1706 }
1707
1708
1709 /*
1710 * rfi: Return from Interrupt
1711 */
1712 X(rfi)
1713 {
1714 uint64_t tmp;
1715
1716 reg_access_msr(cpu, &tmp, 0, 0);
1717 tmp &= ~0xffff;
1718 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & 0xffff);
1719 reg_access_msr(cpu, &tmp, 1, 0);
1720
1721 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1722 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 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0, 0);
1745 }
1746
1747
1748 /*
1749 * mtmsr: Move To MSR
1750 *
1751 * arg[0] = pointer to source register
1752 */
1753 X(mtmsr)
1754 {
1755 /* 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 }
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 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * (int32_t)ic->arg[1]);
1784 }
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 int rs = ic->arg[0];
1798
1799 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 while (rs <= 31) {
1806 if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1807 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1808 /* exception */
1809 return;
1810 }
1811
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 int rs = ic->arg[0];
1827
1828 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 while (rs <= 31) {
1835 uint32_t tmp = cpu->cd.ppc.gpr[rs];
1836 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 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1845 /* exception */
1846 return;
1847 }
1848
1849 rs ++;
1850 addr += sizeof(uint32_t);
1851 }
1852 }
1853
1854
1855 /*
1856 * 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 * 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 DOT2(extsb)
1943 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 DOT2(extsh)
1951 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 DOT2(extsw)
1959 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
1960 << (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 X(srw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
1983 >> (reg(ic->arg[1]) & 31); }
1984 DOT2(srw)
1985 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1986 DOT2(and)
1987 X(nand) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) & reg(ic->arg[1])); }
1988 DOT2(nand)
1989 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
1990 DOT2(andc)
1991 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1992 DOT2(nor)
1993 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1994 DOT2(or)
1995 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
1996 DOT2(orc)
1997 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1998 DOT2(xor)
1999
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 DOT1(neg)
2009
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 DOT2(mullw)
2024 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 DOT2(mulhw)
2032 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 DOT2(mulhwu)
2040 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 DOT2(divw)
2051 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 DOT2(divwu)
2062
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 DOT2(add)
2073
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 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2088 tmp += (uint32_t)reg(ic->arg[1]);
2089 if ((tmp >> 32) != (tmp2 >> 32))
2090 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2091 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 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2106 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2107 uint64_t tmp2 = tmp;
2108 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2109 tmp += (uint32_t)reg(ic->arg[1]);
2110 if (old_ca)
2111 tmp ++;
2112 if ((tmp >> 32) != (tmp2 >> 32))
2113 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2114 reg(ic->arg[2]) = (uint32_t)tmp;
2115 }
2116 DOT2(adde)
2117 X(addme)
2118 {
2119 /* TODO: this only works in 32-bit mode */
2120 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2121 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2122 uint64_t tmp2 = tmp;
2123 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2124 if (old_ca)
2125 tmp ++;
2126 tmp += 0xffffffffULL;
2127 if ((tmp >> 32) != (tmp2 >> 32))
2128 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2129 reg(ic->arg[2]) = (uint32_t)tmp;
2130 }
2131 DOT2(addme)
2132 X(addze)
2133 {
2134 /* TODO: this only works in 32-bit mode */
2135 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2136 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2137 uint64_t tmp2 = tmp;
2138 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2139 if (old_ca)
2140 tmp ++;
2141 if ((tmp >> 32) != (tmp2 >> 32))
2142 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2143 reg(ic->arg[2]) = (uint32_t)tmp;
2144 }
2145 DOT2(addze)
2146
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 X(subf)
2156 {
2157 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2158 }
2159 DOT2(subf)
2160 X(subfc)
2161 {
2162 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2163 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2164 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2165 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2166 }
2167 DOT2(subfc)
2168 X(subfe)
2169 {
2170 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 if (reg(ic->arg[1]) == reg(ic->arg[0])) {
2173 if (old_ca)
2174 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2175 } else if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2176 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2177
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 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 X(subfze)
2200 {
2201 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2202 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2203 uint64_t tmp2 = tmp;
2204 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2205 if (old_ca)
2206 tmp ++;
2207 if ((tmp >> 32) != (tmp2 >> 32))
2208 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2209 reg(ic->arg[2]) = (uint32_t)tmp;
2210 }
2211 DOT2(subfze)
2212
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 #include "tmp_ppc_loadstore.c"
2226
2227
2228 /*
2229 * 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 * tlbie: TLB invalidate
2439 */
2440 X(tlbie)
2441 {
2442 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2443 INVALIDATE_VADDR);
2444 }
2445
2446
2447 /*
2448 * 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 * 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 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2477 if (cpu->machine->show_trace_tree)
2478 cpu_functioncall_trace_return(cpu);
2479 DYNTRANS_PC_TO_POINTERS(cpu);
2480 }
2481
2482
2483 /*
2484 * tlbli:
2485 */
2486 X(tlbli)
2487 {
2488 }
2489
2490
2491 /*
2492 * tlbld:
2493 */
2494 X(tlbld)
2495 {
2496 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2497 MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2498
2499 /* TODO? */
2500 }
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 uint32_t iword, mask;
2535 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 bfa, fp, byterev, nb, mb, me;
2540 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 fatal("PPC to_be_translated(): "
2563 "read failed: TODO\n");
2564 exit(1);
2565 /* goto bad; */
2566 }
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 ic->arg[2] = 28 - 4 * bf;
2636 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 ic->arg[1] = imm;
2653 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 ic->arg[1] = (int16_t)(iword & 0xffff);
2665 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 case PPC_HI6_LHA:
2704 case PPC_HI6_LHAU:
2705 case PPC_HI6_LWZ:
2706 case PPC_HI6_LWZU:
2707 case PPC_HI6_LFD:
2708 case PPC_HI6_LFS:
2709 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 case PPC_HI6_STFD:
2716 case PPC_HI6_STFS:
2717 rs = (iword >> 21) & 31;
2718 ra = (iword >> 16) & 31;
2719 imm = (int16_t)iword;
2720 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2721 ic->f = NULL;
2722 switch (main_opcode) {
2723 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 case PPC_HI6_STB: break;
2734 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 }
2742 if (ic->f == NULL) {
2743 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 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 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 ic->arg[1] = (addr & 0xfff) + 4;
2810 if (cpu->machine->userland_emul != NULL)
2811 ic->f = instr(user_syscall);
2812 else if (iword == 0x44ee0002) {
2813 /* Special case/magic hack for OpenFirmware emul: */
2814 ic->f = instr(openfirmware);
2815 } else
2816 ic->f = instr(sc);
2817 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 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 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 else {
2880 ic->f = instr(bclr);
2881 if (!cpu->machine->show_trace_tree &&
2882 (bo & 0x14) == 0x14)
2883 ic->f = instr(bclr_20);
2884 }
2885 } 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 ic->arg[1] = 31 - bi;
2893 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 ic->arg[0] = 28 - 4*bf;
2909 ic->arg[1] = 28 - 4*bfa;
2910 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 case PPC_19_CRNOR:
2918 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 case PPC_19_CRNOR: ic->f = instr(crnor); break;
2925 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 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 case PPC_HI6_RLWIMI:
2959 rs = (iword >> 21) & 31;
2960 ra = (iword >> 16) & 31;
2961 ic->f = instr(rlwimi);
2962 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 ic->arg[2] = 28 - 4*bf;
3029 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 debug_spr_usage(cpu->pc, spr);
3048 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3049 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3050 switch (spr) {
3051 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3052 default: ic->f = instr(mfspr);
3053 }
3054 break;
3055
3056 case PPC_31_MTSPR:
3057 rs = (iword >> 21) & 31;
3058 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3059 debug_spr_usage(cpu->pc, spr);
3060 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3061 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3062 ic->f = instr(mtspr);
3063 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 ic->arg[1] = (addr & 0xfff) + 4;
3086 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 case PPC_31_MFSR:
3122 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 switch (xo) {
3127 case PPC_31_MFSR: ic->f = instr(mfsr); break;
3128 case PPC_31_MTSR: ic->f = instr(mtsr); break;
3129 }
3130 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 ic->arg[2] = addr & 0xfff;
3169 ic->f = instr(dcbz);
3170 break;
3171
3172 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 case PPC_31_TLBIE:
3185 /* TODO: POWER also uses ra? */
3186 rb = (iword >> 11) & 31;
3187 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3188 ic->f = instr(tlbie);
3189 break;
3190
3191 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 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 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 case PPC_31_LBZX:
3258 case PPC_31_LBZUX:
3259 case PPC_31_LHAX:
3260 case PPC_31_LHAUX:
3261 case PPC_31_LHZX:
3262 case PPC_31_LHZUX:
3263 case PPC_31_LWZX:
3264 case PPC_31_LWZUX:
3265 case PPC_31_LHBRX:
3266 case PPC_31_LWBRX:
3267 case PPC_31_LFDX:
3268 case PPC_31_LFSX:
3269 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 case PPC_31_STHBRX:
3278 case PPC_31_STWBRX:
3279 case PPC_31_STFDX:
3280 case PPC_31_STFSX:
3281 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 byterev = 0; fp = 0;
3291 ic->f = NULL;
3292 switch (xo) {
3293 case PPC_31_LBZX: load = 1; break;
3294 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 case PPC_31_STBX: break;
3310 case PPC_31_STBUX: update = 1; break;
3311 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 }
3326 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 #ifdef MODE32
3333 ppc32_loadstore_indexed
3334 #else
3335 ppc_loadstore_indexed
3336 #endif
3337 [size + 4*zero + 8*load + 16*update];
3338 }
3339 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 case PPC_31_SUBFME:
3412 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 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3437 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 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 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 case PPC_31_SUBFME:
3466 ic->f = instr(subfme_dot); break;
3467 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 case PPC_HI6_59:
3487 xo = (iword >> 1) & 1023;
3488 rt = (iword >> 21) & 31;
3489 ra = (iword >> 16) & 31;
3490 rb = (iword >> 11) & 31;
3491 rs = (iword >> 6) & 31; /* actually frc */
3492 rc = iword & 1;
3493
3494 if (rc) {
3495 fatal("Floating point (59) with rc bit! TODO\n");
3496 goto bad;
3497 }
3498
3499 /* 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 }
3510 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 break;
3514 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
3527 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 }
3539
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 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