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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26