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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 92656 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 44 * $Id: cpu_ppc_instr.c,v 1.77 2007/06/28 13:36:47 debug Exp $
29 dpavlin 14 *
30     * POWER/PowerPC instructions.
31     *
32     * Individual functions should keep track of cpu->n_translated_instrs.
33     * (If no instruction was executed, then it should be decreased. If, say, 4
34     * instructions were combined into one function and executed, then it should
35     * be increased by 3.)
36     */
37    
38    
39 dpavlin 20 #include "float_emul.h"
40    
41    
42     #define DOT0(n) X(n ## _dot) { instr(n)(cpu,ic); \
43     update_cr0(cpu, reg(ic->arg[0])); }
44     #define DOT1(n) X(n ## _dot) { instr(n)(cpu,ic); \
45 dpavlin 14 update_cr0(cpu, reg(ic->arg[1])); }
46 dpavlin 20 #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47     update_cr0(cpu, reg(ic->arg[2])); }
48 dpavlin 14
49 dpavlin 22 #ifndef CHECK_FOR_FPU_EXCEPTION
50     #define CHECK_FOR_FPU_EXCEPTION { if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) { \
51     /* Synchronize the PC, and cause an FPU exception: */ \
52     uint64_t low_pc = ((size_t)ic - \
53     (size_t)cpu->cd.ppc.cur_ic_page) \
54     / sizeof(struct ppc_instr_call); \
55     cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << \
56     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << \
57     PPC_INSTR_ALIGNMENT_SHIFT); \
58     ppc_exception(cpu, PPC_EXCEPTION_FPU); \
59     return; } }
60     #endif
61 dpavlin 14
62 dpavlin 22
63    
64 dpavlin 14 /*
65     * nop: Do nothing.
66     */
67     X(nop)
68     {
69     }
70    
71    
72     /*
73     * invalid: To catch bugs.
74     */
75     X(invalid)
76     {
77 dpavlin 20 fatal("PPC: invalid(): INTERNAL ERROR\n");
78 dpavlin 14 exit(1);
79     }
80    
81    
82     /*
83     * addi: Add immediate.
84     *
85     * arg[0] = pointer to source uint64_t
86     * arg[1] = immediate value (int32_t or larger)
87     * arg[2] = pointer to destination uint64_t
88     */
89     X(addi)
90     {
91     reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];
92     }
93 dpavlin 22 X(li)
94     {
95     reg(ic->arg[2]) = (int32_t)ic->arg[1];
96     }
97     X(li_0)
98     {
99     reg(ic->arg[2]) = 0;
100     }
101 dpavlin 14
102    
103     /*
104     * andi_dot: AND immediate, update CR.
105     *
106     * arg[0] = pointer to source uint64_t
107     * arg[1] = immediate value (uint32_t)
108     * arg[2] = pointer to destination uint64_t
109     */
110     X(andi_dot)
111     {
112     MODE_uint_t tmp = reg(ic->arg[0]) & (uint32_t)ic->arg[1];
113     reg(ic->arg[2]) = tmp;
114     update_cr0(cpu, tmp);
115     }
116    
117    
118     /*
119     * addic: Add immediate, Carry.
120     *
121     * arg[0] = pointer to source register
122     * arg[1] = immediate value (int32_t or larger)
123     * arg[2] = pointer to destination register
124     */
125     X(addic)
126     {
127     /* TODO/NOTE: Only for 32-bit mode, so far! */
128     uint64_t tmp = (uint32_t)reg(ic->arg[0]);
129     uint64_t tmp2 = tmp;
130 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
131 dpavlin 14 tmp2 += (uint32_t)ic->arg[1];
132     if ((tmp2 >> 32) != (tmp >> 32))
133 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
134 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp2;
135     }
136    
137    
138     /*
139     * subfic: Subtract from immediate, Carry.
140     *
141     * arg[0] = pointer to source uint64_t
142     * arg[1] = immediate value (int32_t or larger)
143     * arg[2] = pointer to destination uint64_t
144     */
145     X(subfic)
146     {
147     MODE_uint_t tmp = (int64_t)(int32_t)ic->arg[1];
148 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
149 dpavlin 14 if (tmp >= reg(ic->arg[0]))
150 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
151 dpavlin 14 reg(ic->arg[2]) = tmp - reg(ic->arg[0]);
152     }
153    
154    
155     /*
156     * addic_dot: Add immediate, Carry.
157     *
158     * arg[0] = pointer to source uint64_t
159     * arg[1] = immediate value (int32_t or larger)
160     * arg[2] = pointer to destination uint64_t
161     */
162     X(addic_dot)
163     {
164     /* TODO/NOTE: Only for 32-bit mode, so far! */
165     uint64_t tmp = (uint32_t)reg(ic->arg[0]);
166     uint64_t tmp2 = tmp;
167 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
168 dpavlin 14 tmp2 += (uint32_t)ic->arg[1];
169     if ((tmp2 >> 32) != (tmp >> 32))
170 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
171 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp2;
172     update_cr0(cpu, (uint32_t)tmp2);
173     }
174    
175    
176     /*
177     * bclr: Branch Conditional to Link Register
178     *
179     * arg[0] = bo
180 dpavlin 20 * arg[1] = 31 - bi
181 dpavlin 14 * arg[2] = bh
182     */
183     X(bclr)
184     {
185 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
186 dpavlin 14 int ctr_ok, cond_ok;
187     uint64_t old_pc = cpu->pc;
188 dpavlin 20 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
189 dpavlin 14 if (!(bo & 4))
190 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
191 dpavlin 14 ctr_ok = (bo >> 2) & 1;
192 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
193 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
194 dpavlin 14 cond_ok = (bo >> 4) & 1;
195 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
196 dpavlin 14 if (ctr_ok && cond_ok) {
197     uint64_t mask_within_page =
198     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
199     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
200     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
201     /* TODO: trace in separate (duplicate) function? */
202     if (cpu->machine->show_trace_tree)
203     cpu_functioncall_trace_return(cpu);
204     if ((old_pc & ~mask_within_page) ==
205     (cpu->pc & ~mask_within_page)) {
206     cpu->cd.ppc.next_ic =
207     cpu->cd.ppc.cur_ic_page +
208     ((cpu->pc & mask_within_page) >>
209     PPC_INSTR_ALIGNMENT_SHIFT);
210     } else {
211     /* Find the new physical page and update pointers: */
212 dpavlin 22 quick_pc_to_pointers(cpu);
213 dpavlin 14 }
214     }
215     }
216 dpavlin 20 X(bclr_20)
217     {
218     cpu->pc = cpu->cd.ppc.spr[SPR_LR];
219 dpavlin 22 quick_pc_to_pointers(cpu);
220 dpavlin 20 }
221 dpavlin 14 X(bclr_l)
222     {
223     uint64_t low_pc, old_pc = cpu->pc;
224 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /* ,bh = ic->arg[2]*/;
225 dpavlin 14 int ctr_ok, cond_ok;
226 dpavlin 20 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
227 dpavlin 14 if (!(bo & 4))
228 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
229 dpavlin 14 ctr_ok = (bo >> 2) & 1;
230 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
231 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
232 dpavlin 14 cond_ok = (bo >> 4) & 1;
233 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
234 dpavlin 14
235     /* Calculate return PC: */
236 dpavlin 20 low_pc = ((size_t)ic - (size_t)
237     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
238 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
239     << PPC_INSTR_ALIGNMENT_SHIFT);
240     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
241 dpavlin 14
242     if (ctr_ok && cond_ok) {
243     uint64_t mask_within_page =
244     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
245     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
246     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
247     /* TODO: trace in separate (duplicate) function? */
248     if (cpu->machine->show_trace_tree)
249     cpu_functioncall_trace_return(cpu);
250     if (cpu->machine->show_trace_tree)
251     cpu_functioncall_trace(cpu, cpu->pc);
252     if ((old_pc & ~mask_within_page) ==
253     (cpu->pc & ~mask_within_page)) {
254     cpu->cd.ppc.next_ic =
255     cpu->cd.ppc.cur_ic_page +
256     ((cpu->pc & mask_within_page) >>
257     PPC_INSTR_ALIGNMENT_SHIFT);
258     } else {
259     /* Find the new physical page and update pointers: */
260 dpavlin 22 quick_pc_to_pointers(cpu);
261 dpavlin 14 }
262     }
263     }
264    
265    
266     /*
267     * bcctr: Branch Conditional to Count register
268     *
269     * arg[0] = bo
270 dpavlin 20 * arg[1] = 31 - bi
271 dpavlin 14 * arg[2] = bh
272     */
273     X(bcctr)
274     {
275 dpavlin 42 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
276 dpavlin 14 uint64_t old_pc = cpu->pc;
277 dpavlin 20 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
278 dpavlin 14 int cond_ok = (bo >> 4) & 1;
279 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
280 dpavlin 14 if (cond_ok) {
281     uint64_t mask_within_page =
282     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
283     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
284     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
285     /* TODO: trace in separate (duplicate) function? */
286     if (cpu->machine->show_trace_tree)
287     cpu_functioncall_trace_return(cpu);
288     if ((old_pc & ~mask_within_page) ==
289     (cpu->pc & ~mask_within_page)) {
290     cpu->cd.ppc.next_ic =
291     cpu->cd.ppc.cur_ic_page +
292     ((cpu->pc & mask_within_page) >>
293     PPC_INSTR_ALIGNMENT_SHIFT);
294     } else {
295     /* Find the new physical page and update pointers: */
296 dpavlin 22 quick_pc_to_pointers(cpu);
297 dpavlin 14 }
298     }
299     }
300     X(bcctr_l)
301     {
302     uint64_t low_pc, old_pc = cpu->pc;
303 dpavlin 22 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2] */;
304 dpavlin 20 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
305 dpavlin 14 int cond_ok = (bo >> 4) & 1;
306 dpavlin 20 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
307 dpavlin 14
308     /* Calculate return PC: */
309 dpavlin 20 low_pc = ((size_t)ic - (size_t)
310     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
311 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
312     << PPC_INSTR_ALIGNMENT_SHIFT);
313     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
314 dpavlin 14
315     if (cond_ok) {
316     uint64_t mask_within_page =
317     ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
318     | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
319     cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
320     /* TODO: trace in separate (duplicate) function? */
321     if (cpu->machine->show_trace_tree)
322     cpu_functioncall_trace(cpu, cpu->pc);
323     if ((old_pc & ~mask_within_page) ==
324     (cpu->pc & ~mask_within_page)) {
325     cpu->cd.ppc.next_ic =
326     cpu->cd.ppc.cur_ic_page +
327     ((cpu->pc & mask_within_page) >>
328     PPC_INSTR_ALIGNMENT_SHIFT);
329     } else {
330     /* Find the new physical page and update pointers: */
331 dpavlin 22 quick_pc_to_pointers(cpu);
332 dpavlin 14 }
333     }
334     }
335    
336    
337     /*
338     * b: Branch (to a different translated page)
339     *
340 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
341 dpavlin 14 */
342     X(b)
343     {
344 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
345 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
346    
347     /* Find the new physical page and update the translation pointers: */
348 dpavlin 22 quick_pc_to_pointers(cpu);
349 dpavlin 14 }
350 dpavlin 20 X(ba)
351     {
352     cpu->pc = (int32_t)ic->arg[0];
353 dpavlin 22 quick_pc_to_pointers(cpu);
354 dpavlin 20 }
355 dpavlin 14
356    
357     /*
358     * bc: Branch Conditional (to a different translated page)
359     *
360 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
361 dpavlin 14 * arg[1] = bo
362 dpavlin 22 * arg[2] = 31-bi
363 dpavlin 14 */
364     X(bc)
365     {
366     MODE_uint_t tmp;
367 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
368 dpavlin 14 if (!(bo & 4))
369 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
370 dpavlin 14 ctr_ok = (bo >> 2) & 1;
371 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
372 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
373 dpavlin 14 cond_ok = (bo >> 4) & 1;
374     cond_ok |= ( ((bo >> 3) & 1) ==
375 dpavlin 22 ((cpu->cd.ppc.cr >> (bi31m)) & 1) );
376 dpavlin 14 if (ctr_ok && cond_ok)
377     instr(b)(cpu,ic);
378     }
379 dpavlin 20 X(bcl)
380     {
381     MODE_uint_t tmp;
382 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
383     int low_pc;
384 dpavlin 14
385 dpavlin 20 /* Calculate LR: */
386     low_pc = ((size_t)ic - (size_t)
387     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
388 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
389     << PPC_INSTR_ALIGNMENT_SHIFT);
390     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
391 dpavlin 14
392 dpavlin 20 if (!(bo & 4))
393     cpu->cd.ppc.spr[SPR_CTR] --;
394     ctr_ok = (bo >> 2) & 1;
395     tmp = cpu->cd.ppc.spr[SPR_CTR];
396 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
397 dpavlin 20 cond_ok = (bo >> 4) & 1;
398     cond_ok |= ( ((bo >> 3) & 1) ==
399 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
400 dpavlin 20 if (ctr_ok && cond_ok)
401     instr(b)(cpu,ic);
402     }
403    
404    
405 dpavlin 14 /*
406     * b_samepage: Branch (to within the same translated page)
407     *
408     * arg[0] = pointer to new ppc_instr_call
409     */
410     X(b_samepage)
411     {
412     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
413     }
414    
415    
416     /*
417     * bc_samepage: Branch Conditional (to within the same page)
418     *
419     * arg[0] = new ic ptr
420     * arg[1] = bo
421 dpavlin 22 * arg[2] = 31-bi
422 dpavlin 14 */
423     X(bc_samepage)
424     {
425     MODE_uint_t tmp;
426 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
427 dpavlin 14 if (!(bo & 4))
428 dpavlin 20 cpu->cd.ppc.spr[SPR_CTR] --;
429 dpavlin 14 ctr_ok = (bo >> 2) & 1;
430 dpavlin 20 tmp = cpu->cd.ppc.spr[SPR_CTR];
431 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
432 dpavlin 14 cond_ok = (bo >> 4) & 1;
433     cond_ok |= ( ((bo >> 3) & 1) ==
434 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
435 dpavlin 14 if (ctr_ok && cond_ok)
436 dpavlin 20 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
437 dpavlin 14 }
438 dpavlin 22 X(bc_samepage_simple0)
439 dpavlin 20 {
440 dpavlin 22 int bi31m = ic->arg[2];
441     if (!((cpu->cd.ppc.cr >> bi31m) & 1))
442 dpavlin 20 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
443     }
444 dpavlin 22 X(bc_samepage_simple1)
445     {
446     int bi31m = ic->arg[2];
447     if ((cpu->cd.ppc.cr >> bi31m) & 1)
448     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
449     }
450 dpavlin 20 X(bcl_samepage)
451     {
452     MODE_uint_t tmp;
453 dpavlin 22 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
454     int low_pc;
455 dpavlin 14
456 dpavlin 20 /* Calculate LR: */
457     low_pc = ((size_t)ic - (size_t)
458     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
459 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
460     << PPC_INSTR_ALIGNMENT_SHIFT);
461     cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
462 dpavlin 14
463 dpavlin 20 if (!(bo & 4))
464     cpu->cd.ppc.spr[SPR_CTR] --;
465     ctr_ok = (bo >> 2) & 1;
466     tmp = cpu->cd.ppc.spr[SPR_CTR];
467 dpavlin 42 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
468 dpavlin 20 cond_ok = (bo >> 4) & 1;
469     cond_ok |= ( ((bo >> 3) & 1) ==
470 dpavlin 22 ((cpu->cd.ppc.cr >> bi31m) & 1) );
471 dpavlin 20 if (ctr_ok && cond_ok)
472     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
473     }
474    
475    
476 dpavlin 14 /*
477     * bl: Branch and Link (to a different translated page)
478     *
479 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
480     * arg[1] = lr offset (relative to start of current page)
481 dpavlin 14 */
482     X(bl)
483     {
484 dpavlin 22 /* Calculate LR and new PC: */
485     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
486     cpu->cd.ppc.spr[SPR_LR] = cpu->pc + ic->arg[1];
487 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
488    
489     /* Find the new physical page and update the translation pointers: */
490 dpavlin 22 quick_pc_to_pointers(cpu);
491 dpavlin 14 }
492 dpavlin 20 X(bla)
493     {
494 dpavlin 22 /* Calculate LR: */
495     cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
496     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
497    
498 dpavlin 20 cpu->pc = (int32_t)ic->arg[0];
499 dpavlin 22 quick_pc_to_pointers(cpu);
500 dpavlin 20 }
501 dpavlin 14
502    
503     /*
504     * bl_trace: Branch and Link (to a different translated page) (with trace)
505     *
506 dpavlin 22 * arg[0] = relative offset (as an int32_t) from start of page
507     * arg[1] = lr offset (relative to start of current page)
508 dpavlin 14 */
509     X(bl_trace)
510     {
511     /* Calculate LR: */
512 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
513     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
514 dpavlin 14
515 dpavlin 22 /* Calculate new PC from start of page + arg[0] */
516     cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
517 dpavlin 14 cpu->pc += (int32_t)ic->arg[0];
518    
519     cpu_functioncall_trace(cpu, cpu->pc);
520    
521     /* Find the new physical page and update the translation pointers: */
522 dpavlin 22 quick_pc_to_pointers(cpu);
523 dpavlin 14 }
524 dpavlin 20 X(bla_trace)
525     {
526 dpavlin 22 /* Calculate LR: */
527     cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
528     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
529    
530 dpavlin 20 cpu->pc = (int32_t)ic->arg[0];
531     cpu_functioncall_trace(cpu, cpu->pc);
532 dpavlin 22 quick_pc_to_pointers(cpu);
533 dpavlin 20 }
534 dpavlin 14
535    
536     /*
537     * bl_samepage: Branch and Link (to within the same translated page)
538     *
539     * arg[0] = pointer to new ppc_instr_call
540 dpavlin 22 * arg[1] = lr offset (relative to start of current page)
541 dpavlin 14 */
542     X(bl_samepage)
543     {
544     /* Calculate LR: */
545 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
546     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
547 dpavlin 14
548     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
549     }
550    
551    
552     /*
553     * bl_samepage_trace: Branch and Link (to within the same translated page)
554     *
555     * arg[0] = pointer to new ppc_instr_call
556 dpavlin 22 * arg[1] = lr offset (relative to start of current page)
557 dpavlin 14 */
558     X(bl_samepage_trace)
559     {
560     uint32_t low_pc;
561    
562     /* Calculate LR: */
563 dpavlin 22 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
564     << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
565 dpavlin 14
566     cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
567    
568     /* Calculate new PC (for the trace) */
569     low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
570     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
571 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
572     cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
573 dpavlin 14 cpu_functioncall_trace(cpu, cpu->pc);
574     }
575    
576    
577     /*
578     * cntlzw: Count leading zeroes (32-bit word).
579     *
580     * arg[0] = ptr to rs
581     * arg[1] = ptr to ra
582     */
583     X(cntlzw)
584     {
585     uint32_t tmp = reg(ic->arg[0]);
586     int i;
587     for (i=0; i<32; i++) {
588     if (tmp & 0x80000000)
589     break;
590     tmp <<= 1;
591     }
592     reg(ic->arg[1]) = i;
593     }
594    
595    
596     /*
597     * cmpd: Compare Doubleword
598     *
599     * arg[0] = ptr to ra
600     * arg[1] = ptr to rb
601 dpavlin 20 * arg[2] = 28 - 4*bf
602 dpavlin 14 */
603     X(cmpd)
604     {
605     int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
606 dpavlin 20 int bf_shift = ic->arg[2], c;
607 dpavlin 14 if (tmp < tmp2)
608     c = 8;
609     else if (tmp > tmp2)
610     c = 4;
611     else
612     c = 2;
613 dpavlin 20 /* SO bit, copied from XER */
614     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
615     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
616     cpu->cd.ppc.cr |= (c << bf_shift);
617 dpavlin 14 }
618    
619    
620     /*
621     * cmpld: Compare Doubleword, unsigned
622     *
623     * arg[0] = ptr to ra
624     * arg[1] = ptr to rb
625 dpavlin 20 * arg[2] = 28 - 4*bf
626 dpavlin 14 */
627     X(cmpld)
628     {
629     uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
630 dpavlin 20 int bf_shift = ic->arg[2], c;
631 dpavlin 14 if (tmp < tmp2)
632     c = 8;
633     else if (tmp > tmp2)
634     c = 4;
635     else
636     c = 2;
637 dpavlin 20 /* SO bit, copied from XER */
638     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
639     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
640     cpu->cd.ppc.cr |= (c << bf_shift);
641 dpavlin 14 }
642    
643    
644     /*
645     * cmpdi: Compare Doubleword immediate
646     *
647     * arg[0] = ptr to ra
648     * arg[1] = int32_t imm
649 dpavlin 20 * arg[2] = 28 - 4*bf
650 dpavlin 14 */
651     X(cmpdi)
652     {
653     int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
654 dpavlin 20 int bf_shift = ic->arg[2], c;
655 dpavlin 14 if (tmp < imm)
656     c = 8;
657     else if (tmp > imm)
658     c = 4;
659     else
660     c = 2;
661 dpavlin 20 /* SO bit, copied from XER */
662     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
663     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
664     cpu->cd.ppc.cr |= (c << bf_shift);
665 dpavlin 14 }
666    
667    
668     /*
669     * cmpldi: Compare Doubleword immediate, logical
670     *
671     * arg[0] = ptr to ra
672     * arg[1] = int32_t imm
673 dpavlin 20 * arg[2] = 28 - 4*bf
674 dpavlin 14 */
675     X(cmpldi)
676     {
677     uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
678 dpavlin 20 int bf_shift = ic->arg[2], c;
679 dpavlin 14 if (tmp < imm)
680     c = 8;
681     else if (tmp > imm)
682     c = 4;
683     else
684     c = 2;
685 dpavlin 20 /* SO bit, copied from XER */
686     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
687     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
688     cpu->cd.ppc.cr |= (c << bf_shift);
689 dpavlin 14 }
690    
691    
692     /*
693     * cmpw: Compare Word
694     *
695     * arg[0] = ptr to ra
696     * arg[1] = ptr to rb
697 dpavlin 20 * arg[2] = 28 - 4*bf
698 dpavlin 14 */
699     X(cmpw)
700     {
701     int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
702 dpavlin 20 int bf_shift = ic->arg[2], c;
703 dpavlin 14 if (tmp < tmp2)
704     c = 8;
705     else if (tmp > tmp2)
706     c = 4;
707     else
708     c = 2;
709 dpavlin 20 /* SO bit, copied from XER */
710     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
711     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
712     cpu->cd.ppc.cr |= (c << bf_shift);
713 dpavlin 14 }
714 dpavlin 22 X(cmpw_cr0)
715     {
716     /* arg[2] is assumed to be 28 */
717     int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
718     cpu->cd.ppc.cr &= ~(0xf0000000);
719     if (tmp < tmp2)
720     cpu->cd.ppc.cr |= 0x80000000;
721     else if (tmp > tmp2)
722     cpu->cd.ppc.cr |= 0x40000000;
723     else
724     cpu->cd.ppc.cr |= 0x20000000;
725     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
726     }
727 dpavlin 14
728    
729     /*
730     * cmplw: Compare Word, unsigned
731     *
732     * arg[0] = ptr to ra
733     * arg[1] = ptr to rb
734 dpavlin 20 * arg[2] = 28 - 4*bf
735 dpavlin 14 */
736     X(cmplw)
737     {
738     uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
739 dpavlin 20 int bf_shift = ic->arg[2], c;
740 dpavlin 14 if (tmp < tmp2)
741     c = 8;
742     else if (tmp > tmp2)
743     c = 4;
744     else
745     c = 2;
746 dpavlin 20 /* SO bit, copied from XER */
747     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
748     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
749     cpu->cd.ppc.cr |= (c << bf_shift);
750 dpavlin 14 }
751    
752    
753     /*
754     * cmpwi: Compare Word immediate
755     *
756     * arg[0] = ptr to ra
757     * arg[1] = int32_t imm
758 dpavlin 20 * arg[2] = 28 - 4*bf
759 dpavlin 14 */
760     X(cmpwi)
761     {
762     int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
763 dpavlin 20 int bf_shift = ic->arg[2], c;
764 dpavlin 14 if (tmp < imm)
765     c = 8;
766     else if (tmp > imm)
767     c = 4;
768     else
769     c = 2;
770 dpavlin 20 /* SO bit, copied from XER */
771     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
772     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
773     cpu->cd.ppc.cr |= (c << bf_shift);
774 dpavlin 14 }
775 dpavlin 22 X(cmpwi_cr0)
776     {
777     /* arg[2] is assumed to be 28 */
778     int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
779     cpu->cd.ppc.cr &= ~(0xf0000000);
780     if (tmp < imm)
781     cpu->cd.ppc.cr |= 0x80000000;
782     else if (tmp > imm)
783     cpu->cd.ppc.cr |= 0x40000000;
784     else
785     cpu->cd.ppc.cr |= 0x20000000;
786     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
787     }
788 dpavlin 14
789    
790     /*
791     * cmplwi: Compare Word immediate, logical
792     *
793     * arg[0] = ptr to ra
794     * arg[1] = int32_t imm
795 dpavlin 20 * arg[2] = 28 - 4*bf
796 dpavlin 14 */
797     X(cmplwi)
798     {
799     uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
800 dpavlin 20 int bf_shift = ic->arg[2], c;
801 dpavlin 14 if (tmp < imm)
802     c = 8;
803     else if (tmp > imm)
804     c = 4;
805     else
806     c = 2;
807 dpavlin 20 /* SO bit, copied from XER */
808     c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
809     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
810     cpu->cd.ppc.cr |= (c << bf_shift);
811 dpavlin 14 }
812    
813    
814     /*
815     * dcbz: Data-Cache Block Zero
816     *
817     * arg[0] = ptr to ra (or zero)
818     * arg[1] = ptr to rb
819     */
820     X(dcbz)
821     {
822     MODE_uint_t addr = reg(ic->arg[0]) + reg(ic->arg[1]);
823     unsigned char cacheline[128];
824 dpavlin 22 size_t cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;
825     size_t cleared = 0;
826 dpavlin 14
827 dpavlin 20 /* Synchronize the PC first: */
828     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
829    
830 dpavlin 14 addr &= ~(cacheline_size - 1);
831     memset(cacheline, 0, sizeof(cacheline));
832    
833     while (cleared < cacheline_size) {
834     int to_clear = cacheline_size < sizeof(cacheline)?
835     cacheline_size : sizeof(cacheline);
836 dpavlin 22 #ifdef MODE32
837     unsigned char *page = cpu->cd.ppc.host_store[addr >> 12];
838     if (page != NULL) {
839     memset(page + (addr & 0xfff), 0, to_clear);
840     } else
841     #endif
842     if (cpu->memory_rw(cpu, cpu->mem, addr, cacheline,
843     to_clear, MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
844 dpavlin 20 /* exception */
845     return;
846 dpavlin 14 }
847    
848     cleared += to_clear;
849     addr += to_clear;
850     }
851     }
852    
853    
854     /*
855 dpavlin 20 * mtfsf: Copy FPR into the FPSCR.
856     *
857     * arg[0] = ptr to frb
858     * arg[1] = mask
859     */
860     X(mtfsf)
861     {
862 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
863 dpavlin 20 cpu->cd.ppc.fpscr &= ~ic->arg[1];
864     cpu->cd.ppc.fpscr |= (ic->arg[1] & (*(uint64_t *)ic->arg[0]));
865     }
866    
867    
868     /*
869     * mffs: Copy FPSCR into a FPR.
870     *
871     * arg[0] = ptr to frt
872     */
873     X(mffs)
874     {
875 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
876 dpavlin 20 (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;
877     }
878    
879    
880     /*
881 dpavlin 14 * fmr: Floating-point Move
882     *
883     * arg[0] = ptr to frb
884     * arg[1] = ptr to frt
885     */
886     X(fmr)
887     {
888 dpavlin 22 /*
889     * This works like a normal register to register copy, but
890     * a) it can cause an FPU exception, and b) the move is always
891     * 64-bit, even when running in 32-bit mode.
892     */
893     CHECK_FOR_FPU_EXCEPTION;
894 dpavlin 14 *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
895     }
896    
897    
898     /*
899 dpavlin 20 * fneg: Floating-point Negate
900     *
901     * arg[0] = ptr to frb
902     * arg[1] = ptr to frt
903     */
904     X(fneg)
905     {
906     uint64_t v;
907 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
908 dpavlin 20 v = *(uint64_t *)ic->arg[0];
909     *(uint64_t *)ic->arg[1] = v ^ 0x8000000000000000ULL;
910     }
911    
912    
913     /*
914     * fcmpu: Floating-point Compare Unordered
915     *
916     * arg[0] = 28 - 4*bf (bitfield shift)
917     * arg[1] = ptr to fra
918     * arg[2] = ptr to frb
919     */
920     X(fcmpu)
921     {
922     struct ieee_float_value fra, frb;
923     int bf_shift = ic->arg[0], c = 0;
924    
925 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
926 dpavlin 20
927     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
928     ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frb, IEEE_FMT_D);
929     if (fra.nan | frb.nan) {
930     c = 1;
931     } else {
932     if (fra.f < frb.f)
933     c = 8;
934     else if (fra.f > frb.f)
935     c = 4;
936     else
937     c = 2;
938     }
939     /* TODO: Signaling vs Quiet NaN */
940     cpu->cd.ppc.cr &= ~(0xf << bf_shift);
941     cpu->cd.ppc.cr |= ((c&0xe) << bf_shift);
942     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
943     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
944     }
945    
946    
947     /*
948     * frsp: Floating-point Round to Single Precision
949     *
950     * arg[0] = ptr to frb
951     * arg[1] = ptr to frt
952     */
953     X(frsp)
954     {
955     struct ieee_float_value frb;
956     float fl = 0.0;
957     int c = 0;
958    
959 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
960 dpavlin 20
961     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
962     if (frb.nan) {
963     c = 1;
964     } else {
965     fl = frb.f;
966     if (fl < 0.0)
967     c = 8;
968     else if (fl > 0.0)
969     c = 4;
970     else
971     c = 2;
972     }
973     /* TODO: Signaling vs Quiet NaN */
974     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
975     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
976     (*(uint64_t *)ic->arg[1]) =
977     ieee_store_float_value(fl, IEEE_FMT_D, frb.nan);
978     }
979    
980    
981     /*
982     * fctiwz: Floating-point Convert to Integer Word, Round to Zero
983     *
984     * arg[0] = ptr to frb
985     * arg[1] = ptr to frt
986     */
987     X(fctiwz)
988     {
989     struct ieee_float_value frb;
990 dpavlin 24 uint32_t res = 0;
991 dpavlin 20
992 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
993 dpavlin 20
994     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
995     if (!frb.nan) {
996     if (frb.f >= 2147483647.0)
997     res = 0x7fffffff;
998     else if (frb.f <= -2147483648.0)
999     res = 0x80000000;
1000     else
1001     res = frb.f;
1002     }
1003     *(uint64_t *)ic->arg[1] = (uint32_t)res;
1004     }
1005    
1006    
1007     /*
1008     * fmul: Floating-point Multiply
1009     *
1010     * arg[0] = ptr to frt
1011     * arg[1] = ptr to fra
1012     * arg[2] = ptr to frc
1013     */
1014     X(fmul)
1015     {
1016     struct ieee_float_value fra;
1017     struct ieee_float_value frc;
1018     double result = 0.0;
1019     int c, nan = 0;
1020    
1021 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1022 dpavlin 20
1023     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1024     ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frc, IEEE_FMT_D);
1025     if (fra.nan || frc.nan)
1026     nan = 1;
1027     else
1028     result = fra.f * frc.f;
1029     if (nan)
1030     c = 1;
1031     else {
1032     if (result < 0.0)
1033     c = 8;
1034     else if (result > 0.0)
1035     c = 4;
1036     else
1037     c = 2;
1038     }
1039     /* TODO: Signaling vs Quiet NaN */
1040     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1041     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1042    
1043     (*(uint64_t *)ic->arg[0]) =
1044     ieee_store_float_value(result, IEEE_FMT_D, nan);
1045     }
1046     X(fmuls)
1047     {
1048     /* TODO */
1049     instr(fmul)(cpu, ic);
1050     }
1051    
1052    
1053     /*
1054     * fmadd: Floating-point Multiply and Add
1055     *
1056     * arg[0] = ptr to frt
1057     * arg[1] = ptr to fra
1058     * arg[2] = copy of the instruction word
1059     */
1060     X(fmadd)
1061     {
1062     uint32_t iw = ic->arg[2];
1063     int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1064     struct ieee_float_value fra;
1065     struct ieee_float_value frb;
1066     struct ieee_float_value frc;
1067     double result = 0.0;
1068     int nan = 0, cc;
1069    
1070 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1071 dpavlin 20
1072     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1073     ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1074     ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1075     if (fra.nan || frb.nan || frc.nan)
1076     nan = 1;
1077     else
1078     result = fra.f * frc.f + frb.f;
1079     if (nan)
1080     cc = 1;
1081     else {
1082     if (result < 0.0)
1083     cc = 8;
1084     else if (result > 0.0)
1085     cc = 4;
1086     else
1087     cc = 2;
1088     }
1089     /* TODO: Signaling vs Quiet NaN */
1090     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1091     cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1092    
1093     (*(uint64_t *)ic->arg[0]) =
1094     ieee_store_float_value(result, IEEE_FMT_D, nan);
1095     }
1096    
1097    
1098     /*
1099     * fmsub: Floating-point Multiply and Sub
1100     *
1101     * arg[0] = ptr to frt
1102     * arg[1] = ptr to fra
1103     * arg[2] = copy of the instruction word
1104     */
1105     X(fmsub)
1106     {
1107     uint32_t iw = ic->arg[2];
1108     int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1109     struct ieee_float_value fra;
1110     struct ieee_float_value frb;
1111     struct ieee_float_value frc;
1112     double result = 0.0;
1113     int nan = 0, cc;
1114    
1115 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1116 dpavlin 20
1117     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1118     ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1119     ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1120     if (fra.nan || frb.nan || frc.nan)
1121     nan = 1;
1122     else
1123     result = fra.f * frc.f - frb.f;
1124     if (nan)
1125     cc = 1;
1126     else {
1127     if (result < 0.0)
1128     cc = 8;
1129     else if (result > 0.0)
1130     cc = 4;
1131     else
1132     cc = 2;
1133     }
1134     /* TODO: Signaling vs Quiet NaN */
1135     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1136     cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1137    
1138     (*(uint64_t *)ic->arg[0]) =
1139     ieee_store_float_value(result, IEEE_FMT_D, nan);
1140     }
1141    
1142    
1143     /*
1144     * fadd, fsub, fdiv: Various Floating-point operationgs
1145     *
1146     * arg[0] = ptr to fra
1147     * arg[1] = ptr to frb
1148     * arg[2] = ptr to frt
1149     */
1150     X(fadd)
1151     {
1152     struct ieee_float_value fra;
1153     struct ieee_float_value frb;
1154     double result = 0.0;
1155     int nan = 0, c;
1156    
1157 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1158 dpavlin 20
1159     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1160     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1161     if (fra.nan || frb.nan)
1162     nan = 1;
1163     else
1164     result = fra.f + frb.f;
1165     if (nan)
1166     c = 1;
1167     else {
1168     if (result < 0.0)
1169     c = 8;
1170     else if (result > 0.0)
1171     c = 4;
1172     else
1173     c = 2;
1174     }
1175     /* TODO: Signaling vs Quiet NaN */
1176     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1177     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1178    
1179     (*(uint64_t *)ic->arg[2]) =
1180     ieee_store_float_value(result, IEEE_FMT_D, nan);
1181     }
1182     X(fadds)
1183     {
1184     /* TODO */
1185     instr(fadd)(cpu, ic);
1186     }
1187     X(fsub)
1188     {
1189     struct ieee_float_value fra;
1190     struct ieee_float_value frb;
1191     double result = 0.0;
1192     int nan = 0, c;
1193    
1194 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1195 dpavlin 20
1196     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1197     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1198     if (fra.nan || frb.nan)
1199     nan = 1;
1200     else
1201     result = fra.f - frb.f;
1202     if (nan)
1203     c = 1;
1204     else {
1205     if (result < 0.0)
1206     c = 8;
1207     else if (result > 0.0)
1208     c = 4;
1209     else
1210     c = 2;
1211     }
1212     /* TODO: Signaling vs Quiet NaN */
1213     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1214     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1215    
1216     (*(uint64_t *)ic->arg[2]) =
1217     ieee_store_float_value(result, IEEE_FMT_D, nan);
1218     }
1219     X(fsubs)
1220     {
1221     /* TODO */
1222     instr(fsub)(cpu, ic);
1223     }
1224     X(fdiv)
1225     {
1226     struct ieee_float_value fra;
1227     struct ieee_float_value frb;
1228     double result = 0.0;
1229     int nan = 0, c;
1230    
1231 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
1232 dpavlin 20
1233     ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1234     ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1235     if (fra.nan || frb.nan || frb.f == 0)
1236     nan = 1;
1237     else
1238     result = fra.f / frb.f;
1239     if (nan)
1240     c = 1;
1241     else {
1242     if (result < 0.0)
1243     c = 8;
1244     else if (result > 0.0)
1245     c = 4;
1246     else
1247     c = 2;
1248     }
1249     /* TODO: Signaling vs Quiet NaN */
1250     cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1251     cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1252    
1253     (*(uint64_t *)ic->arg[2]) =
1254     ieee_store_float_value(result, IEEE_FMT_D, nan);
1255     }
1256     X(fdivs)
1257     {
1258     /* TODO */
1259     instr(fdiv)(cpu, ic);
1260     }
1261    
1262    
1263     /*
1264 dpavlin 14 * llsc: Load-linked and store conditional
1265     *
1266     * arg[0] = copy of the instruction word.
1267     */
1268     X(llsc)
1269     {
1270     int iw = ic->arg[0], len = 4, load = 0, xo = (iw >> 1) & 1023;
1271     int i, rc = iw & 1, rt, ra, rb;
1272     uint64_t addr = 0, value;
1273     unsigned char d[8];
1274    
1275     switch (xo) {
1276     case PPC_31_LDARX:
1277     len = 8;
1278     case PPC_31_LWARX:
1279     load = 1;
1280     break;
1281     case PPC_31_STDCX_DOT:
1282     len = 8;
1283     case PPC_31_STWCX_DOT:
1284     break;
1285     }
1286    
1287     rt = (iw >> 21) & 31;
1288     ra = (iw >> 16) & 31;
1289     rb = (iw >> 11) & 31;
1290    
1291     if (ra != 0)
1292     addr = cpu->cd.ppc.gpr[ra];
1293     addr += cpu->cd.ppc.gpr[rb];
1294    
1295     if (load) {
1296     if (rc) {
1297     fatal("ll: rc-bit set?\n");
1298     exit(1);
1299     }
1300     if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1301     MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1302     fatal("ll: error: TODO\n");
1303     exit(1);
1304     }
1305    
1306     value = 0;
1307     for (i=0; i<len; i++) {
1308     value <<= 8;
1309     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1310     value |= d[i];
1311     else
1312     value |= d[len - 1 - i];
1313     }
1314    
1315     cpu->cd.ppc.gpr[rt] = value;
1316     cpu->cd.ppc.ll_addr = addr;
1317     cpu->cd.ppc.ll_bit = 1;
1318     } else {
1319 dpavlin 20 uint32_t old_so = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_SO;
1320 dpavlin 14 if (!rc) {
1321     fatal("sc: rc-bit not set?\n");
1322     exit(1);
1323     }
1324    
1325     value = cpu->cd.ppc.gpr[rt];
1326    
1327     /* "If the store is performed, bits 0-2 of Condition
1328     Register Field 0 are set to 0b001, otherwise, they are
1329     set to 0b000. The SO bit of the XER is copied to to bit
1330     4 of Condition Register Field 0. */
1331     if (!cpu->cd.ppc.ll_bit || cpu->cd.ppc.ll_addr != addr) {
1332     cpu->cd.ppc.cr &= 0x0fffffff;
1333     if (old_so)
1334     cpu->cd.ppc.cr |= 0x10000000;
1335     cpu->cd.ppc.ll_bit = 0;
1336     return;
1337     }
1338    
1339     for (i=0; i<len; i++) {
1340     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1341     d[len - 1 - i] = value >> (8*i);
1342     else
1343     d[i] = value >> (8*i);
1344     }
1345    
1346     if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1347     MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1348     fatal("sc: error: TODO\n");
1349     exit(1);
1350     }
1351    
1352     cpu->cd.ppc.cr &= 0x0fffffff;
1353     cpu->cd.ppc.cr |= 0x20000000; /* success! */
1354     if (old_so)
1355     cpu->cd.ppc.cr |= 0x10000000;
1356    
1357     /* Clear _all_ CPUs' ll_bits: */
1358     for (i=0; i<cpu->machine->ncpus; i++)
1359     cpu->machine->cpus[i]->cd.ppc.ll_bit = 0;
1360     }
1361     }
1362    
1363    
1364     /*
1365 dpavlin 22 * mtsr, mtsrin: Move To Segment Register [Indirect]
1366 dpavlin 14 *
1367 dpavlin 20 * arg[0] = sr number, or for indirect mode: ptr to rb
1368 dpavlin 14 * arg[1] = ptr to rt
1369 dpavlin 22 *
1370     * TODO: These only work for 32-bit mode!
1371 dpavlin 14 */
1372     X(mtsr)
1373     {
1374 dpavlin 22 int sr_num = ic->arg[0];
1375     uint32_t old = cpu->cd.ppc.sr[sr_num];
1376     cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1377 dpavlin 20
1378 dpavlin 22 if (cpu->cd.ppc.sr[sr_num] != old)
1379     cpu->invalidate_translation_caches(cpu, ic->arg[0] << 28,
1380     INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1381 dpavlin 14 }
1382 dpavlin 20 X(mtsrin)
1383     {
1384 dpavlin 22 int sr_num = reg(ic->arg[0]) >> 28;
1385     uint32_t old = cpu->cd.ppc.sr[sr_num];
1386 dpavlin 20 cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1387 dpavlin 14
1388 dpavlin 22 if (cpu->cd.ppc.sr[sr_num] != old)
1389     cpu->invalidate_translation_caches(cpu, sr_num << 28,
1390     INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1391 dpavlin 20 }
1392 dpavlin 14
1393 dpavlin 20
1394 dpavlin 14 /*
1395     * mfsrin, mtsrin: Move From/To Segment Register Indirect
1396     *
1397 dpavlin 20 * arg[0] = sr number, or for indirect mode: ptr to rb
1398 dpavlin 14 * arg[1] = ptr to rt
1399     */
1400 dpavlin 20 X(mfsr)
1401 dpavlin 14 {
1402     /* TODO: This only works for 32-bit mode */
1403 dpavlin 20 reg(ic->arg[1]) = cpu->cd.ppc.sr[ic->arg[0]];
1404 dpavlin 14 }
1405 dpavlin 20 X(mfsrin)
1406 dpavlin 14 {
1407     /* TODO: This only works for 32-bit mode */
1408     uint32_t sr_num = reg(ic->arg[0]) >> 28;
1409 dpavlin 20 reg(ic->arg[1]) = cpu->cd.ppc.sr[sr_num];
1410 dpavlin 14 }
1411    
1412    
1413     /*
1414 dpavlin 24 * 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 dpavlin 14 * 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 dpavlin 24 * 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 dpavlin 20 * 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 dpavlin 14 * rlwinm:
1522     *
1523 dpavlin 20 * arg[0] = ptr to ra
1524     * arg[1] = mask
1525 dpavlin 14 * arg[2] = copy of the instruction word
1526     */
1527     X(rlwinm)
1528     {
1529 dpavlin 20 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 dpavlin 14 }
1537 dpavlin 20 DOT0(rlwinm)
1538 dpavlin 14
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 dpavlin 20 int sh = (iword >> 11) & 31;
1552     int mb = (iword >> 6) & 31;
1553     int me = (iword >> 1) & 31;
1554     int rc = iword & 1;
1555 dpavlin 14
1556 dpavlin 20 tmp = (tmp << sh) | (tmp >> (32-sh));
1557 dpavlin 14
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 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
1588 dpavlin 14 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 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
1599 dpavlin 14 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
1600     }
1601 dpavlin 20 DOT1(srawi)
1602 dpavlin 14
1603    
1604     /*
1605     * mcrf: Move inside condition register
1606     *
1607 dpavlin 20 * arg[0] = 28-4*bf, arg[1] = 28-4*bfa
1608 dpavlin 14 */
1609     X(mcrf)
1610     {
1611 dpavlin 20 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 dpavlin 14 }
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 dpavlin 22 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 * mfspr: Move from SPR
1690 dpavlin 14 *
1691     * arg[0] = pointer to destination register
1692 dpavlin 20 * arg[1] = pointer to source SPR
1693 dpavlin 14 */
1694 dpavlin 20 X(mfspr) {
1695 dpavlin 22 /* TODO: Check permission */
1696 dpavlin 20 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 dpavlin 14
1716    
1717     /*
1718 dpavlin 20 * mtspr: Move to SPR.
1719 dpavlin 14 *
1720     * arg[0] = pointer to source register
1721 dpavlin 20 * arg[1] = pointer to the SPR
1722 dpavlin 14 */
1723 dpavlin 20 X(mtspr) {
1724 dpavlin 22 /* TODO: Check permission */
1725 dpavlin 20 reg(ic->arg[1]) = reg(ic->arg[0]);
1726     }
1727 dpavlin 22 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 dpavlin 14
1734    
1735     /*
1736 dpavlin 24 * rfi[d]: Return from Interrupt
1737 dpavlin 14 */
1738     X(rfi)
1739     {
1740     uint64_t tmp;
1741    
1742 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
1743 dpavlin 14 tmp &= ~0xffff;
1744 dpavlin 20 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & 0xffff);
1745     reg_access_msr(cpu, &tmp, 1, 0);
1746 dpavlin 14
1747 dpavlin 20 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1748 dpavlin 22 quick_pc_to_pointers(cpu);
1749 dpavlin 14 }
1750 dpavlin 24 X(rfid)
1751     {
1752     uint64_t tmp, mask = 0x800000000000ff73ULL;
1753 dpavlin 14
1754 dpavlin 24 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 dpavlin 14
1759 dpavlin 24 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 dpavlin 14 /*
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 dpavlin 20 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0, 0);
1785 dpavlin 14 }
1786    
1787    
1788     /*
1789     * mtmsr: Move To MSR
1790     *
1791     * arg[0] = pointer to source register
1792 dpavlin 24 * arg[1] = page offset of the next instruction
1793     * arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd)
1794 dpavlin 14 */
1795     X(mtmsr)
1796     {
1797 dpavlin 22 MODE_uint_t old_pc;
1798 dpavlin 24 uint64_t x = reg(ic->arg[0]);
1799 dpavlin 22
1800     /* TODO: check permission! */
1801    
1802 dpavlin 20 /* Synchronize the PC (pointing to _after_ this instruction) */
1803     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1804 dpavlin 22 old_pc = cpu->pc;
1805 dpavlin 20
1806 dpavlin 24 if (!ic->arg[2]) {
1807     uint64_t y;
1808     reg_access_msr(cpu, &y, 0, 0);
1809     x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL);
1810     }
1811 dpavlin 22
1812 dpavlin 24 reg_access_msr(cpu, &x, 1, 1);
1813    
1814 dpavlin 22 /*
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 dpavlin 14 }
1822    
1823    
1824     /*
1825 dpavlin 22 * 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 dpavlin 14 * 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 dpavlin 20 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * (int32_t)ic->arg[1]);
1865 dpavlin 14 }
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 dpavlin 20 int rs = ic->arg[0];
1879 dpavlin 14
1880 dpavlin 20 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 dpavlin 14 while (rs <= 31) {
1887     if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1888 dpavlin 20 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1889     /* exception */
1890     return;
1891     }
1892 dpavlin 14
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 dpavlin 20 int rs = ic->arg[0];
1908 dpavlin 14
1909 dpavlin 20 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 dpavlin 14 while (rs <= 31) {
1916 dpavlin 20 uint32_t tmp = cpu->cd.ppc.gpr[rs];
1917 dpavlin 14 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 dpavlin 20 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1926     /* exception */
1927     return;
1928 dpavlin 14 }
1929    
1930     rs ++;
1931     addr += sizeof(uint32_t);
1932     }
1933     }
1934    
1935    
1936     /*
1937 dpavlin 20 * 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 dpavlin 14 * 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 dpavlin 20 DOT2(extsb)
2024 dpavlin 14 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 dpavlin 20 DOT2(extsh)
2032 dpavlin 14 X(extsw) {
2033     #ifdef MODE32
2034 dpavlin 24 fatal("TODO: extsw: invalid instruction\n");
2035 dpavlin 14 #else
2036     reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);
2037     #endif
2038     }
2039 dpavlin 20 DOT2(extsw)
2040 dpavlin 14 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2041 dpavlin 20 << (reg(ic->arg[1]) & 31); }
2042     DOT2(slw)
2043 dpavlin 24 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 dpavlin 20 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 dpavlin 14 X(srw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2068 dpavlin 20 >> (reg(ic->arg[1]) & 31); }
2069     DOT2(srw)
2070 dpavlin 14 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
2071 dpavlin 20 DOT2(and)
2072 dpavlin 14 X(nand) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) & reg(ic->arg[1])); }
2073 dpavlin 20 DOT2(nand)
2074 dpavlin 14 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
2075 dpavlin 20 DOT2(andc)
2076 dpavlin 14 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
2077 dpavlin 20 DOT2(nor)
2078 dpavlin 22 X(mr) { reg(ic->arg[2]) = reg(ic->arg[1]); }
2079 dpavlin 14 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
2080 dpavlin 20 DOT2(or)
2081 dpavlin 14 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
2082 dpavlin 20 DOT2(orc)
2083 dpavlin 14 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
2084 dpavlin 20 DOT2(xor)
2085 dpavlin 24 X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); }
2086     DOT2(eqv)
2087 dpavlin 14
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 dpavlin 20 DOT1(neg)
2097 dpavlin 14
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 dpavlin 20 DOT2(mullw)
2112 dpavlin 14 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 dpavlin 20 DOT2(mulhw)
2120 dpavlin 14 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 dpavlin 20 DOT2(mulhwu)
2128 dpavlin 14 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 dpavlin 20 DOT2(divw)
2139 dpavlin 14 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 dpavlin 20 DOT2(divwu)
2150 dpavlin 14
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 dpavlin 20 DOT2(add)
2161 dpavlin 14
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 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2176 dpavlin 14 tmp += (uint32_t)reg(ic->arg[1]);
2177     if ((tmp >> 32) != (tmp2 >> 32))
2178 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2179 dpavlin 14 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 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2194 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2195     uint64_t tmp2 = tmp;
2196 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2197 dpavlin 14 tmp += (uint32_t)reg(ic->arg[1]);
2198     if (old_ca)
2199     tmp ++;
2200     if ((tmp >> 32) != (tmp2 >> 32))
2201 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2202 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2203     }
2204 dpavlin 20 DOT2(adde)
2205 dpavlin 14 X(addme)
2206     {
2207     /* TODO: this only works in 32-bit mode */
2208 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2209 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2210     uint64_t tmp2 = tmp;
2211 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2212 dpavlin 14 if (old_ca)
2213     tmp ++;
2214     tmp += 0xffffffffULL;
2215     if ((tmp >> 32) != (tmp2 >> 32))
2216 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2217 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2218     }
2219 dpavlin 20 DOT2(addme)
2220 dpavlin 14 X(addze)
2221     {
2222     /* TODO: this only works in 32-bit mode */
2223 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2224 dpavlin 14 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2225     uint64_t tmp2 = tmp;
2226 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2227 dpavlin 14 if (old_ca)
2228     tmp ++;
2229     if ((tmp >> 32) != (tmp2 >> 32))
2230 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2231 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2232     }
2233 dpavlin 20 DOT2(addze)
2234 dpavlin 14
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 dpavlin 20 X(subf)
2244     {
2245     reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2246     }
2247     DOT2(subf)
2248 dpavlin 14 X(subfc)
2249     {
2250 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2251 dpavlin 14 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2252 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2253 dpavlin 14 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2254     }
2255 dpavlin 20 DOT2(subfc)
2256 dpavlin 14 X(subfe)
2257     {
2258 dpavlin 20 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 dpavlin 14 if (reg(ic->arg[1]) == reg(ic->arg[0])) {
2261     if (old_ca)
2262 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2263 dpavlin 14 } else if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2264 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2265 dpavlin 14
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 dpavlin 20 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 dpavlin 14 X(subfze)
2288     {
2289 dpavlin 20 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2290 dpavlin 14 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2291     uint64_t tmp2 = tmp;
2292 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2293 dpavlin 14 if (old_ca)
2294     tmp ++;
2295     if ((tmp >> 32) != (tmp2 >> 32))
2296 dpavlin 20 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2297 dpavlin 14 reg(ic->arg[2]) = (uint32_t)tmp;
2298     }
2299 dpavlin 20 DOT2(subfze)
2300 dpavlin 14
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 dpavlin 20 #include "tmp_ppc_loadstore.c"
2314    
2315    
2316 dpavlin 14 /*
2317 dpavlin 20 * lfs, stfs: Load/Store Floating-point Single precision
2318     */
2319     X(lfs)
2320     {
2321 dpavlin 22 /* Sync. PC in case of an exception, and remember it: */
2322 dpavlin 20 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2323     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2324 dpavlin 22 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2325     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2326 dpavlin 20 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 dpavlin 22 /* Sync. PC in case of an exception, and remember it: */
2352 dpavlin 20 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2353     cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2354 dpavlin 22 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2355     PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2356 dpavlin 20 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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2382 dpavlin 20
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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2394    
2395 dpavlin 20 /* 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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2410 dpavlin 20
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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2433 dpavlin 20
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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2452    
2453 dpavlin 20 /* 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 dpavlin 22 CHECK_FOR_FPU_EXCEPTION;
2464    
2465 dpavlin 20 /* 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 dpavlin 34 * lvx, stvx: Vector (16-byte) load/store (slow implementation)
2477     *
2478     * arg[0] = v-register nr of rs
2479     * arg[1] = pointer to ra
2480     * arg[2] = pointer to rb
2481     */
2482     X(lvx)
2483     {
2484     MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2485     uint8_t data[16];
2486     uint64_t hi, lo;
2487     int rs = ic->arg[0];
2488    
2489     if (cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
2490     MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
2491     /* exception */
2492     return;
2493     }
2494    
2495     hi = ((uint64_t)data[0] << 56) +
2496     ((uint64_t)data[1] << 48) +
2497     ((uint64_t)data[2] << 40) +
2498     ((uint64_t)data[3] << 32) +
2499     ((uint64_t)data[4] << 24) +
2500     ((uint64_t)data[5] << 16) +
2501     ((uint64_t)data[6] << 8) +
2502     ((uint64_t)data[7]);
2503     lo = ((uint64_t)data[8] << 56) +
2504     ((uint64_t)data[9] << 48) +
2505     ((uint64_t)data[10] << 40) +
2506     ((uint64_t)data[11] << 32) +
2507     ((uint64_t)data[12] << 24) +
2508     ((uint64_t)data[13] << 16) +
2509     ((uint64_t)data[14] << 8) +
2510     ((uint64_t)data[15]);
2511    
2512     cpu->cd.ppc.vr_hi[rs] = hi; cpu->cd.ppc.vr_lo[rs] = lo;
2513     }
2514     X(stvx)
2515     {
2516     uint8_t data[16];
2517     MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2518     int rs = ic->arg[0];
2519     uint64_t hi = cpu->cd.ppc.vr_hi[rs], lo = cpu->cd.ppc.vr_lo[rs];
2520    
2521     data[0] = hi >> 56;
2522     data[1] = hi >> 48;
2523     data[2] = hi >> 40;
2524     data[3] = hi >> 32;
2525     data[4] = hi >> 24;
2526     data[5] = hi >> 16;
2527     data[6] = hi >> 8;
2528     data[7] = hi;
2529     data[8] = lo >> 56;
2530     data[9] = lo >> 48;
2531     data[10] = lo >> 40;
2532     data[11] = lo >> 32;
2533     data[12] = lo >> 24;
2534     data[13] = lo >> 16;
2535     data[14] = lo >> 8;
2536     data[15] = lo;
2537    
2538     cpu->memory_rw(cpu, cpu->mem, addr, data,
2539     sizeof(data), MEM_WRITE, CACHE_DATA);
2540     }
2541    
2542    
2543     /*
2544     * vxor: Vector (16-byte) XOR
2545     *
2546     * arg[0] = v-register nr of source 1
2547     * arg[1] = v-register nr of source 2
2548     * arg[2] = v-register nr of destination
2549     */
2550     X(vxor)
2551     {
2552     cpu->cd.ppc.vr_hi[ic->arg[2]] =
2553     cpu->cd.ppc.vr_hi[ic->arg[0]] ^ cpu->cd.ppc.vr_hi[ic->arg[1]];
2554     cpu->cd.ppc.vr_lo[ic->arg[2]] =
2555     cpu->cd.ppc.vr_lo[ic->arg[0]] ^ cpu->cd.ppc.vr_lo[ic->arg[1]];
2556     }
2557    
2558    
2559     /*
2560 dpavlin 20 * tlbia: TLB invalidate all
2561     */
2562     X(tlbia)
2563     {
2564 dpavlin 24 fatal("[ tlbia ]\n");
2565 dpavlin 20 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2566     }
2567    
2568    
2569     /*
2570 dpavlin 14 * tlbie: TLB invalidate
2571     */
2572     X(tlbie)
2573     {
2574 dpavlin 24 /* fatal("[ tlbie ]\n"); */
2575 dpavlin 20 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2576     INVALIDATE_VADDR);
2577 dpavlin 14 }
2578    
2579    
2580     /*
2581 dpavlin 20 * sc: Syscall.
2582     */
2583     X(sc)
2584     {
2585     /* Synchronize the PC (pointing to _after_ this instruction) */
2586     cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2587    
2588     ppc_exception(cpu, PPC_EXCEPTION_SC);
2589 dpavlin 22
2590     /* This caused an update to the PC register, so there is no need
2591     to worry about the next instruction being an end_of_page. */
2592 dpavlin 20 }
2593    
2594    
2595     /*
2596 dpavlin 14 * user_syscall: Userland syscall.
2597     *
2598     * arg[0] = syscall "level" (usually 0)
2599     */
2600     X(user_syscall)
2601     {
2602     useremul_syscall(cpu, ic->arg[0]);
2603 dpavlin 24
2604     if (!cpu->running) {
2605     cpu->n_translated_instrs --;
2606     cpu->cd.ppc.next_ic = &nothing_call;
2607     }
2608 dpavlin 14 }
2609    
2610    
2611     /*
2612     * openfirmware:
2613     */
2614     X(openfirmware)
2615     {
2616     of_emul(cpu);
2617 dpavlin 22 if (cpu->running == 0) {
2618 dpavlin 30 cpu->n_translated_instrs --;
2619     cpu->cd.ppc.next_ic = &nothing_call;
2620 dpavlin 22 }
2621 dpavlin 20 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2622 dpavlin 14 if (cpu->machine->show_trace_tree)
2623     cpu_functioncall_trace_return(cpu);
2624 dpavlin 22 quick_pc_to_pointers(cpu);
2625 dpavlin 14 }
2626    
2627    
2628 dpavlin 20 /*
2629 dpavlin 22 * tlbsx_dot: TLB scan
2630     */
2631     X(tlbsx_dot)
2632     {
2633     /* TODO */
2634     cpu->cd.ppc.cr &= ~(0xf0000000);
2635     cpu->cd.ppc.cr |= 0x20000000;
2636     cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2637     }
2638    
2639    
2640     /*
2641 dpavlin 20 * tlbli:
2642     */
2643     X(tlbli)
2644     {
2645 dpavlin 22 fatal("tlbli\n");
2646     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2647 dpavlin 20 }
2648 dpavlin 14
2649    
2650     /*
2651 dpavlin 20 * tlbld:
2652 dpavlin 14 */
2653 dpavlin 20 X(tlbld)
2654 dpavlin 14 {
2655 dpavlin 20 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2656     MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2657 dpavlin 14
2658 dpavlin 22 fatal("tlbld\n");
2659     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2660 dpavlin 14 }
2661    
2662    
2663     /*****************************************************************************/
2664    
2665    
2666     X(end_of_page)
2667     {
2668     /* Update the PC: (offset 0, but on the next page) */
2669 dpavlin 22 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2670     cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2671 dpavlin 14
2672     /* Find the new physical page and update the translation pointers: */
2673 dpavlin 22 quick_pc_to_pointers(cpu);
2674 dpavlin 14
2675     /* end_of_page doesn't count as an executed instruction: */
2676     cpu->n_translated_instrs --;
2677     }
2678    
2679    
2680     /*****************************************************************************/
2681    
2682    
2683     /*
2684     * ppc_instr_to_be_translated():
2685     *
2686 dpavlin 24 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2687 dpavlin 14 * valid data for the translated instruction, or a "nothing" instruction if
2688     * there was a translation failure. The newly translated instruction is then
2689     * executed.
2690     */
2691     X(to_be_translated)
2692     {
2693     uint64_t addr, low_pc, tmp_addr;
2694 dpavlin 20 uint32_t iword, mask;
2695 dpavlin 14 unsigned char *page;
2696     unsigned char ib[4];
2697     int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
2698     xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,
2699 dpavlin 20 bfa, fp, byterev, nb, mb, me;
2700 dpavlin 14 void (*samepage_function)(struct cpu *, struct ppc_instr_call *);
2701     void (*rc_f)(struct cpu *, struct ppc_instr_call *);
2702    
2703     /* Figure out the (virtual) address of the instruction: */
2704     low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
2705     / sizeof(struct ppc_instr_call);
2706     addr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
2707     << PPC_INSTR_ALIGNMENT_SHIFT);
2708     addr += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2709     cpu->pc = addr;
2710     addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
2711    
2712     /* Read the instruction word from memory: */
2713 dpavlin 24 #ifdef MODE32
2714     page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12];
2715     #else
2716     {
2717     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2718     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2719     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2720     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2721     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2722     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2723     DYNTRANS_L3N)) & mask3;
2724     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1];
2725     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2726     page = l3->host_load[x3];
2727     }
2728     #endif
2729 dpavlin 14
2730     if (page != NULL) {
2731     /* fatal("TRANSLATION HIT!\n"); */
2732     memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2733     } else {
2734     /* fatal("TRANSLATION MISS!\n"); */
2735     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2736     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2737 dpavlin 20 fatal("PPC to_be_translated(): "
2738 dpavlin 14 "read failed: TODO\n");
2739 dpavlin 20 exit(1);
2740     /* goto bad; */
2741 dpavlin 14 }
2742     }
2743    
2744     iword = *((uint32_t *)&ib[0]);
2745 dpavlin 22 iword = BE32_TO_HOST(iword);
2746 dpavlin 14
2747    
2748     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2749     #include "cpu_dyntrans.c"
2750     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2751    
2752    
2753     /*
2754     * Translate the instruction:
2755     */
2756    
2757     main_opcode = iword >> 26;
2758    
2759     switch (main_opcode) {
2760    
2761 dpavlin 22 case 0x04:
2762 dpavlin 34 if (iword == 0x12739cc4) {
2763     /* vxor v19,v19,v19 */
2764     ic->f = instr(vxor);
2765     ic->arg[0] = 19;
2766     ic->arg[1] = 19;
2767     ic->arg[2] = 19;
2768     } else {
2769 dpavlin 42 if (!cpu->translation_readahead)
2770     fatal("[ TODO: Unimplemented ALTIVEC, iword"
2771     " = 0x%08"PRIx32"x ]\n", iword);
2772 dpavlin 34 goto bad;
2773     }
2774 dpavlin 22 break;
2775    
2776 dpavlin 14 case PPC_HI6_MULLI:
2777     rt = (iword >> 21) & 31;
2778     ra = (iword >> 16) & 31;
2779     imm = (int16_t)(iword & 0xffff);
2780     ic->f = instr(mulli);
2781     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2782     ic->arg[1] = (ssize_t)imm;
2783     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2784     break;
2785    
2786     case PPC_HI6_SUBFIC:
2787     rt = (iword >> 21) & 31;
2788     ra = (iword >> 16) & 31;
2789     imm = (int16_t)(iword & 0xffff);
2790     ic->f = instr(subfic);
2791     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2792     ic->arg[1] = (ssize_t)imm;
2793     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2794     break;
2795    
2796     case PPC_HI6_CMPLI:
2797     case PPC_HI6_CMPI:
2798     bf = (iword >> 23) & 7;
2799     l_bit = (iword >> 21) & 1;
2800     ra = (iword >> 16) & 31;
2801     if (main_opcode == PPC_HI6_CMPLI) {
2802     imm = iword & 0xffff;
2803     if (l_bit)
2804     ic->f = instr(cmpldi);
2805     else
2806     ic->f = instr(cmplwi);
2807     } else {
2808     imm = (int16_t)(iword & 0xffff);
2809     if (l_bit)
2810     ic->f = instr(cmpdi);
2811 dpavlin 22 else {
2812     if (bf == 0)
2813     ic->f = instr(cmpwi_cr0);
2814     else
2815     ic->f = instr(cmpwi);
2816     }
2817 dpavlin 14 }
2818     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2819     ic->arg[1] = (ssize_t)imm;
2820 dpavlin 20 ic->arg[2] = 28 - 4 * bf;
2821 dpavlin 14 break;
2822    
2823     case PPC_HI6_ADDIC:
2824     case PPC_HI6_ADDIC_DOT:
2825     if (cpu->cd.ppc.bits == 64) {
2826 dpavlin 42 if (!cpu->translation_readahead)
2827     fatal("addic for 64-bit: TODO\n");
2828 dpavlin 14 goto bad;
2829     }
2830     rt = (iword >> 21) & 31;
2831     ra = (iword >> 16) & 31;
2832     imm = (int16_t)(iword & 0xffff);
2833     if (main_opcode == PPC_HI6_ADDIC)
2834     ic->f = instr(addic);
2835     else
2836     ic->f = instr(addic_dot);
2837     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2838 dpavlin 20 ic->arg[1] = imm;
2839 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2840     break;
2841    
2842     case PPC_HI6_ADDI:
2843     case PPC_HI6_ADDIS:
2844     rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2845     ic->f = instr(addi);
2846     if (ra == 0)
2847 dpavlin 22 ic->f = instr(li);
2848 dpavlin 14 else
2849     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2850 dpavlin 20 ic->arg[1] = (int16_t)(iword & 0xffff);
2851 dpavlin 14 if (main_opcode == PPC_HI6_ADDIS)
2852     ic->arg[1] <<= 16;
2853 dpavlin 22 if (ra == 0 && ic->arg[1] == 0)
2854     ic->f = instr(li_0);
2855 dpavlin 14 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2856     break;
2857    
2858     case PPC_HI6_ANDI_DOT:
2859     case PPC_HI6_ANDIS_DOT:
2860     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2861     ic->f = instr(andi_dot);
2862     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2863     ic->arg[1] = iword & 0xffff;
2864     if (main_opcode == PPC_HI6_ANDIS_DOT)
2865     ic->arg[1] <<= 16;
2866     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2867     break;
2868    
2869     case PPC_HI6_ORI:
2870     case PPC_HI6_ORIS:
2871     case PPC_HI6_XORI:
2872     case PPC_HI6_XORIS:
2873     rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2874     if (main_opcode == PPC_HI6_ORI ||
2875     main_opcode == PPC_HI6_ORIS)
2876     ic->f = instr(ori);
2877     else
2878     ic->f = instr(xori);
2879     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2880     ic->arg[1] = iword & 0xffff;
2881     if (main_opcode == PPC_HI6_ORIS ||
2882     main_opcode == PPC_HI6_XORIS)
2883     ic->arg[1] <<= 16;
2884     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2885     break;
2886    
2887     case PPC_HI6_LBZ:
2888     case PPC_HI6_LBZU:
2889     case PPC_HI6_LHZ:
2890     case PPC_HI6_LHZU:
2891 dpavlin 20 case PPC_HI6_LHA:
2892     case PPC_HI6_LHAU:
2893 dpavlin 14 case PPC_HI6_LWZ:
2894     case PPC_HI6_LWZU:
2895 dpavlin 24 case PPC_HI6_LD:
2896 dpavlin 14 case PPC_HI6_LFD:
2897 dpavlin 20 case PPC_HI6_LFS:
2898 dpavlin 14 case PPC_HI6_STB:
2899     case PPC_HI6_STBU:
2900     case PPC_HI6_STH:
2901     case PPC_HI6_STHU:
2902     case PPC_HI6_STW:
2903     case PPC_HI6_STWU:
2904 dpavlin 24 case PPC_HI6_STD:
2905 dpavlin 20 case PPC_HI6_STFD:
2906     case PPC_HI6_STFS:
2907 dpavlin 14 rs = (iword >> 21) & 31;
2908     ra = (iword >> 16) & 31;
2909 dpavlin 20 imm = (int16_t)iword;
2910 dpavlin 14 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2911 dpavlin 20 ic->f = NULL;
2912 dpavlin 14 switch (main_opcode) {
2913 dpavlin 20 case PPC_HI6_LBZ: load=1; break;
2914     case PPC_HI6_LBZU: load=1; update=1; break;
2915     case PPC_HI6_LHA: load=1; size=1; zero=0; break;
2916     case PPC_HI6_LHAU: load=1; size=1; zero=0; update=1; break;
2917     case PPC_HI6_LHZ: load=1; size=1; break;
2918     case PPC_HI6_LHZU: load=1; size=1; update=1; break;
2919     case PPC_HI6_LWZ: load=1; size=2; break;
2920     case PPC_HI6_LWZU: load=1; size=2; update=1; break;
2921 dpavlin 24 case PPC_HI6_LD: load=1; size=3; break;
2922 dpavlin 20 case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break;
2923     case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break;
2924 dpavlin 14 case PPC_HI6_STB: break;
2925 dpavlin 20 case PPC_HI6_STBU: update=1; break;
2926     case PPC_HI6_STH: size=1; break;
2927     case PPC_HI6_STHU: size=1; update=1; break;
2928     case PPC_HI6_STW: size=2; break;
2929     case PPC_HI6_STWU: size=2; update=1; break;
2930 dpavlin 24 case PPC_HI6_STD: size=3; break;
2931 dpavlin 20 case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;
2932     case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;
2933 dpavlin 14 }
2934 dpavlin 20 if (ic->f == NULL) {
2935 dpavlin 14 ic->f =
2936     #ifdef MODE32
2937     ppc32_loadstore
2938     #else
2939     ppc_loadstore
2940     #endif
2941     [size + 4*zero + 8*load + (imm==0? 16 : 0)
2942     + 32*update];
2943     }
2944     if (ra == 0 && update) {
2945 dpavlin 42 if (!cpu->translation_readahead)
2946     fatal("TODO: ra=0 && update?\n");
2947 dpavlin 14 goto bad;
2948     }
2949     if (fp)
2950     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
2951     else
2952     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2953     if (ra == 0)
2954     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
2955     else
2956     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2957     ic->arg[2] = (ssize_t)imm;
2958     break;
2959    
2960     case PPC_HI6_BC:
2961     aa_bit = (iword >> 1) & 1;
2962     lk_bit = iword & 1;
2963     bo = (iword >> 21) & 31;
2964     bi = (iword >> 16) & 31;
2965     tmp_addr = (int64_t)(int16_t)(iword & 0xfffc);
2966     if (aa_bit) {
2967 dpavlin 42 if (!cpu->translation_readahead)
2968     fatal("aa_bit: NOT YET\n");
2969 dpavlin 14 goto bad;
2970     }
2971 dpavlin 20 if (lk_bit) {
2972     ic->f = instr(bcl);
2973     samepage_function = instr(bcl_samepage);
2974     } else {
2975     ic->f = instr(bc);
2976 dpavlin 22 if ((bo & 0x14) == 0x04) {
2977     samepage_function = bo & 8?
2978     instr(bc_samepage_simple1) :
2979     instr(bc_samepage_simple0);
2980     } else
2981 dpavlin 20 samepage_function = instr(bc_samepage);
2982     }
2983 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2984 dpavlin 14 ic->arg[1] = bo;
2985 dpavlin 22 ic->arg[2] = 31-bi;
2986 dpavlin 14 /* Branches are calculated as cur PC + offset. */
2987     /* Special case: branch within the same page: */
2988     {
2989     uint64_t mask_within_page =
2990     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2991     uint64_t old_pc = addr;
2992 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2993 dpavlin 14 if ((old_pc & ~mask_within_page) ==
2994     (new_pc & ~mask_within_page)) {
2995     ic->f = samepage_function;
2996     ic->arg[0] = (size_t) (
2997     cpu->cd.ppc.cur_ic_page +
2998     ((new_pc & mask_within_page) >> 2));
2999     }
3000     }
3001     break;
3002    
3003     case PPC_HI6_SC:
3004     ic->arg[0] = (iword >> 5) & 0x7f;
3005 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
3006 dpavlin 14 if (cpu->machine->userland_emul != NULL)
3007     ic->f = instr(user_syscall);
3008 dpavlin 20 else if (iword == 0x44ee0002) {
3009 dpavlin 14 /* Special case/magic hack for OpenFirmware emul: */
3010 dpavlin 20 ic->f = instr(openfirmware);
3011     } else
3012     ic->f = instr(sc);
3013 dpavlin 14 break;
3014    
3015     case PPC_HI6_B:
3016     aa_bit = (iword & 2) >> 1;
3017     lk_bit = iword & 1;
3018     tmp_addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
3019     tmp_addr = (int64_t)tmp_addr >> 6;
3020     if (lk_bit) {
3021     if (cpu->machine->show_trace_tree) {
3022     ic->f = instr(bl_trace);
3023     samepage_function = instr(bl_samepage_trace);
3024     } else {
3025     ic->f = instr(bl);
3026     samepage_function = instr(bl_samepage);
3027     }
3028     } else {
3029     ic->f = instr(b);
3030     samepage_function = instr(b_samepage);
3031     }
3032 dpavlin 22 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
3033     ic->arg[1] = (addr & 0xffc) + 4;
3034 dpavlin 14 /* Branches are calculated as cur PC + offset. */
3035     /* Special case: branch within the same page: */
3036     {
3037     uint64_t mask_within_page =
3038     ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
3039     uint64_t old_pc = addr;
3040 dpavlin 22 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
3041 dpavlin 14 if ((old_pc & ~mask_within_page) ==
3042     (new_pc & ~mask_within_page)) {
3043     ic->f = samepage_function;
3044     ic->arg[0] = (size_t) (
3045     cpu->cd.ppc.cur_ic_page +
3046     ((new_pc & mask_within_page) >> 2));
3047     }
3048     }
3049 dpavlin 20 if (aa_bit) {
3050     if (lk_bit) {
3051     if (cpu->machine->show_trace_tree) {
3052     ic->f = instr(bla_trace);
3053     } else {
3054     ic->f = instr(bla);
3055     }
3056     } else {
3057     ic->f = instr(ba);
3058     }
3059     ic->arg[0] = (ssize_t)tmp_addr;
3060     }
3061 dpavlin 14 break;
3062    
3063     case PPC_HI6_19:
3064     xo = (iword >> 1) & 1023;
3065     switch (xo) {
3066    
3067     case PPC_19_BCLR:
3068     case PPC_19_BCCTR:
3069     bo = (iword >> 21) & 31;
3070     bi = (iword >> 16) & 31;
3071     bh = (iword >> 11) & 3;
3072     lk_bit = iword & 1;
3073     if (xo == PPC_19_BCLR) {
3074     if (lk_bit)
3075     ic->f = instr(bclr_l);
3076 dpavlin 20 else {
3077 dpavlin 14 ic->f = instr(bclr);
3078 dpavlin 20 if (!cpu->machine->show_trace_tree &&
3079     (bo & 0x14) == 0x14)
3080     ic->f = instr(bclr_20);
3081     }
3082 dpavlin 14 } else {
3083 dpavlin 42 if (!(bo & 4)) {
3084     if (!cpu->translation_readahead)
3085     fatal("TODO: bclr/bcctr "
3086     "bo bit 2 clear!\n");
3087     goto bad;
3088     }
3089 dpavlin 14 if (lk_bit)
3090     ic->f = instr(bcctr_l);
3091     else
3092     ic->f = instr(bcctr);
3093     }
3094     ic->arg[0] = bo;
3095 dpavlin 20 ic->arg[1] = 31 - bi;
3096 dpavlin 14 ic->arg[2] = bh;
3097     break;
3098    
3099     case PPC_19_ISYNC:
3100     /* TODO */
3101     ic->f = instr(nop);
3102     break;
3103    
3104     case PPC_19_RFI:
3105     ic->f = instr(rfi);
3106     break;
3107    
3108 dpavlin 24 case PPC_19_RFID:
3109     ic->f = instr(rfid);
3110     break;
3111    
3112 dpavlin 14 case PPC_19_MCRF:
3113     bf = (iword >> 23) & 7;
3114     bfa = (iword >> 18) & 7;
3115 dpavlin 20 ic->arg[0] = 28 - 4*bf;
3116     ic->arg[1] = 28 - 4*bfa;
3117 dpavlin 14 ic->f = instr(mcrf);
3118     break;
3119    
3120     case PPC_19_CRAND:
3121     case PPC_19_CRANDC:
3122     case PPC_19_CREQV:
3123     case PPC_19_CROR:
3124 dpavlin 22 case PPC_19_CRORC:
3125 dpavlin 20 case PPC_19_CRNOR:
3126 dpavlin 14 case PPC_19_CRXOR:
3127     switch (xo) {
3128     case PPC_19_CRAND: ic->f = instr(crand); break;
3129     case PPC_19_CRANDC: ic->f = instr(crandc); break;
3130     case PPC_19_CREQV: ic->f = instr(creqv); break;
3131     case PPC_19_CROR: ic->f = instr(cror); break;
3132 dpavlin 22 case PPC_19_CRORC: ic->f = instr(crorc); break;
3133 dpavlin 20 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3134 dpavlin 14 case PPC_19_CRXOR: ic->f = instr(crxor); break;
3135     }
3136     ic->arg[0] = iword;
3137     break;
3138    
3139     default:goto bad;
3140     }
3141     break;
3142    
3143 dpavlin 20 case PPC_HI6_RLWNM:
3144     case PPC_HI6_RLWINM:
3145     ra = (iword >> 16) & 31;
3146     mb = (iword >> 6) & 31;
3147     me = (iword >> 1) & 31;
3148     rc = iword & 1;
3149     mask = 0;
3150     for (;;) {
3151     mask |= ((uint32_t)0x80000000 >> mb);
3152     if (mb == me)
3153     break;
3154     mb ++; mb &= 31;
3155     }
3156     switch (main_opcode) {
3157     case PPC_HI6_RLWNM:
3158     ic->f = rc? instr(rlwnm_dot) : instr(rlwnm); break;
3159     case PPC_HI6_RLWINM:
3160     ic->f = rc? instr(rlwinm_dot) : instr(rlwinm); break;
3161     }
3162     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3163     ic->arg[1] = mask;
3164     ic->arg[2] = (uint32_t)iword;
3165     break;
3166    
3167 dpavlin 14 case PPC_HI6_RLWIMI:
3168     rs = (iword >> 21) & 31;
3169     ra = (iword >> 16) & 31;
3170 dpavlin 20 ic->f = instr(rlwimi);
3171 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3172     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3173     ic->arg[2] = (uint32_t)iword;
3174     break;
3175    
3176     case PPC_HI6_LMW:
3177     case PPC_HI6_STMW:
3178     /* NOTE: Loads use rt, not rs. */
3179     rs = (iword >> 21) & 31;
3180     ra = (iword >> 16) & 31;
3181     ic->arg[0] = rs;
3182     if (ra == 0)
3183     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3184     else
3185     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3186     ic->arg[2] = (int32_t)(int16_t)iword;
3187     switch (main_opcode) {
3188     case PPC_HI6_LMW:
3189     ic->f = instr(lmw);
3190     break;
3191     case PPC_HI6_STMW:
3192     ic->f = instr(stmw);
3193     break;
3194     }
3195     break;
3196    
3197     case PPC_HI6_30:
3198     xo = (iword >> 2) & 7;
3199     switch (xo) {
3200    
3201 dpavlin 24 case PPC_30_RLDICL:
3202 dpavlin 14 case PPC_30_RLDICR:
3203 dpavlin 24 case PPC_30_RLDIMI:
3204     switch (xo) {
3205     case PPC_30_RLDICL: ic->f = instr(rldicl); break;
3206     case PPC_30_RLDICR: ic->f = instr(rldicr); break;
3207     case PPC_30_RLDIMI: ic->f = instr(rldimi); break;
3208     }
3209 dpavlin 14 ic->arg[0] = iword;
3210     if (cpu->cd.ppc.bits == 32) {
3211 dpavlin 42 if (!cpu->translation_readahead)
3212     fatal("TODO: rld* in 32-bit mode?\n");
3213 dpavlin 14 goto bad;
3214     }
3215     break;
3216    
3217     default:goto bad;
3218     }
3219     break;
3220    
3221     case PPC_HI6_31:
3222     xo = (iword >> 1) & 1023;
3223     switch (xo) {
3224    
3225     case PPC_31_CMPL:
3226     case PPC_31_CMP:
3227     bf = (iword >> 23) & 7;
3228     l_bit = (iword >> 21) & 1;
3229     ra = (iword >> 16) & 31;
3230     rb = (iword >> 11) & 31;
3231     if (xo == PPC_31_CMPL) {
3232     if (l_bit)
3233     ic->f = instr(cmpld);
3234     else
3235     ic->f = instr(cmplw);
3236     } else {
3237     if (l_bit)
3238     ic->f = instr(cmpd);
3239 dpavlin 22 else {
3240     if (bf == 0)
3241     ic->f = instr(cmpw_cr0);
3242     else
3243     ic->f = instr(cmpw);
3244     }
3245 dpavlin 14 }
3246     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3247     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3248 dpavlin 20 ic->arg[2] = 28 - 4*bf;
3249 dpavlin 14 break;
3250    
3251     case PPC_31_CNTLZW:
3252     rs = (iword >> 21) & 31;
3253     ra = (iword >> 16) & 31;
3254     rc = iword & 1;
3255     if (rc) {
3256 dpavlin 42 if (!cpu->translation_readahead)
3257     fatal("TODO: rc\n");
3258 dpavlin 14 goto bad;
3259     }
3260     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3261     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3262     ic->f = instr(cntlzw);
3263     break;
3264    
3265     case PPC_31_MFSPR:
3266     rt = (iword >> 21) & 31;
3267     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3268 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3269 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3270 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3271 dpavlin 14 switch (spr) {
3272 dpavlin 20 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3273     default: ic->f = instr(mfspr);
3274 dpavlin 14 }
3275     break;
3276    
3277     case PPC_31_MTSPR:
3278     rs = (iword >> 21) & 31;
3279     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3280 dpavlin 20 debug_spr_usage(cpu->pc, spr);
3281 dpavlin 14 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3282 dpavlin 20 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3283 dpavlin 22 switch (spr) {
3284     case SPR_LR:
3285     ic->f = instr(mtlr);
3286     break;
3287     case SPR_CTR:
3288     ic->f = instr(mtctr);
3289     break;
3290     default:ic->f = instr(mtspr);
3291     }
3292 dpavlin 14 break;
3293    
3294     case PPC_31_MFCR:
3295     rt = (iword >> 21) & 31;
3296     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3297     ic->f = instr(mfcr);
3298     break;
3299    
3300     case PPC_31_MFMSR:
3301     rt = (iword >> 21) & 31;
3302     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3303     ic->f = instr(mfmsr);
3304     break;
3305    
3306     case PPC_31_MTMSR:
3307 dpavlin 24 case PPC_31_MTMSRD:
3308 dpavlin 14 rs = (iword >> 21) & 31;
3309     l_bit = (iword >> 16) & 1;
3310     if (l_bit) {
3311 dpavlin 42 if (!cpu->translation_readahead)
3312     fatal("TODO: mtmsr l-bit\n");
3313 dpavlin 14 goto bad;
3314     }
3315     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3316 dpavlin 20 ic->arg[1] = (addr & 0xfff) + 4;
3317 dpavlin 24 ic->arg[2] = xo == PPC_31_MTMSRD;
3318 dpavlin 14 ic->f = instr(mtmsr);
3319     break;
3320    
3321     case PPC_31_MTCRF:
3322     rs = (iword >> 21) & 31;
3323     {
3324     int i, fxm = (iword >> 12) & 255;
3325     uint32_t tmp = 0;
3326     for (i=0; i<8; i++, fxm <<= 1) {
3327     tmp <<= 4;
3328     if (fxm & 128)
3329     tmp |= 0xf;
3330     }
3331     ic->arg[1] = (uint32_t)tmp;
3332     }
3333     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3334     ic->f = instr(mtcrf);
3335     break;
3336    
3337     case PPC_31_MFSRIN:
3338     case PPC_31_MTSRIN:
3339     rt = (iword >> 21) & 31;
3340     rb = (iword >> 11) & 31;
3341     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3342     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3343     switch (xo) {
3344     case PPC_31_MFSRIN: ic->f = instr(mfsrin); break;
3345     case PPC_31_MTSRIN: ic->f = instr(mtsrin); break;
3346     }
3347     if (cpu->cd.ppc.bits == 64) {
3348 dpavlin 42 if (!cpu->translation_readahead)
3349     fatal("Not yet for 64-bit mode\n");
3350 dpavlin 14 goto bad;
3351     }
3352     break;
3353    
3354 dpavlin 20 case PPC_31_MFSR:
3355 dpavlin 14 case PPC_31_MTSR:
3356     rt = (iword >> 21) & 31;
3357     ic->arg[0] = (iword >> 16) & 15;
3358     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3359 dpavlin 20 switch (xo) {
3360     case PPC_31_MFSR: ic->f = instr(mfsr); break;
3361     case PPC_31_MTSR: ic->f = instr(mtsr); break;
3362     }
3363 dpavlin 14 if (cpu->cd.ppc.bits == 64) {
3364 dpavlin 42 if (!cpu->translation_readahead)
3365     fatal("Not yet for 64-bit mode\n");
3366 dpavlin 14 goto bad;
3367     }
3368     break;
3369    
3370     case PPC_31_SRAWI:
3371     rs = (iword >> 21) & 31;
3372     ra = (iword >> 16) & 31;
3373     sh = (iword >> 11) & 31;
3374     rc = iword & 1;
3375     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3376     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3377     ic->arg[2] = sh;
3378     if (rc)
3379     ic->f = instr(srawi_dot);
3380     else
3381     ic->f = instr(srawi);
3382     break;
3383    
3384     case PPC_31_SYNC:
3385 dpavlin 24 case PPC_31_DSSALL:
3386 dpavlin 14 case PPC_31_EIEIO:
3387     case PPC_31_DCBST:
3388     case PPC_31_DCBTST:
3389     case PPC_31_DCBF:
3390     case PPC_31_DCBT:
3391     case PPC_31_ICBI:
3392     ic->f = instr(nop);
3393     break;
3394    
3395     case PPC_31_DCBZ:
3396     ra = (iword >> 16) & 31;
3397     rb = (iword >> 11) & 31;
3398     if (ra == 0)
3399     ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);
3400     else
3401     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3402     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3403 dpavlin 20 ic->arg[2] = addr & 0xfff;
3404 dpavlin 14 ic->f = instr(dcbz);
3405     break;
3406    
3407 dpavlin 20 case PPC_31_TLBIA:
3408     ic->f = instr(tlbia);
3409     break;
3410    
3411     case PPC_31_TLBSYNC:
3412     /* According to IBM, "Ensures that a tlbie and
3413     tlbia instruction executed by one processor has
3414     completed on all other processors.", which in
3415     GXemul means a nop :-) */
3416     ic->f = instr(nop);
3417     break;
3418    
3419 dpavlin 14 case PPC_31_TLBIE:
3420 dpavlin 20 /* TODO: POWER also uses ra? */
3421     rb = (iword >> 11) & 31;
3422     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3423 dpavlin 14 ic->f = instr(tlbie);
3424     break;
3425    
3426 dpavlin 20 case PPC_31_TLBLD: /* takes an arg */
3427     rb = (iword >> 11) & 31;
3428     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3429     ic->f = instr(tlbld);
3430     break;
3431    
3432     case PPC_31_TLBLI: /* takes an arg */
3433     rb = (iword >> 11) & 31;
3434     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3435     ic->f = instr(tlbli);
3436     break;
3437    
3438 dpavlin 22 case PPC_31_TLBSX_DOT:
3439     /* TODO */
3440     ic->f = instr(tlbsx_dot);
3441     break;
3442    
3443 dpavlin 14 case PPC_31_MFTB:
3444     rt = (iword >> 21) & 31;
3445     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3446     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3447     switch (spr) {
3448     case 268: ic->f = instr(mftb); break;
3449     case 269: ic->f = instr(mftbu); break;
3450 dpavlin 42 default:if (!cpu->translation_readahead)
3451     fatal("mftb spr=%i?\n", spr);
3452 dpavlin 14 goto bad;
3453     }
3454     break;
3455    
3456     case PPC_31_NEG:
3457     rt = (iword >> 21) & 31;
3458     ra = (iword >> 16) & 31;
3459     rc = iword & 1;
3460     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3461     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3462     if (rc)
3463     ic->f = instr(neg_dot);
3464     else
3465     ic->f = instr(neg);
3466     break;
3467    
3468     case PPC_31_LWARX:
3469     case PPC_31_LDARX:
3470     case PPC_31_STWCX_DOT:
3471     case PPC_31_STDCX_DOT:
3472     ic->arg[0] = iword;
3473     ic->f = instr(llsc);
3474     break;
3475    
3476 dpavlin 20 case PPC_31_LSWI:
3477     case PPC_31_STSWI:
3478     rs = (iword >> 21) & 31;
3479     ra = (iword >> 16) & 31;
3480     nb = (iword >> 11) & 31;
3481     ic->arg[0] = rs;
3482     if (ra == 0)
3483     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3484     else
3485     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3486     ic->arg[2] = nb == 0? 32 : nb;
3487     switch (xo) {
3488     case PPC_31_LSWI: ic->f = instr(lswi); break;
3489     case PPC_31_STSWI: ic->f = instr(stswi); break;
3490     }
3491     break;
3492    
3493 dpavlin 22 case PPC_31_WRTEEI:
3494     ic->arg[0] = iword & 0x8000;
3495     ic->f = instr(wrteei);
3496     break;
3497    
3498 dpavlin 20 case 0x1c3:
3499     fatal("[ mtdcr: TODO ]\n");
3500     ic->f = instr(nop);
3501     break;
3502    
3503 dpavlin 14 case PPC_31_LBZX:
3504     case PPC_31_LBZUX:
3505 dpavlin 20 case PPC_31_LHAX:
3506     case PPC_31_LHAUX:
3507 dpavlin 14 case PPC_31_LHZX:
3508     case PPC_31_LHZUX:
3509     case PPC_31_LWZX:
3510     case PPC_31_LWZUX:
3511 dpavlin 20 case PPC_31_LHBRX:
3512     case PPC_31_LWBRX:
3513     case PPC_31_LFDX:
3514     case PPC_31_LFSX:
3515 dpavlin 14 case PPC_31_STBX:
3516     case PPC_31_STBUX:
3517     case PPC_31_STHX:
3518     case PPC_31_STHUX:
3519     case PPC_31_STWX:
3520     case PPC_31_STWUX:
3521     case PPC_31_STDX:
3522     case PPC_31_STDUX:
3523 dpavlin 20 case PPC_31_STHBRX:
3524     case PPC_31_STWBRX:
3525     case PPC_31_STFDX:
3526     case PPC_31_STFSX:
3527 dpavlin 14 rs = (iword >> 21) & 31;
3528     ra = (iword >> 16) & 31;
3529     rb = (iword >> 11) & 31;
3530     if (ra == 0)
3531     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3532     else
3533     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3534     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3535     load = 0; zero = 1; size = 0; update = 0;
3536 dpavlin 20 byterev = 0; fp = 0;
3537     ic->f = NULL;
3538 dpavlin 14 switch (xo) {
3539     case PPC_31_LBZX: load = 1; break;
3540 dpavlin 20 case PPC_31_LBZUX: load=update=1; break;
3541     case PPC_31_LHAX: size=1; load=1; zero=0; break;
3542     case PPC_31_LHAUX: size=1; load=update=1; zero=0; break;
3543     case PPC_31_LHZX: size=1; load=1; break;
3544     case PPC_31_LHZUX: size=1; load=update = 1; break;
3545     case PPC_31_LWZX: size=2; load=1; break;
3546     case PPC_31_LWZUX: size=2; load=update = 1; break;
3547     case PPC_31_LHBRX: size=1; load=1; byterev=1;
3548     ic->f = instr(lhbrx); break;
3549     case PPC_31_LWBRX: size=2; load=1; byterev=1;
3550     ic->f = instr(lwbrx); break;
3551     case PPC_31_LFDX: size=3; load=1; fp=1;
3552     ic->f = instr(lfdx); break;
3553     case PPC_31_LFSX: size=2; load=1; fp=1;
3554     ic->f = instr(lfsx); break;
3555 dpavlin 14 case PPC_31_STBX: break;
3556     case PPC_31_STBUX: update = 1; break;
3557 dpavlin 20 case PPC_31_STHX: size=1; break;
3558     case PPC_31_STHUX: size=1; update = 1; break;
3559     case PPC_31_STWX: size=2; break;
3560     case PPC_31_STWUX: size=2; update = 1; break;
3561     case PPC_31_STDX: size=3; break;
3562     case PPC_31_STDUX: size=3; update = 1; break;
3563     case PPC_31_STHBRX:size=1; byterev = 1;
3564     ic->f = instr(sthbrx); break;
3565     case PPC_31_STWBRX:size=2; byterev = 1;
3566     ic->f = instr(stwbrx); break;
3567     case PPC_31_STFDX: size=3; fp=1;
3568     ic->f = instr(stfdx); break;
3569     case PPC_31_STFSX: size=2; fp=1;
3570     ic->f = instr(stfsx); break;
3571 dpavlin 14 }
3572 dpavlin 20 if (fp)
3573     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
3574     else
3575     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3576     if (!byterev && ic->f == NULL) {
3577     ic->f =
3578 dpavlin 14 #ifdef MODE32
3579 dpavlin 20 ppc32_loadstore_indexed
3580 dpavlin 14 #else
3581 dpavlin 20 ppc_loadstore_indexed
3582 dpavlin 14 #endif
3583 dpavlin 20 [size + 4*zero + 8*load + 16*update];
3584     }
3585 dpavlin 14 if (ra == 0 && update) {
3586 dpavlin 42 if (!cpu->translation_readahead)
3587     fatal("TODO: ra=0 && update?\n");
3588 dpavlin 14 goto bad;
3589     }
3590     break;
3591    
3592     case PPC_31_EXTSB:
3593     case PPC_31_EXTSH:
3594     case PPC_31_EXTSW:
3595     case PPC_31_SLW:
3596 dpavlin 24 case PPC_31_SLD:
3597 dpavlin 14 case PPC_31_SRAW:
3598     case PPC_31_SRW:
3599     case PPC_31_AND:
3600     case PPC_31_NAND:
3601     case PPC_31_ANDC:
3602     case PPC_31_NOR:
3603     case PPC_31_OR:
3604     case PPC_31_ORC:
3605     case PPC_31_XOR:
3606 dpavlin 24 case PPC_31_EQV:
3607 dpavlin 14 rs = (iword >> 21) & 31;
3608     ra = (iword >> 16) & 31;
3609     rb = (iword >> 11) & 31;
3610     rc = iword & 1;
3611     rc_f = NULL;
3612     switch (xo) {
3613     case PPC_31_EXTSB:ic->f = instr(extsb);
3614     rc_f = instr(extsb_dot); break;
3615     case PPC_31_EXTSH:ic->f = instr(extsh);
3616     rc_f = instr(extsh_dot); break;
3617     case PPC_31_EXTSW:ic->f = instr(extsw);
3618     rc_f = instr(extsw_dot); break;
3619     case PPC_31_SLW: ic->f = instr(slw);
3620     rc_f = instr(slw_dot); break;
3621 dpavlin 24 case PPC_31_SLD: ic->f = instr(sld);
3622     rc_f = instr(sld_dot); break;
3623 dpavlin 14 case PPC_31_SRAW: ic->f = instr(sraw);
3624     rc_f = instr(sraw_dot); break;
3625     case PPC_31_SRW: ic->f = instr(srw);
3626     rc_f = instr(srw_dot); break;
3627     case PPC_31_AND: ic->f = instr(and);
3628     rc_f = instr(and_dot); break;
3629     case PPC_31_NAND: ic->f = instr(nand);
3630     rc_f = instr(nand_dot); break;
3631     case PPC_31_ANDC: ic->f = instr(andc);
3632     rc_f = instr(andc_dot); break;
3633     case PPC_31_NOR: ic->f = instr(nor);
3634     rc_f = instr(nor_dot); break;
3635 dpavlin 22 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3636     : instr(or);
3637 dpavlin 14 rc_f = instr(or_dot); break;
3638     case PPC_31_ORC: ic->f = instr(orc);
3639     rc_f = instr(orc_dot); break;
3640     case PPC_31_XOR: ic->f = instr(xor);
3641     rc_f = instr(xor_dot); break;
3642 dpavlin 24 case PPC_31_EQV: ic->f = instr(eqv);
3643     rc_f = instr(eqv_dot); break;
3644 dpavlin 14 }
3645     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3646     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3647     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3648     if (rc)
3649     ic->f = rc_f;
3650     break;
3651    
3652     case PPC_31_MULLW:
3653     case PPC_31_MULHW:
3654     case PPC_31_MULHWU:
3655     case PPC_31_DIVW:
3656     case PPC_31_DIVWU:
3657     case PPC_31_ADD:
3658     case PPC_31_ADDC:
3659     case PPC_31_ADDE:
3660     case PPC_31_ADDME:
3661     case PPC_31_ADDZE:
3662     case PPC_31_SUBF:
3663     case PPC_31_SUBFC:
3664     case PPC_31_SUBFE:
3665 dpavlin 20 case PPC_31_SUBFME:
3666 dpavlin 14 case PPC_31_SUBFZE:
3667     rt = (iword >> 21) & 31;
3668     ra = (iword >> 16) & 31;
3669     rb = (iword >> 11) & 31;
3670     oe_bit = (iword >> 10) & 1;
3671     rc = iword & 1;
3672     if (oe_bit) {
3673 dpavlin 42 if (!cpu->translation_readahead)
3674     fatal("oe_bit not yet implemented\n");
3675 dpavlin 14 goto bad;
3676     }
3677     switch (xo) {
3678     case PPC_31_MULLW: ic->f = instr(mullw); break;
3679     case PPC_31_MULHW: ic->f = instr(mulhw); break;
3680     case PPC_31_MULHWU: ic->f = instr(mulhwu); break;
3681     case PPC_31_DIVW: ic->f = instr(divw); n64=1; break;
3682     case PPC_31_DIVWU: ic->f = instr(divwu); n64=1; break;
3683     case PPC_31_ADD: ic->f = instr(add); break;
3684     case PPC_31_ADDC: ic->f = instr(addc); n64=1; break;
3685     case PPC_31_ADDE: ic->f = instr(adde); n64=1; break;
3686     case PPC_31_ADDME: ic->f = instr(addme); n64=1; break;
3687     case PPC_31_ADDZE: ic->f = instr(addze); n64=1; break;
3688     case PPC_31_SUBF: ic->f = instr(subf); break;
3689     case PPC_31_SUBFC: ic->f = instr(subfc); break;
3690     case PPC_31_SUBFE: ic->f = instr(subfe); n64=1; break;
3691 dpavlin 20 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3692 dpavlin 14 case PPC_31_SUBFZE: ic->f = instr(subfze); n64=1;break;
3693     }
3694     if (rc) {
3695     switch (xo) {
3696     case PPC_31_ADD:
3697     ic->f = instr(add_dot); break;
3698     case PPC_31_ADDE:
3699     ic->f = instr(adde_dot); break;
3700     case PPC_31_ADDME:
3701     ic->f = instr(addme_dot); break;
3702     case PPC_31_ADDZE:
3703     ic->f = instr(addze_dot); break;
3704 dpavlin 20 case PPC_31_DIVW:
3705     ic->f = instr(divw_dot); break;
3706     case PPC_31_DIVWU:
3707     ic->f = instr(divwu_dot); break;
3708     case PPC_31_MULLW:
3709     ic->f = instr(mullw_dot); break;
3710     case PPC_31_MULHW:
3711     ic->f = instr(mulhw_dot); break;
3712     case PPC_31_MULHWU:
3713     ic->f = instr(mulhwu_dot); break;
3714 dpavlin 14 case PPC_31_SUBF:
3715     ic->f = instr(subf_dot); break;
3716     case PPC_31_SUBFC:
3717     ic->f = instr(subfc_dot); break;
3718     case PPC_31_SUBFE:
3719     ic->f = instr(subfe_dot); break;
3720 dpavlin 20 case PPC_31_SUBFME:
3721     ic->f = instr(subfme_dot); break;
3722 dpavlin 14 case PPC_31_SUBFZE:
3723     ic->f = instr(subfze_dot); break;
3724 dpavlin 42 default:if (!cpu->translation_readahead)
3725     fatal("RC bit not yet "
3726     "implemented\n");
3727 dpavlin 14 goto bad;
3728     }
3729     }
3730     ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3731     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3732     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3733     if (cpu->cd.ppc.bits == 64 && n64) {
3734 dpavlin 42 if (!cpu->translation_readahead)
3735     fatal("Not yet for 64-bit mode\n");
3736 dpavlin 14 goto bad;
3737     }
3738     break;
3739    
3740 dpavlin 22 case PPC_31_LVX:
3741 dpavlin 24 case PPC_31_LVXL:
3742 dpavlin 22 case PPC_31_STVX:
3743     case PPC_31_STVXL:
3744 dpavlin 24 load = 0;
3745     switch (xo) {
3746     case PPC_31_LVX:
3747     case PPC_31_LVXL:
3748     load = 1; break;
3749     }
3750     rs = (iword >> 21) & 31;
3751     ra = (iword >> 16) & 31;
3752     rb = (iword >> 11) & 31;
3753 dpavlin 34 ic->arg[0] = rs;
3754 dpavlin 24 if (ra == 0)
3755     ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3756     else
3757     ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3758     ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3759 dpavlin 34 ic->f = load? instr(lvx) : instr(stvx);
3760 dpavlin 22 break;
3761    
3762 dpavlin 14 default:goto bad;
3763     }
3764     break;
3765    
3766 dpavlin 20 case PPC_HI6_59:
3767     xo = (iword >> 1) & 1023;
3768 dpavlin 14 rt = (iword >> 21) & 31;
3769     ra = (iword >> 16) & 31;
3770     rb = (iword >> 11) & 31;
3771 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
3772 dpavlin 14 rc = iword & 1;
3773    
3774 dpavlin 20 if (rc) {
3775 dpavlin 42 if (!cpu->translation_readahead)
3776     fatal("Floating point (59) "
3777     "with rc bit! TODO\n");
3778 dpavlin 20 goto bad;
3779     }
3780 dpavlin 14
3781 dpavlin 20 /* NOTE: Some floating-point instructions are selected
3782     using only the lowest 5 bits, not all 10! */
3783     switch (xo & 31) {
3784     case PPC_59_FDIVS:
3785     case PPC_59_FSUBS:
3786     case PPC_59_FADDS:
3787     switch (xo & 31) {
3788     case PPC_59_FDIVS: ic->f = instr(fdivs); break;
3789     case PPC_59_FSUBS: ic->f = instr(fsubs); break;
3790     case PPC_59_FADDS: ic->f = instr(fadds); break;
3791 dpavlin 14 }
3792 dpavlin 20 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3793     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3794     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3795 dpavlin 14 break;
3796 dpavlin 20 case PPC_59_FMULS:
3797     ic->f = instr(fmuls);
3798     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3799     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3800     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3801     break;
3802     default:/* Use all 10 bits of xo: */
3803     switch (xo) {
3804     default:goto bad;
3805     }
3806     }
3807     break;
3808 dpavlin 14
3809 dpavlin 20 case PPC_HI6_63:
3810     xo = (iword >> 1) & 1023;
3811     rt = (iword >> 21) & 31;
3812     ra = (iword >> 16) & 31;
3813     rb = (iword >> 11) & 31;
3814     rs = (iword >> 6) & 31; /* actually frc */
3815     rc = iword & 1;
3816    
3817     if (rc) {
3818 dpavlin 42 if (!cpu->translation_readahead)
3819     fatal("Floating point (63) "
3820     "with rc bit! TODO\n");
3821 dpavlin 20 goto bad;
3822 dpavlin 14 }
3823 dpavlin 20
3824     /* NOTE: Some floating-point instructions are selected
3825     using only the lowest 5 bits, not all 10! */
3826     switch (xo & 31) {
3827     case PPC_63_FDIV:
3828     case PPC_63_FSUB:
3829     case PPC_63_FADD:
3830     switch (xo & 31) {
3831     case PPC_63_FDIV: ic->f = instr(fdiv); break;
3832     case PPC_63_FSUB: ic->f = instr(fsub); break;
3833     case PPC_63_FADD: ic->f = instr(fadd); break;
3834     }
3835     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3836     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3837     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3838     break;
3839     case PPC_63_FMUL:
3840     ic->f = instr(fmul);
3841     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3842     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3843     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3844     break;
3845     case PPC_63_FMSUB:
3846     case PPC_63_FMADD:
3847     switch (xo & 31) {
3848     case PPC_63_FMSUB: ic->f = instr(fmsub); break;
3849     case PPC_63_FMADD: ic->f = instr(fmadd); break;
3850     }
3851     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3852     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3853     ic->arg[2] = iword;
3854     break;
3855     default:/* Use all 10 bits of xo: */
3856     switch (xo) {
3857     case PPC_63_FCMPU:
3858     ic->f = instr(fcmpu);
3859     ic->arg[0] = 28 - 4*(rt >> 2);
3860     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3861     ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3862     break;
3863     case PPC_63_FRSP:
3864     case PPC_63_FCTIWZ:
3865     case PPC_63_FNEG:
3866     case PPC_63_FMR:
3867     switch (xo) {
3868     case PPC_63_FRSP: ic->f = instr(frsp); break;
3869     case PPC_63_FCTIWZ: ic->f = instr(fctiwz);break;
3870     case PPC_63_FNEG: ic->f = instr(fneg); break;
3871     case PPC_63_FMR: ic->f = instr(fmr); break;
3872     }
3873     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3874     ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3875     break;
3876     case PPC_63_MFFS:
3877     ic->f = instr(mffs);
3878     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3879     break;
3880     case PPC_63_MTFSF:
3881     ic->f = instr(mtfsf);
3882     ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3883     ic->arg[1] = 0;
3884     for (bi=7; bi>=0; bi--) {
3885     ic->arg[1] <<= 8;
3886     if (iword & (1 << (17+bi)))
3887     ic->arg[1] |= 0xf;
3888     }
3889     break;
3890     default:goto bad;
3891     }
3892     }
3893 dpavlin 14 break;
3894    
3895     default:goto bad;
3896     }
3897    
3898    
3899     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3900     #include "cpu_dyntrans.c"
3901     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3902     }
3903    

  ViewVC Help
Powered by ViewVC 1.1.26