/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 89844 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26