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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc_instr.c,v 1.77 2007/06/28 13:36:47 debug Exp $
29 *
30 * POWER/PowerPC instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 #include "float_emul.h"
40
41
42 #define DOT0(n) X(n ## _dot) { instr(n)(cpu,ic); \
43 update_cr0(cpu, reg(ic->arg[0])); }
44 #define DOT1(n) X(n ## _dot) { instr(n)(cpu,ic); \
45 update_cr0(cpu, reg(ic->arg[1])); }
46 #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47 update_cr0(cpu, reg(ic->arg[2])); }
48
49 #ifndef CHECK_FOR_FPU_EXCEPTION
50 #define CHECK_FOR_FPU_EXCEPTION { if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) { \
51 /* Synchronize the PC, and cause an FPU exception: */ \
52 uint64_t low_pc = ((size_t)ic - \
53 (size_t)cpu->cd.ppc.cur_ic_page) \
54 / sizeof(struct ppc_instr_call); \
55 cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << \
56 PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << \
57 PPC_INSTR_ALIGNMENT_SHIFT); \
58 ppc_exception(cpu, PPC_EXCEPTION_FPU); \
59 return; } }
60 #endif
61
62
63
64 /*
65 * nop: Do nothing.
66 */
67 X(nop)
68 {
69 }
70
71
72 /*
73 * invalid: To catch bugs.
74 */
75 X(invalid)
76 {
77 fatal("PPC: invalid(): INTERNAL ERROR\n");
78 exit(1);
79 }
80
81
82 /*
83 * addi: Add immediate.
84 *
85 * arg[0] = pointer to source uint64_t
86 * arg[1] = immediate value (int32_t or larger)
87 * arg[2] = pointer to destination uint64_t
88 */
89 X(addi)
90 {
91 reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];
92 }
93 X(li)
94 {
95 reg(ic->arg[2]) = (int32_t)ic->arg[1];
96 }
97 X(li_0)
98 {
99 reg(ic->arg[2]) = 0;
100 }
101
102
103 /*
104 * andi_dot: AND immediate, update CR.
105 *
106 * arg[0] = pointer to source uint64_t
107 * arg[1] = immediate value (uint32_t)
108 * arg[2] = pointer to destination uint64_t
109 */
110 X(andi_dot)
111 {
112 MODE_uint_t tmp = reg(ic->arg[0]) & (uint32_t)ic->arg[1];
113 reg(ic->arg[2]) = tmp;
114 update_cr0(cpu, tmp);
115 }
116
117
118 /*
119 * addic: Add immediate, Carry.
120 *
121 * arg[0] = pointer to source register
122 * arg[1] = immediate value (int32_t or larger)
123 * arg[2] = pointer to destination register
124 */
125 X(addic)
126 {
127 /* TODO/NOTE: Only for 32-bit mode, so far! */
128 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
129 uint64_t tmp2 = tmp;
130 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
131 tmp2 += (uint32_t)ic->arg[1];
132 if ((tmp2 >> 32) != (tmp >> 32))
133 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
134 reg(ic->arg[2]) = (uint32_t)tmp2;
135 }
136
137
138 /*
139 * subfic: Subtract from immediate, Carry.
140 *
141 * arg[0] = pointer to source uint64_t
142 * arg[1] = immediate value (int32_t or larger)
143 * arg[2] = pointer to destination uint64_t
144 */
145 X(subfic)
146 {
147 MODE_uint_t tmp = (int64_t)(int32_t)ic->arg[1];
148 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
149 if (tmp >= reg(ic->arg[0]))
150 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
151 reg(ic->arg[2]) = tmp - reg(ic->arg[0]);
152 }
153
154
155 /*
156 * addic_dot: Add immediate, Carry.
157 *
158 * arg[0] = pointer to source uint64_t
159 * arg[1] = immediate value (int32_t or larger)
160 * arg[2] = pointer to destination uint64_t
161 */
162 X(addic_dot)
163 {
164 /* TODO/NOTE: Only for 32-bit mode, so far! */
165 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
166 uint64_t tmp2 = tmp;
167 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
168 tmp2 += (uint32_t)ic->arg[1];
169 if ((tmp2 >> 32) != (tmp >> 32))
170 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
171 reg(ic->arg[2]) = (uint32_t)tmp2;
172 update_cr0(cpu, (uint32_t)tmp2);
173 }
174
175
176 /*
177 * bclr: Branch Conditional to Link Register
178 *
179 * arg[0] = bo
180 * arg[1] = 31 - bi
181 * arg[2] = bh
182 */
183 X(bclr)
184 {
185 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
186 int ctr_ok, cond_ok;
187 uint64_t old_pc = cpu->pc;
188 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
189 if (!(bo & 4))
190 cpu->cd.ppc.spr[SPR_CTR] --;
191 ctr_ok = (bo >> 2) & 1;
192 tmp = cpu->cd.ppc.spr[SPR_CTR];
193 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
194 cond_ok = (bo >> 4) & 1;
195 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
196 if (ctr_ok && cond_ok) {
197 uint64_t mask_within_page =
198 ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
199 | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
200 cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
201 /* TODO: trace in separate (duplicate) function? */
202 if (cpu->machine->show_trace_tree)
203 cpu_functioncall_trace_return(cpu);
204 if ((old_pc & ~mask_within_page) ==
205 (cpu->pc & ~mask_within_page)) {
206 cpu->cd.ppc.next_ic =
207 cpu->cd.ppc.cur_ic_page +
208 ((cpu->pc & mask_within_page) >>
209 PPC_INSTR_ALIGNMENT_SHIFT);
210 } else {
211 /* Find the new physical page and update pointers: */
212 quick_pc_to_pointers(cpu);
213 }
214 }
215 }
216 X(bclr_20)
217 {
218 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
219 quick_pc_to_pointers(cpu);
220 }
221 X(bclr_l)
222 {
223 uint64_t low_pc, old_pc = cpu->pc;
224 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /* ,bh = ic->arg[2]*/;
225 int ctr_ok, cond_ok;
226 MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
227 if (!(bo & 4))
228 cpu->cd.ppc.spr[SPR_CTR] --;
229 ctr_ok = (bo >> 2) & 1;
230 tmp = cpu->cd.ppc.spr[SPR_CTR];
231 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
232 cond_ok = (bo >> 4) & 1;
233 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
234
235 /* Calculate return PC: */
236 low_pc = ((size_t)ic - (size_t)
237 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
238 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
239 << PPC_INSTR_ALIGNMENT_SHIFT);
240 cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
241
242 if (ctr_ok && cond_ok) {
243 uint64_t mask_within_page =
244 ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
245 | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
246 cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
247 /* TODO: trace in separate (duplicate) function? */
248 if (cpu->machine->show_trace_tree)
249 cpu_functioncall_trace_return(cpu);
250 if (cpu->machine->show_trace_tree)
251 cpu_functioncall_trace(cpu, cpu->pc);
252 if ((old_pc & ~mask_within_page) ==
253 (cpu->pc & ~mask_within_page)) {
254 cpu->cd.ppc.next_ic =
255 cpu->cd.ppc.cur_ic_page +
256 ((cpu->pc & mask_within_page) >>
257 PPC_INSTR_ALIGNMENT_SHIFT);
258 } else {
259 /* Find the new physical page and update pointers: */
260 quick_pc_to_pointers(cpu);
261 }
262 }
263 }
264
265
266 /*
267 * bcctr: Branch Conditional to Count register
268 *
269 * arg[0] = bo
270 * arg[1] = 31 - bi
271 * arg[2] = bh
272 */
273 X(bcctr)
274 {
275 unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
276 uint64_t old_pc = cpu->pc;
277 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
278 int cond_ok = (bo >> 4) & 1;
279 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
280 if (cond_ok) {
281 uint64_t mask_within_page =
282 ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
283 | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
284 cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
285 /* TODO: trace in separate (duplicate) function? */
286 if (cpu->machine->show_trace_tree)
287 cpu_functioncall_trace_return(cpu);
288 if ((old_pc & ~mask_within_page) ==
289 (cpu->pc & ~mask_within_page)) {
290 cpu->cd.ppc.next_ic =
291 cpu->cd.ppc.cur_ic_page +
292 ((cpu->pc & mask_within_page) >>
293 PPC_INSTR_ALIGNMENT_SHIFT);
294 } else {
295 /* Find the new physical page and update pointers: */
296 quick_pc_to_pointers(cpu);
297 }
298 }
299 }
300 X(bcctr_l)
301 {
302 uint64_t low_pc, old_pc = cpu->pc;
303 unsigned int bo = ic->arg[0], bi31m = ic->arg[1] /*,bh = ic->arg[2] */;
304 MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
305 int cond_ok = (bo >> 4) & 1;
306 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
307
308 /* Calculate return PC: */
309 low_pc = ((size_t)ic - (size_t)
310 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
311 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
312 << PPC_INSTR_ALIGNMENT_SHIFT);
313 cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
314
315 if (cond_ok) {
316 uint64_t mask_within_page =
317 ((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT)
318 | ((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
319 cpu->pc = addr & ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
320 /* TODO: trace in separate (duplicate) function? */
321 if (cpu->machine->show_trace_tree)
322 cpu_functioncall_trace(cpu, cpu->pc);
323 if ((old_pc & ~mask_within_page) ==
324 (cpu->pc & ~mask_within_page)) {
325 cpu->cd.ppc.next_ic =
326 cpu->cd.ppc.cur_ic_page +
327 ((cpu->pc & mask_within_page) >>
328 PPC_INSTR_ALIGNMENT_SHIFT);
329 } else {
330 /* Find the new physical page and update pointers: */
331 quick_pc_to_pointers(cpu);
332 }
333 }
334 }
335
336
337 /*
338 * b: Branch (to a different translated page)
339 *
340 * arg[0] = relative offset (as an int32_t) from start of page
341 */
342 X(b)
343 {
344 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
345 cpu->pc += (int32_t)ic->arg[0];
346
347 /* Find the new physical page and update the translation pointers: */
348 quick_pc_to_pointers(cpu);
349 }
350 X(ba)
351 {
352 cpu->pc = (int32_t)ic->arg[0];
353 quick_pc_to_pointers(cpu);
354 }
355
356
357 /*
358 * bc: Branch Conditional (to a different translated page)
359 *
360 * arg[0] = relative offset (as an int32_t) from start of page
361 * arg[1] = bo
362 * arg[2] = 31-bi
363 */
364 X(bc)
365 {
366 MODE_uint_t tmp;
367 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
368 if (!(bo & 4))
369 cpu->cd.ppc.spr[SPR_CTR] --;
370 ctr_ok = (bo >> 2) & 1;
371 tmp = cpu->cd.ppc.spr[SPR_CTR];
372 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
373 cond_ok = (bo >> 4) & 1;
374 cond_ok |= ( ((bo >> 3) & 1) ==
375 ((cpu->cd.ppc.cr >> (bi31m)) & 1) );
376 if (ctr_ok && cond_ok)
377 instr(b)(cpu,ic);
378 }
379 X(bcl)
380 {
381 MODE_uint_t tmp;
382 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
383 int low_pc;
384
385 /* Calculate LR: */
386 low_pc = ((size_t)ic - (size_t)
387 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
388 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
389 << PPC_INSTR_ALIGNMENT_SHIFT);
390 cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
391
392 if (!(bo & 4))
393 cpu->cd.ppc.spr[SPR_CTR] --;
394 ctr_ok = (bo >> 2) & 1;
395 tmp = cpu->cd.ppc.spr[SPR_CTR];
396 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
397 cond_ok = (bo >> 4) & 1;
398 cond_ok |= ( ((bo >> 3) & 1) ==
399 ((cpu->cd.ppc.cr >> bi31m) & 1) );
400 if (ctr_ok && cond_ok)
401 instr(b)(cpu,ic);
402 }
403
404
405 /*
406 * b_samepage: Branch (to within the same translated page)
407 *
408 * arg[0] = pointer to new ppc_instr_call
409 */
410 X(b_samepage)
411 {
412 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
413 }
414
415
416 /*
417 * bc_samepage: Branch Conditional (to within the same page)
418 *
419 * arg[0] = new ic ptr
420 * arg[1] = bo
421 * arg[2] = 31-bi
422 */
423 X(bc_samepage)
424 {
425 MODE_uint_t tmp;
426 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
427 if (!(bo & 4))
428 cpu->cd.ppc.spr[SPR_CTR] --;
429 ctr_ok = (bo >> 2) & 1;
430 tmp = cpu->cd.ppc.spr[SPR_CTR];
431 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
432 cond_ok = (bo >> 4) & 1;
433 cond_ok |= ( ((bo >> 3) & 1) ==
434 ((cpu->cd.ppc.cr >> bi31m) & 1) );
435 if (ctr_ok && cond_ok)
436 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
437 }
438 X(bc_samepage_simple0)
439 {
440 int bi31m = ic->arg[2];
441 if (!((cpu->cd.ppc.cr >> bi31m) & 1))
442 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
443 }
444 X(bc_samepage_simple1)
445 {
446 int bi31m = ic->arg[2];
447 if ((cpu->cd.ppc.cr >> bi31m) & 1)
448 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
449 }
450 X(bcl_samepage)
451 {
452 MODE_uint_t tmp;
453 unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
454 int low_pc;
455
456 /* Calculate LR: */
457 low_pc = ((size_t)ic - (size_t)
458 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
459 cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
460 << PPC_INSTR_ALIGNMENT_SHIFT);
461 cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
462
463 if (!(bo & 4))
464 cpu->cd.ppc.spr[SPR_CTR] --;
465 ctr_ok = (bo >> 2) & 1;
466 tmp = cpu->cd.ppc.spr[SPR_CTR];
467 ctr_ok |= ( (tmp == 0) == ((bo >> 1) & 1) );
468 cond_ok = (bo >> 4) & 1;
469 cond_ok |= ( ((bo >> 3) & 1) ==
470 ((cpu->cd.ppc.cr >> bi31m) & 1) );
471 if (ctr_ok && cond_ok)
472 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
473 }
474
475
476 /*
477 * bl: Branch and Link (to a different translated page)
478 *
479 * arg[0] = relative offset (as an int32_t) from start of page
480 * arg[1] = lr offset (relative to start of current page)
481 */
482 X(bl)
483 {
484 /* Calculate LR and new PC: */
485 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
486 cpu->cd.ppc.spr[SPR_LR] = cpu->pc + ic->arg[1];
487 cpu->pc += (int32_t)ic->arg[0];
488
489 /* Find the new physical page and update the translation pointers: */
490 quick_pc_to_pointers(cpu);
491 }
492 X(bla)
493 {
494 /* Calculate LR: */
495 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
496 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
497
498 cpu->pc = (int32_t)ic->arg[0];
499 quick_pc_to_pointers(cpu);
500 }
501
502
503 /*
504 * bl_trace: Branch and Link (to a different translated page) (with trace)
505 *
506 * arg[0] = relative offset (as an int32_t) from start of page
507 * arg[1] = lr offset (relative to start of current page)
508 */
509 X(bl_trace)
510 {
511 /* Calculate LR: */
512 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
513 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
514
515 /* Calculate new PC from start of page + arg[0] */
516 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
517 cpu->pc += (int32_t)ic->arg[0];
518
519 cpu_functioncall_trace(cpu, cpu->pc);
520
521 /* Find the new physical page and update the translation pointers: */
522 quick_pc_to_pointers(cpu);
523 }
524 X(bla_trace)
525 {
526 /* Calculate LR: */
527 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
528 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
529
530 cpu->pc = (int32_t)ic->arg[0];
531 cpu_functioncall_trace(cpu, cpu->pc);
532 quick_pc_to_pointers(cpu);
533 }
534
535
536 /*
537 * bl_samepage: Branch and Link (to within the same translated page)
538 *
539 * arg[0] = pointer to new ppc_instr_call
540 * arg[1] = lr offset (relative to start of current page)
541 */
542 X(bl_samepage)
543 {
544 /* Calculate LR: */
545 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
546 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
547
548 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
549 }
550
551
552 /*
553 * bl_samepage_trace: Branch and Link (to within the same translated page)
554 *
555 * arg[0] = pointer to new ppc_instr_call
556 * arg[1] = lr offset (relative to start of current page)
557 */
558 X(bl_samepage_trace)
559 {
560 uint32_t low_pc;
561
562 /* Calculate LR: */
563 cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
564 << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
565
566 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
567
568 /* Calculate new PC (for the trace) */
569 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
570 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
571 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
572 cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
573 cpu_functioncall_trace(cpu, cpu->pc);
574 }
575
576
577 /*
578 * cntlzw: Count leading zeroes (32-bit word).
579 *
580 * arg[0] = ptr to rs
581 * arg[1] = ptr to ra
582 */
583 X(cntlzw)
584 {
585 uint32_t tmp = reg(ic->arg[0]);
586 int i;
587 for (i=0; i<32; i++) {
588 if (tmp & 0x80000000)
589 break;
590 tmp <<= 1;
591 }
592 reg(ic->arg[1]) = i;
593 }
594
595
596 /*
597 * cmpd: Compare Doubleword
598 *
599 * arg[0] = ptr to ra
600 * arg[1] = ptr to rb
601 * arg[2] = 28 - 4*bf
602 */
603 X(cmpd)
604 {
605 int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
606 int bf_shift = ic->arg[2], c;
607 if (tmp < tmp2)
608 c = 8;
609 else if (tmp > tmp2)
610 c = 4;
611 else
612 c = 2;
613 /* SO bit, copied from XER */
614 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
615 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
616 cpu->cd.ppc.cr |= (c << bf_shift);
617 }
618
619
620 /*
621 * cmpld: Compare Doubleword, unsigned
622 *
623 * arg[0] = ptr to ra
624 * arg[1] = ptr to rb
625 * arg[2] = 28 - 4*bf
626 */
627 X(cmpld)
628 {
629 uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
630 int bf_shift = ic->arg[2], c;
631 if (tmp < tmp2)
632 c = 8;
633 else if (tmp > tmp2)
634 c = 4;
635 else
636 c = 2;
637 /* SO bit, copied from XER */
638 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
639 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
640 cpu->cd.ppc.cr |= (c << bf_shift);
641 }
642
643
644 /*
645 * cmpdi: Compare Doubleword immediate
646 *
647 * arg[0] = ptr to ra
648 * arg[1] = int32_t imm
649 * arg[2] = 28 - 4*bf
650 */
651 X(cmpdi)
652 {
653 int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
654 int bf_shift = ic->arg[2], c;
655 if (tmp < imm)
656 c = 8;
657 else if (tmp > imm)
658 c = 4;
659 else
660 c = 2;
661 /* SO bit, copied from XER */
662 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
663 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
664 cpu->cd.ppc.cr |= (c << bf_shift);
665 }
666
667
668 /*
669 * cmpldi: Compare Doubleword immediate, logical
670 *
671 * arg[0] = ptr to ra
672 * arg[1] = int32_t imm
673 * arg[2] = 28 - 4*bf
674 */
675 X(cmpldi)
676 {
677 uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
678 int bf_shift = ic->arg[2], c;
679 if (tmp < imm)
680 c = 8;
681 else if (tmp > imm)
682 c = 4;
683 else
684 c = 2;
685 /* SO bit, copied from XER */
686 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
687 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
688 cpu->cd.ppc.cr |= (c << bf_shift);
689 }
690
691
692 /*
693 * cmpw: Compare Word
694 *
695 * arg[0] = ptr to ra
696 * arg[1] = ptr to rb
697 * arg[2] = 28 - 4*bf
698 */
699 X(cmpw)
700 {
701 int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
702 int bf_shift = ic->arg[2], c;
703 if (tmp < tmp2)
704 c = 8;
705 else if (tmp > tmp2)
706 c = 4;
707 else
708 c = 2;
709 /* SO bit, copied from XER */
710 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
711 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
712 cpu->cd.ppc.cr |= (c << bf_shift);
713 }
714 X(cmpw_cr0)
715 {
716 /* arg[2] is assumed to be 28 */
717 int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
718 cpu->cd.ppc.cr &= ~(0xf0000000);
719 if (tmp < tmp2)
720 cpu->cd.ppc.cr |= 0x80000000;
721 else if (tmp > tmp2)
722 cpu->cd.ppc.cr |= 0x40000000;
723 else
724 cpu->cd.ppc.cr |= 0x20000000;
725 cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
726 }
727
728
729 /*
730 * cmplw: Compare Word, unsigned
731 *
732 * arg[0] = ptr to ra
733 * arg[1] = ptr to rb
734 * arg[2] = 28 - 4*bf
735 */
736 X(cmplw)
737 {
738 uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
739 int bf_shift = ic->arg[2], c;
740 if (tmp < tmp2)
741 c = 8;
742 else if (tmp > tmp2)
743 c = 4;
744 else
745 c = 2;
746 /* SO bit, copied from XER */
747 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
748 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
749 cpu->cd.ppc.cr |= (c << bf_shift);
750 }
751
752
753 /*
754 * cmpwi: Compare Word immediate
755 *
756 * arg[0] = ptr to ra
757 * arg[1] = int32_t imm
758 * arg[2] = 28 - 4*bf
759 */
760 X(cmpwi)
761 {
762 int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
763 int bf_shift = ic->arg[2], c;
764 if (tmp < imm)
765 c = 8;
766 else if (tmp > imm)
767 c = 4;
768 else
769 c = 2;
770 /* SO bit, copied from XER */
771 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
772 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
773 cpu->cd.ppc.cr |= (c << bf_shift);
774 }
775 X(cmpwi_cr0)
776 {
777 /* arg[2] is assumed to be 28 */
778 int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
779 cpu->cd.ppc.cr &= ~(0xf0000000);
780 if (tmp < imm)
781 cpu->cd.ppc.cr |= 0x80000000;
782 else if (tmp > imm)
783 cpu->cd.ppc.cr |= 0x40000000;
784 else
785 cpu->cd.ppc.cr |= 0x20000000;
786 cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
787 }
788
789
790 /*
791 * cmplwi: Compare Word immediate, logical
792 *
793 * arg[0] = ptr to ra
794 * arg[1] = int32_t imm
795 * arg[2] = 28 - 4*bf
796 */
797 X(cmplwi)
798 {
799 uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
800 int bf_shift = ic->arg[2], c;
801 if (tmp < imm)
802 c = 8;
803 else if (tmp > imm)
804 c = 4;
805 else
806 c = 2;
807 /* SO bit, copied from XER */
808 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
809 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
810 cpu->cd.ppc.cr |= (c << bf_shift);
811 }
812
813
814 /*
815 * dcbz: Data-Cache Block Zero
816 *
817 * arg[0] = ptr to ra (or zero)
818 * arg[1] = ptr to rb
819 */
820 X(dcbz)
821 {
822 MODE_uint_t addr = reg(ic->arg[0]) + reg(ic->arg[1]);
823 unsigned char cacheline[128];
824 size_t cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;
825 size_t cleared = 0;
826
827 /* Synchronize the PC first: */
828 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
829
830 addr &= ~(cacheline_size - 1);
831 memset(cacheline, 0, sizeof(cacheline));
832
833 while (cleared < cacheline_size) {
834 int to_clear = cacheline_size < sizeof(cacheline)?
835 cacheline_size : sizeof(cacheline);
836 #ifdef MODE32
837 unsigned char *page = cpu->cd.ppc.host_store[addr >> 12];
838 if (page != NULL) {
839 memset(page + (addr & 0xfff), 0, to_clear);
840 } else
841 #endif
842 if (cpu->memory_rw(cpu, cpu->mem, addr, cacheline,
843 to_clear, MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
844 /* exception */
845 return;
846 }
847
848 cleared += to_clear;
849 addr += to_clear;
850 }
851 }
852
853
854 /*
855 * mtfsf: Copy FPR into the FPSCR.
856 *
857 * arg[0] = ptr to frb
858 * arg[1] = mask
859 */
860 X(mtfsf)
861 {
862 CHECK_FOR_FPU_EXCEPTION;
863 cpu->cd.ppc.fpscr &= ~ic->arg[1];
864 cpu->cd.ppc.fpscr |= (ic->arg[1] & (*(uint64_t *)ic->arg[0]));
865 }
866
867
868 /*
869 * mffs: Copy FPSCR into a FPR.
870 *
871 * arg[0] = ptr to frt
872 */
873 X(mffs)
874 {
875 CHECK_FOR_FPU_EXCEPTION;
876 (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;
877 }
878
879
880 /*
881 * fmr: Floating-point Move
882 *
883 * arg[0] = ptr to frb
884 * arg[1] = ptr to frt
885 */
886 X(fmr)
887 {
888 /*
889 * This works like a normal register to register copy, but
890 * a) it can cause an FPU exception, and b) the move is always
891 * 64-bit, even when running in 32-bit mode.
892 */
893 CHECK_FOR_FPU_EXCEPTION;
894 *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
895 }
896
897
898 /*
899 * fneg: Floating-point Negate
900 *
901 * arg[0] = ptr to frb
902 * arg[1] = ptr to frt
903 */
904 X(fneg)
905 {
906 uint64_t v;
907 CHECK_FOR_FPU_EXCEPTION;
908 v = *(uint64_t *)ic->arg[0];
909 *(uint64_t *)ic->arg[1] = v ^ 0x8000000000000000ULL;
910 }
911
912
913 /*
914 * fcmpu: Floating-point Compare Unordered
915 *
916 * arg[0] = 28 - 4*bf (bitfield shift)
917 * arg[1] = ptr to fra
918 * arg[2] = ptr to frb
919 */
920 X(fcmpu)
921 {
922 struct ieee_float_value fra, frb;
923 int bf_shift = ic->arg[0], c = 0;
924
925 CHECK_FOR_FPU_EXCEPTION;
926
927 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
928 ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frb, IEEE_FMT_D);
929 if (fra.nan | frb.nan) {
930 c = 1;
931 } else {
932 if (fra.f < frb.f)
933 c = 8;
934 else if (fra.f > frb.f)
935 c = 4;
936 else
937 c = 2;
938 }
939 /* TODO: Signaling vs Quiet NaN */
940 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
941 cpu->cd.ppc.cr |= ((c&0xe) << bf_shift);
942 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
943 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
944 }
945
946
947 /*
948 * frsp: Floating-point Round to Single Precision
949 *
950 * arg[0] = ptr to frb
951 * arg[1] = ptr to frt
952 */
953 X(frsp)
954 {
955 struct ieee_float_value frb;
956 float fl = 0.0;
957 int c = 0;
958
959 CHECK_FOR_FPU_EXCEPTION;
960
961 ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
962 if (frb.nan) {
963 c = 1;
964 } else {
965 fl = frb.f;
966 if (fl < 0.0)
967 c = 8;
968 else if (fl > 0.0)
969 c = 4;
970 else
971 c = 2;
972 }
973 /* TODO: Signaling vs Quiet NaN */
974 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
975 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
976 (*(uint64_t *)ic->arg[1]) =
977 ieee_store_float_value(fl, IEEE_FMT_D, frb.nan);
978 }
979
980
981 /*
982 * fctiwz: Floating-point Convert to Integer Word, Round to Zero
983 *
984 * arg[0] = ptr to frb
985 * arg[1] = ptr to frt
986 */
987 X(fctiwz)
988 {
989 struct ieee_float_value frb;
990 uint32_t res = 0;
991
992 CHECK_FOR_FPU_EXCEPTION;
993
994 ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
995 if (!frb.nan) {
996 if (frb.f >= 2147483647.0)
997 res = 0x7fffffff;
998 else if (frb.f <= -2147483648.0)
999 res = 0x80000000;
1000 else
1001 res = frb.f;
1002 }
1003 *(uint64_t *)ic->arg[1] = (uint32_t)res;
1004 }
1005
1006
1007 /*
1008 * fmul: Floating-point Multiply
1009 *
1010 * arg[0] = ptr to frt
1011 * arg[1] = ptr to fra
1012 * arg[2] = ptr to frc
1013 */
1014 X(fmul)
1015 {
1016 struct ieee_float_value fra;
1017 struct ieee_float_value frc;
1018 double result = 0.0;
1019 int c, nan = 0;
1020
1021 CHECK_FOR_FPU_EXCEPTION;
1022
1023 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1024 ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frc, IEEE_FMT_D);
1025 if (fra.nan || frc.nan)
1026 nan = 1;
1027 else
1028 result = fra.f * frc.f;
1029 if (nan)
1030 c = 1;
1031 else {
1032 if (result < 0.0)
1033 c = 8;
1034 else if (result > 0.0)
1035 c = 4;
1036 else
1037 c = 2;
1038 }
1039 /* TODO: Signaling vs Quiet NaN */
1040 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1041 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1042
1043 (*(uint64_t *)ic->arg[0]) =
1044 ieee_store_float_value(result, IEEE_FMT_D, nan);
1045 }
1046 X(fmuls)
1047 {
1048 /* TODO */
1049 instr(fmul)(cpu, ic);
1050 }
1051
1052
1053 /*
1054 * fmadd: Floating-point Multiply and Add
1055 *
1056 * arg[0] = ptr to frt
1057 * arg[1] = ptr to fra
1058 * arg[2] = copy of the instruction word
1059 */
1060 X(fmadd)
1061 {
1062 uint32_t iw = ic->arg[2];
1063 int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1064 struct ieee_float_value fra;
1065 struct ieee_float_value frb;
1066 struct ieee_float_value frc;
1067 double result = 0.0;
1068 int nan = 0, cc;
1069
1070 CHECK_FOR_FPU_EXCEPTION;
1071
1072 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1073 ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1074 ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1075 if (fra.nan || frb.nan || frc.nan)
1076 nan = 1;
1077 else
1078 result = fra.f * frc.f + frb.f;
1079 if (nan)
1080 cc = 1;
1081 else {
1082 if (result < 0.0)
1083 cc = 8;
1084 else if (result > 0.0)
1085 cc = 4;
1086 else
1087 cc = 2;
1088 }
1089 /* TODO: Signaling vs Quiet NaN */
1090 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1091 cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1092
1093 (*(uint64_t *)ic->arg[0]) =
1094 ieee_store_float_value(result, IEEE_FMT_D, nan);
1095 }
1096
1097
1098 /*
1099 * fmsub: Floating-point Multiply and Sub
1100 *
1101 * arg[0] = ptr to frt
1102 * arg[1] = ptr to fra
1103 * arg[2] = copy of the instruction word
1104 */
1105 X(fmsub)
1106 {
1107 uint32_t iw = ic->arg[2];
1108 int b = (iw >> 11) & 31, c = (iw >> 6) & 31;
1109 struct ieee_float_value fra;
1110 struct ieee_float_value frb;
1111 struct ieee_float_value frc;
1112 double result = 0.0;
1113 int nan = 0, cc;
1114
1115 CHECK_FOR_FPU_EXCEPTION;
1116
1117 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1118 ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
1119 ieee_interpret_float_value(cpu->cd.ppc.fpr[c], &frc, IEEE_FMT_D);
1120 if (fra.nan || frb.nan || frc.nan)
1121 nan = 1;
1122 else
1123 result = fra.f * frc.f - frb.f;
1124 if (nan)
1125 cc = 1;
1126 else {
1127 if (result < 0.0)
1128 cc = 8;
1129 else if (result > 0.0)
1130 cc = 4;
1131 else
1132 cc = 2;
1133 }
1134 /* TODO: Signaling vs Quiet NaN */
1135 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1136 cpu->cd.ppc.fpscr |= (cc << PPC_FPSCR_FPCC_SHIFT);
1137
1138 (*(uint64_t *)ic->arg[0]) =
1139 ieee_store_float_value(result, IEEE_FMT_D, nan);
1140 }
1141
1142
1143 /*
1144 * fadd, fsub, fdiv: Various Floating-point operationgs
1145 *
1146 * arg[0] = ptr to fra
1147 * arg[1] = ptr to frb
1148 * arg[2] = ptr to frt
1149 */
1150 X(fadd)
1151 {
1152 struct ieee_float_value fra;
1153 struct ieee_float_value frb;
1154 double result = 0.0;
1155 int nan = 0, c;
1156
1157 CHECK_FOR_FPU_EXCEPTION;
1158
1159 ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1160 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1161 if (fra.nan || frb.nan)
1162 nan = 1;
1163 else
1164 result = fra.f + frb.f;
1165 if (nan)
1166 c = 1;
1167 else {
1168 if (result < 0.0)
1169 c = 8;
1170 else if (result > 0.0)
1171 c = 4;
1172 else
1173 c = 2;
1174 }
1175 /* TODO: Signaling vs Quiet NaN */
1176 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1177 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1178
1179 (*(uint64_t *)ic->arg[2]) =
1180 ieee_store_float_value(result, IEEE_FMT_D, nan);
1181 }
1182 X(fadds)
1183 {
1184 /* TODO */
1185 instr(fadd)(cpu, ic);
1186 }
1187 X(fsub)
1188 {
1189 struct ieee_float_value fra;
1190 struct ieee_float_value frb;
1191 double result = 0.0;
1192 int nan = 0, c;
1193
1194 CHECK_FOR_FPU_EXCEPTION;
1195
1196 ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1197 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1198 if (fra.nan || frb.nan)
1199 nan = 1;
1200 else
1201 result = fra.f - frb.f;
1202 if (nan)
1203 c = 1;
1204 else {
1205 if (result < 0.0)
1206 c = 8;
1207 else if (result > 0.0)
1208 c = 4;
1209 else
1210 c = 2;
1211 }
1212 /* TODO: Signaling vs Quiet NaN */
1213 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1214 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1215
1216 (*(uint64_t *)ic->arg[2]) =
1217 ieee_store_float_value(result, IEEE_FMT_D, nan);
1218 }
1219 X(fsubs)
1220 {
1221 /* TODO */
1222 instr(fsub)(cpu, ic);
1223 }
1224 X(fdiv)
1225 {
1226 struct ieee_float_value fra;
1227 struct ieee_float_value frb;
1228 double result = 0.0;
1229 int nan = 0, c;
1230
1231 CHECK_FOR_FPU_EXCEPTION;
1232
1233 ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1234 ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
1235 if (fra.nan || frb.nan || frb.f == 0)
1236 nan = 1;
1237 else
1238 result = fra.f / frb.f;
1239 if (nan)
1240 c = 1;
1241 else {
1242 if (result < 0.0)
1243 c = 8;
1244 else if (result > 0.0)
1245 c = 4;
1246 else
1247 c = 2;
1248 }
1249 /* TODO: Signaling vs Quiet NaN */
1250 cpu->cd.ppc.fpscr &= ~(PPC_FPSCR_FPCC | PPC_FPSCR_VXNAN);
1251 cpu->cd.ppc.fpscr |= (c << PPC_FPSCR_FPCC_SHIFT);
1252
1253 (*(uint64_t *)ic->arg[2]) =
1254 ieee_store_float_value(result, IEEE_FMT_D, nan);
1255 }
1256 X(fdivs)
1257 {
1258 /* TODO */
1259 instr(fdiv)(cpu, ic);
1260 }
1261
1262
1263 /*
1264 * llsc: Load-linked and store conditional
1265 *
1266 * arg[0] = copy of the instruction word.
1267 */
1268 X(llsc)
1269 {
1270 int iw = ic->arg[0], len = 4, load = 0, xo = (iw >> 1) & 1023;
1271 int i, rc = iw & 1, rt, ra, rb;
1272 uint64_t addr = 0, value;
1273 unsigned char d[8];
1274
1275 switch (xo) {
1276 case PPC_31_LDARX:
1277 len = 8;
1278 case PPC_31_LWARX:
1279 load = 1;
1280 break;
1281 case PPC_31_STDCX_DOT:
1282 len = 8;
1283 case PPC_31_STWCX_DOT:
1284 break;
1285 }
1286
1287 rt = (iw >> 21) & 31;
1288 ra = (iw >> 16) & 31;
1289 rb = (iw >> 11) & 31;
1290
1291 if (ra != 0)
1292 addr = cpu->cd.ppc.gpr[ra];
1293 addr += cpu->cd.ppc.gpr[rb];
1294
1295 if (load) {
1296 if (rc) {
1297 fatal("ll: rc-bit set?\n");
1298 exit(1);
1299 }
1300 if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1301 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1302 fatal("ll: error: TODO\n");
1303 exit(1);
1304 }
1305
1306 value = 0;
1307 for (i=0; i<len; i++) {
1308 value <<= 8;
1309 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1310 value |= d[i];
1311 else
1312 value |= d[len - 1 - i];
1313 }
1314
1315 cpu->cd.ppc.gpr[rt] = value;
1316 cpu->cd.ppc.ll_addr = addr;
1317 cpu->cd.ppc.ll_bit = 1;
1318 } else {
1319 uint32_t old_so = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_SO;
1320 if (!rc) {
1321 fatal("sc: rc-bit not set?\n");
1322 exit(1);
1323 }
1324
1325 value = cpu->cd.ppc.gpr[rt];
1326
1327 /* "If the store is performed, bits 0-2 of Condition
1328 Register Field 0 are set to 0b001, otherwise, they are
1329 set to 0b000. The SO bit of the XER is copied to to bit
1330 4 of Condition Register Field 0. */
1331 if (!cpu->cd.ppc.ll_bit || cpu->cd.ppc.ll_addr != addr) {
1332 cpu->cd.ppc.cr &= 0x0fffffff;
1333 if (old_so)
1334 cpu->cd.ppc.cr |= 0x10000000;
1335 cpu->cd.ppc.ll_bit = 0;
1336 return;
1337 }
1338
1339 for (i=0; i<len; i++) {
1340 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1341 d[len - 1 - i] = value >> (8*i);
1342 else
1343 d[i] = value >> (8*i);
1344 }
1345
1346 if (cpu->memory_rw(cpu, cpu->mem, addr, d, len,
1347 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1348 fatal("sc: error: TODO\n");
1349 exit(1);
1350 }
1351
1352 cpu->cd.ppc.cr &= 0x0fffffff;
1353 cpu->cd.ppc.cr |= 0x20000000; /* success! */
1354 if (old_so)
1355 cpu->cd.ppc.cr |= 0x10000000;
1356
1357 /* Clear _all_ CPUs' ll_bits: */
1358 for (i=0; i<cpu->machine->ncpus; i++)
1359 cpu->machine->cpus[i]->cd.ppc.ll_bit = 0;
1360 }
1361 }
1362
1363
1364 /*
1365 * mtsr, mtsrin: Move To Segment Register [Indirect]
1366 *
1367 * arg[0] = sr number, or for indirect mode: ptr to rb
1368 * arg[1] = ptr to rt
1369 *
1370 * TODO: These only work for 32-bit mode!
1371 */
1372 X(mtsr)
1373 {
1374 int sr_num = ic->arg[0];
1375 uint32_t old = cpu->cd.ppc.sr[sr_num];
1376 cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1377
1378 if (cpu->cd.ppc.sr[sr_num] != old)
1379 cpu->invalidate_translation_caches(cpu, ic->arg[0] << 28,
1380 INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1381 }
1382 X(mtsrin)
1383 {
1384 int sr_num = reg(ic->arg[0]) >> 28;
1385 uint32_t old = cpu->cd.ppc.sr[sr_num];
1386 cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1387
1388 if (cpu->cd.ppc.sr[sr_num] != old)
1389 cpu->invalidate_translation_caches(cpu, sr_num << 28,
1390 INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1391 }
1392
1393
1394 /*
1395 * mfsrin, mtsrin: Move From/To Segment Register Indirect
1396 *
1397 * arg[0] = sr number, or for indirect mode: ptr to rb
1398 * arg[1] = ptr to rt
1399 */
1400 X(mfsr)
1401 {
1402 /* TODO: This only works for 32-bit mode */
1403 reg(ic->arg[1]) = cpu->cd.ppc.sr[ic->arg[0]];
1404 }
1405 X(mfsrin)
1406 {
1407 /* TODO: This only works for 32-bit mode */
1408 uint32_t sr_num = reg(ic->arg[0]) >> 28;
1409 reg(ic->arg[1]) = cpu->cd.ppc.sr[sr_num];
1410 }
1411
1412
1413 /*
1414 * rldicl:
1415 *
1416 * arg[0] = copy of the instruction word
1417 */
1418 X(rldicl)
1419 {
1420 int rs = (ic->arg[0] >> 21) & 31;
1421 int ra = (ic->arg[0] >> 16) & 31;
1422 int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4);
1423 int mb = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20);
1424 int rc = ic->arg[0] & 1;
1425 uint64_t tmp = cpu->cd.ppc.gpr[rs], tmp2;
1426 /* TODO: Fix this, its performance is awful: */
1427 while (sh-- != 0) {
1428 int b = (tmp >> 63) & 1;
1429 tmp = (tmp << 1) | b;
1430 }
1431 tmp2 = 0;
1432 while (mb <= 63) {
1433 tmp |= ((uint64_t)1 << (63-mb));
1434 mb ++;
1435 }
1436 cpu->cd.ppc.gpr[ra] = tmp & tmp2;
1437 if (rc)
1438 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1439 }
1440
1441
1442 /*
1443 * rldicr:
1444 *
1445 * arg[0] = copy of the instruction word
1446 */
1447 X(rldicr)
1448 {
1449 int rs = (ic->arg[0] >> 21) & 31;
1450 int ra = (ic->arg[0] >> 16) & 31;
1451 int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4);
1452 int me = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20);
1453 int rc = ic->arg[0] & 1;
1454 uint64_t tmp = cpu->cd.ppc.gpr[rs];
1455 /* TODO: Fix this, its performance is awful: */
1456 while (sh-- != 0) {
1457 int b = (tmp >> 63) & 1;
1458 tmp = (tmp << 1) | b;
1459 }
1460 while (me++ < 63)
1461 tmp &= ~((uint64_t)1 << (63-me));
1462 cpu->cd.ppc.gpr[ra] = tmp;
1463 if (rc)
1464 update_cr0(cpu, tmp);
1465 }
1466
1467
1468 /*
1469 * rldimi:
1470 *
1471 * arg[0] = copy of the instruction word
1472 */
1473 X(rldimi)
1474 {
1475 uint32_t iw = ic->arg[0];
1476 int rs = (iw >> 21) & 31, ra = (iw >> 16) & 31;
1477 int sh = ((iw >> 11) & 31) | ((iw & 2) << 4);
1478 int mb = ((iw >> 6) & 31) | (iw & 0x20);
1479 int rc = ic->arg[0] & 1;
1480 int m;
1481 uint64_t tmp, s = cpu->cd.ppc.gpr[rs];
1482 /* TODO: Fix this, its performance is awful: */
1483 while (sh-- != 0) {
1484 int b = (s >> 63) & 1;
1485 s = (s << 1) | b;
1486 }
1487 m = mb; tmp = 0;
1488 do {
1489 tmp |= ((uint64_t)1 << (63-m));
1490 m ++;
1491 } while (m != 63 - sh);
1492 cpu->cd.ppc.gpr[ra] &= ~tmp;
1493 cpu->cd.ppc.gpr[ra] |= (tmp & s);
1494 if (rc)
1495 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1496 }
1497
1498
1499 /*
1500 * rlwnm:
1501 *
1502 * arg[0] = ptr to ra
1503 * arg[1] = mask
1504 * arg[2] = copy of the instruction word
1505 */
1506 X(rlwnm)
1507 {
1508 uint32_t tmp, iword = ic->arg[2];
1509 int rs = (iword >> 21) & 31;
1510 int rb = (iword >> 11) & 31;
1511 int sh = cpu->cd.ppc.gpr[rb] & 0x1f;
1512 tmp = (uint32_t)cpu->cd.ppc.gpr[rs];
1513 tmp = (tmp << sh) | (tmp >> (32-sh));
1514 tmp &= (uint32_t)ic->arg[1];
1515 reg(ic->arg[0]) = tmp;
1516 }
1517 DOT0(rlwnm)
1518
1519
1520 /*
1521 * rlwinm:
1522 *
1523 * arg[0] = ptr to ra
1524 * arg[1] = mask
1525 * arg[2] = copy of the instruction word
1526 */
1527 X(rlwinm)
1528 {
1529 uint32_t tmp, iword = ic->arg[2];
1530 int rs = (iword >> 21) & 31;
1531 int sh = (iword >> 11) & 31;
1532 tmp = (uint32_t)cpu->cd.ppc.gpr[rs];
1533 tmp = (tmp << sh) | (tmp >> (32-sh));
1534 tmp &= (uint32_t)ic->arg[1];
1535 reg(ic->arg[0]) = tmp;
1536 }
1537 DOT0(rlwinm)
1538
1539
1540 /*
1541 * rlwimi:
1542 *
1543 * arg[0] = ptr to rs
1544 * arg[1] = ptr to ra
1545 * arg[2] = copy of the instruction word
1546 */
1547 X(rlwimi)
1548 {
1549 MODE_uint_t tmp = reg(ic->arg[0]), ra = reg(ic->arg[1]);
1550 uint32_t iword = ic->arg[2];
1551 int sh = (iword >> 11) & 31;
1552 int mb = (iword >> 6) & 31;
1553 int me = (iword >> 1) & 31;
1554 int rc = iword & 1;
1555
1556 tmp = (tmp << sh) | (tmp >> (32-sh));
1557
1558 for (;;) {
1559 uint64_t mask;
1560 mask = (uint64_t)1 << (31-mb);
1561 ra &= ~mask;
1562 ra |= (tmp & mask);
1563 if (mb == me)
1564 break;
1565 mb ++;
1566 if (mb == 32)
1567 mb = 0;
1568 }
1569 reg(ic->arg[1]) = ra;
1570 if (rc)
1571 update_cr0(cpu, ra);
1572 }
1573
1574
1575 /*
1576 * srawi:
1577 *
1578 * arg[0] = ptr to rs
1579 * arg[1] = ptr to ra
1580 * arg[2] = sh (shift amount)
1581 */
1582 X(srawi)
1583 {
1584 uint32_t tmp = reg(ic->arg[0]);
1585 int i = 0, j = 0, sh = ic->arg[2];
1586
1587 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
1588 if (tmp & 0x80000000)
1589 i = 1;
1590 while (sh-- > 0) {
1591 if (tmp & 1)
1592 j ++;
1593 tmp >>= 1;
1594 if (tmp & 0x40000000)
1595 tmp |= 0x80000000;
1596 }
1597 if (i && j>0)
1598 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
1599 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
1600 }
1601 DOT1(srawi)
1602
1603
1604 /*
1605 * mcrf: Move inside condition register
1606 *
1607 * arg[0] = 28-4*bf, arg[1] = 28-4*bfa
1608 */
1609 X(mcrf)
1610 {
1611 int bf_shift = ic->arg[0], bfa_shift = ic->arg[1];
1612 uint32_t tmp = (cpu->cd.ppc.cr >> bfa_shift) & 0xf;
1613 cpu->cd.ppc.cr &= ~(0xf << bf_shift);
1614 cpu->cd.ppc.cr |= (tmp << bf_shift);
1615 }
1616
1617
1618 /*
1619 * crand, crxor etc: Condition Register operations
1620 *
1621 * arg[0] = copy of the instruction word
1622 */
1623 X(crand) {
1624 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1625 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1626 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1627 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1628 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1629 if (ba & bb)
1630 cpu->cd.ppc.cr |= (1 << (31-bt));
1631 }
1632 X(crandc) {
1633 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1634 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1635 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1636 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1637 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1638 if (!(ba & bb))
1639 cpu->cd.ppc.cr |= (1 << (31-bt));
1640 }
1641 X(creqv) {
1642 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1643 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1644 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1645 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1646 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1647 if (!(ba ^ bb))
1648 cpu->cd.ppc.cr |= (1 << (31-bt));
1649 }
1650 X(cror) {
1651 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1652 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1653 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1654 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1655 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1656 if (ba | bb)
1657 cpu->cd.ppc.cr |= (1 << (31-bt));
1658 }
1659 X(crorc) {
1660 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1661 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1662 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1663 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1664 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1665 if (!(ba | bb))
1666 cpu->cd.ppc.cr |= (1 << (31-bt));
1667 }
1668 X(crnor) {
1669 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1670 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1671 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1672 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1673 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1674 if (!(ba | bb))
1675 cpu->cd.ppc.cr |= (1 << (31-bt));
1676 }
1677 X(crxor) {
1678 uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1679 int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1680 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1681 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1682 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1683 if (ba ^ bb)
1684 cpu->cd.ppc.cr |= (1 << (31-bt));
1685 }
1686
1687
1688 /*
1689 * mfspr: Move from SPR
1690 *
1691 * arg[0] = pointer to destination register
1692 * arg[1] = pointer to source SPR
1693 */
1694 X(mfspr) {
1695 /* TODO: Check permission */
1696 reg(ic->arg[0]) = reg(ic->arg[1]);
1697 }
1698 X(mfspr_pmc1) {
1699 /*
1700 * TODO: This is a temporary hack to make NetBSD/ppc detect
1701 * a CPU of the correct (emulated) speed.
1702 */
1703 reg(ic->arg[0]) = cpu->machine->emulated_hz / 10;
1704 }
1705 X(mftb) {
1706 /* NOTE/TODO: This increments the time base (slowly) if it
1707 is being polled. */
1708 if (++cpu->cd.ppc.spr[SPR_TBL] == 0)
1709 cpu->cd.ppc.spr[SPR_TBU] ++;
1710 reg(ic->arg[0]) = cpu->cd.ppc.spr[SPR_TBL];
1711 }
1712 X(mftbu) {
1713 reg(ic->arg[0]) = cpu->cd.ppc.spr[SPR_TBU];
1714 }
1715
1716
1717 /*
1718 * mtspr: Move to SPR.
1719 *
1720 * arg[0] = pointer to source register
1721 * arg[1] = pointer to the SPR
1722 */
1723 X(mtspr) {
1724 /* TODO: Check permission */
1725 reg(ic->arg[1]) = reg(ic->arg[0]);
1726 }
1727 X(mtlr) {
1728 cpu->cd.ppc.spr[SPR_LR] = reg(ic->arg[0]);
1729 }
1730 X(mtctr) {
1731 cpu->cd.ppc.spr[SPR_CTR] = reg(ic->arg[0]);
1732 }
1733
1734
1735 /*
1736 * rfi[d]: Return from Interrupt
1737 */
1738 X(rfi)
1739 {
1740 uint64_t tmp;
1741
1742 reg_access_msr(cpu, &tmp, 0, 0);
1743 tmp &= ~0xffff;
1744 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & 0xffff);
1745 reg_access_msr(cpu, &tmp, 1, 0);
1746
1747 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1748 quick_pc_to_pointers(cpu);
1749 }
1750 X(rfid)
1751 {
1752 uint64_t tmp, mask = 0x800000000000ff73ULL;
1753
1754 reg_access_msr(cpu, &tmp, 0, 0);
1755 tmp &= ~mask;
1756 tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & mask);
1757 reg_access_msr(cpu, &tmp, 1, 0);
1758
1759 cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1760 if (!(tmp & PPC_MSR_SF))
1761 cpu->pc = (uint32_t)cpu->pc;
1762 quick_pc_to_pointers(cpu);
1763 }
1764
1765
1766 /*
1767 * mfcr: Move From Condition Register
1768 *
1769 * arg[0] = pointer to destination register
1770 */
1771 X(mfcr)
1772 {
1773 reg(ic->arg[0]) = cpu->cd.ppc.cr;
1774 }
1775
1776
1777 /*
1778 * mfmsr: Move From MSR
1779 *
1780 * arg[0] = pointer to destination register
1781 */
1782 X(mfmsr)
1783 {
1784 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0, 0);
1785 }
1786
1787
1788 /*
1789 * mtmsr: Move To MSR
1790 *
1791 * arg[0] = pointer to source register
1792 * arg[1] = page offset of the next instruction
1793 * arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd)
1794 */
1795 X(mtmsr)
1796 {
1797 MODE_uint_t old_pc;
1798 uint64_t x = reg(ic->arg[0]);
1799
1800 /* TODO: check permission! */
1801
1802 /* Synchronize the PC (pointing to _after_ this instruction) */
1803 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1804 old_pc = cpu->pc;
1805
1806 if (!ic->arg[2]) {
1807 uint64_t y;
1808 reg_access_msr(cpu, &y, 0, 0);
1809 x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL);
1810 }
1811
1812 reg_access_msr(cpu, &x, 1, 1);
1813
1814 /*
1815 * Super-ugly hack: If the pc wasn't changed (i.e. if there was no
1816 * exception while accessing the msr), then we _decrease_ the PC by 4
1817 * again. This is because the next ic could be an end_of_page.
1818 */
1819 if ((MODE_uint_t)cpu->pc == old_pc)
1820 cpu->pc -= 4;
1821 }
1822
1823
1824 /*
1825 * wrteei: Write EE immediate (on PPC405GP)
1826 *
1827 * arg[0] = either 0 or 0x8000
1828 */
1829 X(wrteei)
1830 {
1831 /* TODO: check permission! */
1832 uint64_t x;
1833
1834 /* Synchronize the PC (pointing to _after_ this instruction) */
1835 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1836
1837 reg_access_msr(cpu, &x, 0, 0);
1838 x = (x & ~0x8000) | ic->arg[0];
1839 reg_access_msr(cpu, &x, 1, 1);
1840 }
1841
1842
1843 /*
1844 * mtcrf: Move To Condition Register Fields
1845 *
1846 * arg[0] = pointer to source register
1847 */
1848 X(mtcrf)
1849 {
1850 cpu->cd.ppc.cr &= ~ic->arg[1];
1851 cpu->cd.ppc.cr |= (reg(ic->arg[0]) & ic->arg[1]);
1852 }
1853
1854
1855 /*
1856 * mulli: Multiply Low Immediate.
1857 *
1858 * arg[0] = pointer to source register ra
1859 * arg[1] = int32_t immediate
1860 * arg[2] = pointer to destination register rt
1861 */
1862 X(mulli)
1863 {
1864 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * (int32_t)ic->arg[1]);
1865 }
1866
1867
1868 /*
1869 * Load/Store Multiple:
1870 *
1871 * arg[0] = rs (or rt for loads) NOTE: not a pointer
1872 * arg[1] = ptr to ra
1873 * arg[2] = int32_t immediate offset
1874 */
1875 X(lmw) {
1876 MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1877 unsigned char d[4];
1878 int rs = ic->arg[0];
1879
1880 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1881 / sizeof(struct ppc_instr_call);
1882 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1883 << PPC_INSTR_ALIGNMENT_SHIFT);
1884 cpu->pc |= (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1885
1886 while (rs <= 31) {
1887 if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1888 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1889 /* exception */
1890 return;
1891 }
1892
1893 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1894 cpu->cd.ppc.gpr[rs] = (d[0] << 24) + (d[1] << 16)
1895 + (d[2] << 8) + d[3];
1896 else
1897 cpu->cd.ppc.gpr[rs] = (d[3] << 24) + (d[2] << 16)
1898 + (d[1] << 8) + d[0];
1899
1900 rs ++;
1901 addr += sizeof(uint32_t);
1902 }
1903 }
1904 X(stmw) {
1905 MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1906 unsigned char d[4];
1907 int rs = ic->arg[0];
1908
1909 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1910 / sizeof(struct ppc_instr_call);
1911 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1912 << PPC_INSTR_ALIGNMENT_SHIFT);
1913 cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1914
1915 while (rs <= 31) {
1916 uint32_t tmp = cpu->cd.ppc.gpr[rs];
1917 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1918 d[3] = tmp; d[2] = tmp >> 8;
1919 d[1] = tmp >> 16; d[0] = tmp >> 24;
1920 } else {
1921 d[0] = tmp; d[1] = tmp >> 8;
1922 d[2] = tmp >> 16; d[3] = tmp >> 24;
1923 }
1924 if (cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d),
1925 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1926 /* exception */
1927 return;
1928 }
1929
1930 rs ++;
1931 addr += sizeof(uint32_t);
1932 }
1933 }
1934
1935
1936 /*
1937 * Load/store string:
1938 *
1939 * arg[0] = rs (well, rt for lswi)
1940 * arg[1] = ptr to ra (or ptr to zero)
1941 * arg[2] = nb
1942 */
1943 X(lswi)
1944 {
1945 MODE_uint_t addr = reg(ic->arg[1]);
1946 int rt = ic->arg[0], nb = ic->arg[2];
1947 int sub = 0;
1948
1949 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1950 / sizeof(struct ppc_instr_call);
1951 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1952 << PPC_INSTR_ALIGNMENT_SHIFT);
1953 cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1954
1955 while (nb > 0) {
1956 unsigned char d;
1957 if (cpu->memory_rw(cpu, cpu->mem, addr, &d, 1,
1958 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
1959 /* exception */
1960 return;
1961 }
1962
1963 if (cpu->cd.ppc.mode == MODE_POWER && sub == 0)
1964 cpu->cd.ppc.gpr[rt] = 0;
1965 cpu->cd.ppc.gpr[rt] &= ~(0xff << (24-8*sub));
1966 cpu->cd.ppc.gpr[rt] |= (d << (24-8*sub));
1967 sub ++;
1968 if (sub == 4) {
1969 rt = (rt + 1) & 31;
1970 sub = 0;
1971 }
1972 addr ++;
1973 nb --;
1974 }
1975 }
1976 X(stswi)
1977 {
1978 MODE_uint_t addr = reg(ic->arg[1]);
1979 int rs = ic->arg[0], nb = ic->arg[2];
1980 uint32_t cur = cpu->cd.ppc.gpr[rs];
1981 int sub = 0;
1982
1983 int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1984 / sizeof(struct ppc_instr_call);
1985 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1)
1986 << PPC_INSTR_ALIGNMENT_SHIFT);
1987 cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1988
1989 while (nb > 0) {
1990 unsigned char d = cur >> 24;
1991 if (cpu->memory_rw(cpu, cpu->mem, addr, &d, 1,
1992 MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
1993 /* exception */
1994 return;
1995 }
1996 cur <<= 8;
1997 sub ++;
1998 if (sub == 4) {
1999 rs = (rs + 1) & 31;
2000 sub = 0;
2001 cur = cpu->cd.ppc.gpr[rs];
2002 }
2003 addr ++;
2004 nb --;
2005 }
2006 }
2007
2008
2009 /*
2010 * Shifts, and, or, xor, etc.
2011 *
2012 * arg[0] = pointer to source register rs
2013 * arg[1] = pointer to source register rb
2014 * arg[2] = pointer to destination register ra
2015 */
2016 X(extsb) {
2017 #ifdef MODE32
2018 reg(ic->arg[2]) = (int32_t)(int8_t)reg(ic->arg[0]);
2019 #else
2020 reg(ic->arg[2]) = (int64_t)(int8_t)reg(ic->arg[0]);
2021 #endif
2022 }
2023 DOT2(extsb)
2024 X(extsh) {
2025 #ifdef MODE32
2026 reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]);
2027 #else
2028 reg(ic->arg[2]) = (int64_t)(int16_t)reg(ic->arg[0]);
2029 #endif
2030 }
2031 DOT2(extsh)
2032 X(extsw) {
2033 #ifdef MODE32
2034 fatal("TODO: extsw: invalid instruction\n");
2035 #else
2036 reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);
2037 #endif
2038 }
2039 DOT2(extsw)
2040 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2041 << (reg(ic->arg[1]) & 31); }
2042 DOT2(slw)
2043 X(sld) {int sa = reg(ic->arg[1]) & 127;
2044 if (sa >= 64) reg(ic->arg[2]) = 0;
2045 else reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (sa & 63); }
2046 DOT2(sld)
2047 X(sraw)
2048 {
2049 uint32_t tmp = reg(ic->arg[0]);
2050 int i = 0, j = 0, sh = reg(ic->arg[1]) & 31;
2051
2052 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2053 if (tmp & 0x80000000)
2054 i = 1;
2055 while (sh-- > 0) {
2056 if (tmp & 1)
2057 j ++;
2058 tmp >>= 1;
2059 if (tmp & 0x40000000)
2060 tmp |= 0x80000000;
2061 }
2062 if (i && j>0)
2063 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2064 reg(ic->arg[2]) = (int64_t)(int32_t)tmp;
2065 }
2066 DOT2(sraw)
2067 X(srw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2068 >> (reg(ic->arg[1]) & 31); }
2069 DOT2(srw)
2070 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
2071 DOT2(and)
2072 X(nand) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) & reg(ic->arg[1])); }
2073 DOT2(nand)
2074 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
2075 DOT2(andc)
2076 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
2077 DOT2(nor)
2078 X(mr) { reg(ic->arg[2]) = reg(ic->arg[1]); }
2079 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
2080 DOT2(or)
2081 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
2082 DOT2(orc)
2083 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
2084 DOT2(xor)
2085 X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); }
2086 DOT2(eqv)
2087
2088
2089 /*
2090 * neg:
2091 *
2092 * arg[0] = pointer to source register ra
2093 * arg[1] = pointer to destination register rt
2094 */
2095 X(neg) { reg(ic->arg[1]) = -reg(ic->arg[0]); }
2096 DOT1(neg)
2097
2098
2099 /*
2100 * mullw, mulhw[u], divw[u]:
2101 *
2102 * arg[0] = pointer to source register ra
2103 * arg[1] = pointer to source register rb
2104 * arg[2] = pointer to destination register rt
2105 */
2106 X(mullw)
2107 {
2108 int32_t sum = (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]);
2109 reg(ic->arg[2]) = (int32_t)sum;
2110 }
2111 DOT2(mullw)
2112 X(mulhw)
2113 {
2114 int64_t sum;
2115 sum = (int64_t)(int32_t)reg(ic->arg[0])
2116 * (int64_t)(int32_t)reg(ic->arg[1]);
2117 reg(ic->arg[2]) = sum >> 32;
2118 }
2119 DOT2(mulhw)
2120 X(mulhwu)
2121 {
2122 uint64_t sum;
2123 sum = (uint64_t)(uint32_t)reg(ic->arg[0])
2124 * (uint64_t)(uint32_t)reg(ic->arg[1]);
2125 reg(ic->arg[2]) = sum >> 32;
2126 }
2127 DOT2(mulhwu)
2128 X(divw)
2129 {
2130 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
2131 int32_t sum;
2132 if (b == 0)
2133 sum = 0;
2134 else
2135 sum = a / b;
2136 reg(ic->arg[2]) = (uint32_t)sum;
2137 }
2138 DOT2(divw)
2139 X(divwu)
2140 {
2141 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
2142 uint32_t sum;
2143 if (b == 0)
2144 sum = 0;
2145 else
2146 sum = a / b;
2147 reg(ic->arg[2]) = sum;
2148 }
2149 DOT2(divwu)
2150
2151
2152 /*
2153 * add: Add.
2154 *
2155 * arg[0] = pointer to source register ra
2156 * arg[1] = pointer to source register rb
2157 * arg[2] = pointer to destination register rt
2158 */
2159 X(add) { reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
2160 DOT2(add)
2161
2162
2163 /*
2164 * addc: Add carrying.
2165 *
2166 * arg[0] = pointer to source register ra
2167 * arg[1] = pointer to source register rb
2168 * arg[2] = pointer to destination register rt
2169 */
2170 X(addc)
2171 {
2172 /* TODO: this only works in 32-bit mode */
2173 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2174 uint64_t tmp2 = tmp;
2175 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2176 tmp += (uint32_t)reg(ic->arg[1]);
2177 if ((tmp >> 32) != (tmp2 >> 32))
2178 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2179 reg(ic->arg[2]) = (uint32_t)tmp;
2180 }
2181
2182
2183 /*
2184 * adde: Add extended, etc.
2185 *
2186 * arg[0] = pointer to source register ra
2187 * arg[1] = pointer to source register rb
2188 * arg[2] = pointer to destination register rt
2189 */
2190 X(adde)
2191 {
2192 /* TODO: this only works in 32-bit mode */
2193 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2194 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2195 uint64_t tmp2 = tmp;
2196 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2197 tmp += (uint32_t)reg(ic->arg[1]);
2198 if (old_ca)
2199 tmp ++;
2200 if ((tmp >> 32) != (tmp2 >> 32))
2201 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2202 reg(ic->arg[2]) = (uint32_t)tmp;
2203 }
2204 DOT2(adde)
2205 X(addme)
2206 {
2207 /* TODO: this only works in 32-bit mode */
2208 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2209 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2210 uint64_t tmp2 = tmp;
2211 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2212 if (old_ca)
2213 tmp ++;
2214 tmp += 0xffffffffULL;
2215 if ((tmp >> 32) != (tmp2 >> 32))
2216 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2217 reg(ic->arg[2]) = (uint32_t)tmp;
2218 }
2219 DOT2(addme)
2220 X(addze)
2221 {
2222 /* TODO: this only works in 32-bit mode */
2223 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2224 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
2225 uint64_t tmp2 = tmp;
2226 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2227 if (old_ca)
2228 tmp ++;
2229 if ((tmp >> 32) != (tmp2 >> 32))
2230 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2231 reg(ic->arg[2]) = (uint32_t)tmp;
2232 }
2233 DOT2(addze)
2234
2235
2236 /*
2237 * subf: Subf, etc.
2238 *
2239 * arg[0] = pointer to source register ra
2240 * arg[1] = pointer to source register rb
2241 * arg[2] = pointer to destination register rt
2242 */
2243 X(subf)
2244 {
2245 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2246 }
2247 DOT2(subf)
2248 X(subfc)
2249 {
2250 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2251 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2252 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2253 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]);
2254 }
2255 DOT2(subfc)
2256 X(subfe)
2257 {
2258 int old_ca = (cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA)? 1 : 0;
2259 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2260 if (reg(ic->arg[1]) == reg(ic->arg[0])) {
2261 if (old_ca)
2262 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2263 } else if (reg(ic->arg[1]) >= reg(ic->arg[0]))
2264 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2265
2266 /*
2267 * TODO: The register value calculation should be correct,
2268 * but the CA bit calculation above is probably not.
2269 */
2270
2271 reg(ic->arg[2]) = reg(ic->arg[1]) - reg(ic->arg[0]) - (old_ca? 0 : 1);
2272 }
2273 DOT2(subfe)
2274 X(subfme)
2275 {
2276 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2277 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2278 tmp += 0xffffffffULL;
2279 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2280 if (old_ca)
2281 tmp ++;
2282 if ((tmp >> 32) != 0)
2283 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2284 reg(ic->arg[2]) = (uint32_t)tmp;
2285 }
2286 DOT2(subfme)
2287 X(subfze)
2288 {
2289 int old_ca = cpu->cd.ppc.spr[SPR_XER] & PPC_XER_CA;
2290 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
2291 uint64_t tmp2 = tmp;
2292 cpu->cd.ppc.spr[SPR_XER] &= ~PPC_XER_CA;
2293 if (old_ca)
2294 tmp ++;
2295 if ((tmp >> 32) != (tmp2 >> 32))
2296 cpu->cd.ppc.spr[SPR_XER] |= PPC_XER_CA;
2297 reg(ic->arg[2]) = (uint32_t)tmp;
2298 }
2299 DOT2(subfze)
2300
2301
2302 /*
2303 * ori, xori etc.:
2304 *
2305 * arg[0] = pointer to source uint64_t
2306 * arg[1] = immediate value (uint32_t or larger)
2307 * arg[2] = pointer to destination uint64_t
2308 */
2309 X(ori) { reg(ic->arg[2]) = reg(ic->arg[0]) | (uint32_t)ic->arg[1]; }
2310 X(xori) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[1]; }
2311
2312
2313 #include "tmp_ppc_loadstore.c"
2314
2315
2316 /*
2317 * lfs, stfs: Load/Store Floating-point Single precision
2318 */
2319 X(lfs)
2320 {
2321 /* Sync. PC in case of an exception, and remember it: */
2322 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2323 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2324 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2325 PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2326 if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2327 ppc_exception(cpu, PPC_EXCEPTION_FPU);
2328 return;
2329 }
2330
2331 /* Perform a 32-bit load: */
2332 #ifdef MODE32
2333 ppc32_loadstore
2334 #else
2335 ppc_loadstore
2336 #endif
2337 [2 + 4 + 8](cpu, ic);
2338
2339 if (old_pc == cpu->pc) {
2340 /* The load succeeded. Let's convert the value: */
2341 struct ieee_float_value val;
2342 (*(uint64_t *)ic->arg[0]) &= 0xffffffff;
2343 ieee_interpret_float_value(*(uint64_t *)ic->arg[0],
2344 &val, IEEE_FMT_S);
2345 (*(uint64_t *)ic->arg[0]) =
2346 ieee_store_float_value(val.f, IEEE_FMT_D, val.nan);
2347 }
2348 }
2349 X(lfsx)
2350 {
2351 /* Sync. PC in case of an exception, and remember it: */
2352 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2353 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2354 old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2355 PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2356 if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2357 ppc_exception(cpu, PPC_EXCEPTION_FPU);
2358 return;
2359 }
2360
2361 /* Perform a 32-bit load: */
2362 #ifdef MODE32
2363 ppc32_loadstore_indexed
2364 #else
2365 ppc_loadstore_indexed
2366 #endif
2367 [2 + 4 + 8](cpu, ic);
2368
2369 if (old_pc == cpu->pc) {
2370 /* The load succeeded. Let's convert the value: */
2371 struct ieee_float_value val;
2372 (*(uint64_t *)ic->arg[0]) &= 0xffffffff;
2373 ieee_interpret_float_value(*(uint64_t *)ic->arg[0],
2374 &val, IEEE_FMT_S);
2375 (*(uint64_t *)ic->arg[0]) =
2376 ieee_store_float_value(val.f, IEEE_FMT_D, val.nan);
2377 }
2378 }
2379 X(lfd)
2380 {
2381 CHECK_FOR_FPU_EXCEPTION;
2382
2383 /* Perform a 64-bit load: */
2384 #ifdef MODE32
2385 ppc32_loadstore
2386 #else
2387 ppc_loadstore
2388 #endif
2389 [3 + 4 + 8](cpu, ic);
2390 }
2391 X(lfdx)
2392 {
2393 CHECK_FOR_FPU_EXCEPTION;
2394
2395 /* Perform a 64-bit load: */
2396 #ifdef MODE32
2397 ppc32_loadstore_indexed
2398 #else
2399 ppc_loadstore_indexed
2400 #endif
2401 [3 + 4 + 8](cpu, ic);
2402 }
2403 X(stfs)
2404 {
2405 uint64_t *old_arg0 = (void *)ic->arg[0];
2406 struct ieee_float_value val;
2407 uint64_t tmp_val;
2408
2409 CHECK_FOR_FPU_EXCEPTION;
2410
2411 ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2412 tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
2413
2414 ic->arg[0] = (size_t)&tmp_val;
2415
2416 /* Perform a 32-bit store: */
2417 #ifdef MODE32
2418 ppc32_loadstore
2419 #else
2420 ppc_loadstore
2421 #endif
2422 [2 + 4](cpu, ic);
2423
2424 ic->arg[0] = (size_t)old_arg0;
2425 }
2426 X(stfsx)
2427 {
2428 uint64_t *old_arg0 = (void *)ic->arg[0];
2429 struct ieee_float_value val;
2430 uint64_t tmp_val;
2431
2432 CHECK_FOR_FPU_EXCEPTION;
2433
2434 ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2435 tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
2436
2437 ic->arg[0] = (size_t)&tmp_val;
2438
2439 /* Perform a 32-bit store: */
2440 #ifdef MODE32
2441 ppc32_loadstore_indexed
2442 #else
2443 ppc_loadstore_indexed
2444 #endif
2445 [2 + 4](cpu, ic);
2446
2447 ic->arg[0] = (size_t)old_arg0;
2448 }
2449 X(stfd)
2450 {
2451 CHECK_FOR_FPU_EXCEPTION;
2452
2453 /* Perform a 64-bit store: */
2454 #ifdef MODE32
2455 ppc32_loadstore
2456 #else
2457 ppc_loadstore
2458 #endif
2459 [3 + 4](cpu, ic);
2460 }
2461 X(stfdx)
2462 {
2463 CHECK_FOR_FPU_EXCEPTION;
2464
2465 /* Perform a 64-bit store: */
2466 #ifdef MODE32
2467 ppc32_loadstore_indexed
2468 #else
2469 ppc_loadstore_indexed
2470 #endif
2471 [3 + 4](cpu, ic);
2472 }
2473
2474
2475 /*
2476 * 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 * tlbia: TLB invalidate all
2561 */
2562 X(tlbia)
2563 {
2564 fatal("[ tlbia ]\n");
2565 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2566 }
2567
2568
2569 /*
2570 * tlbie: TLB invalidate
2571 */
2572 X(tlbie)
2573 {
2574 /* fatal("[ tlbie ]\n"); */
2575 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2576 INVALIDATE_VADDR);
2577 }
2578
2579
2580 /*
2581 * 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
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 }
2593
2594
2595 /*
2596 * 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
2604 if (!cpu->running) {
2605 cpu->n_translated_instrs --;
2606 cpu->cd.ppc.next_ic = &nothing_call;
2607 }
2608 }
2609
2610
2611 /*
2612 * openfirmware:
2613 */
2614 X(openfirmware)
2615 {
2616 of_emul(cpu);
2617 if (cpu->running == 0) {
2618 cpu->n_translated_instrs --;
2619 cpu->cd.ppc.next_ic = &nothing_call;
2620 }
2621 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2622 if (cpu->machine->show_trace_tree)
2623 cpu_functioncall_trace_return(cpu);
2624 quick_pc_to_pointers(cpu);
2625 }
2626
2627
2628 /*
2629 * 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 * tlbli:
2642 */
2643 X(tlbli)
2644 {
2645 fatal("tlbli\n");
2646 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2647 }
2648
2649
2650 /*
2651 * tlbld:
2652 */
2653 X(tlbld)
2654 {
2655 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2656 MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2657
2658 fatal("tlbld\n");
2659 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2660 }
2661
2662
2663 /*****************************************************************************/
2664
2665
2666 X(end_of_page)
2667 {
2668 /* Update the PC: (offset 0, but on the next page) */
2669 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
2672 /* Find the new physical page and update the translation pointers: */
2673 quick_pc_to_pointers(cpu);
2674
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 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2687 * 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 uint32_t iword, mask;
2695 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 bfa, fp, byterev, nb, mb, me;
2700 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 #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
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 fatal("PPC to_be_translated(): "
2738 "read failed: TODO\n");
2739 exit(1);
2740 /* goto bad; */
2741 }
2742 }
2743
2744 iword = *((uint32_t *)&ib[0]);
2745 iword = BE32_TO_HOST(iword);
2746
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 case 0x04:
2762 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 if (!cpu->translation_readahead)
2770 fatal("[ TODO: Unimplemented ALTIVEC, iword"
2771 " = 0x%08"PRIx32"x ]\n", iword);
2772 goto bad;
2773 }
2774 break;
2775
2776 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 else {
2812 if (bf == 0)
2813 ic->f = instr(cmpwi_cr0);
2814 else
2815 ic->f = instr(cmpwi);
2816 }
2817 }
2818 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2819 ic->arg[1] = (ssize_t)imm;
2820 ic->arg[2] = 28 - 4 * bf;
2821 break;
2822
2823 case PPC_HI6_ADDIC:
2824 case PPC_HI6_ADDIC_DOT:
2825 if (cpu->cd.ppc.bits == 64) {
2826 if (!cpu->translation_readahead)
2827 fatal("addic for 64-bit: TODO\n");
2828 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 ic->arg[1] = imm;
2839 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 ic->f = instr(li);
2848 else
2849 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2850 ic->arg[1] = (int16_t)(iword & 0xffff);
2851 if (main_opcode == PPC_HI6_ADDIS)
2852 ic->arg[1] <<= 16;
2853 if (ra == 0 && ic->arg[1] == 0)
2854 ic->f = instr(li_0);
2855 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 case PPC_HI6_LHA:
2892 case PPC_HI6_LHAU:
2893 case PPC_HI6_LWZ:
2894 case PPC_HI6_LWZU:
2895 case PPC_HI6_LD:
2896 case PPC_HI6_LFD:
2897 case PPC_HI6_LFS:
2898 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 case PPC_HI6_STD:
2905 case PPC_HI6_STFD:
2906 case PPC_HI6_STFS:
2907 rs = (iword >> 21) & 31;
2908 ra = (iword >> 16) & 31;
2909 imm = (int16_t)iword;
2910 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2911 ic->f = NULL;
2912 switch (main_opcode) {
2913 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 case PPC_HI6_LD: load=1; size=3; break;
2922 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 case PPC_HI6_STB: break;
2925 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 case PPC_HI6_STD: size=3; break;
2931 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 }
2934 if (ic->f == NULL) {
2935 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 if (!cpu->translation_readahead)
2946 fatal("TODO: ra=0 && update?\n");
2947 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 if (!cpu->translation_readahead)
2968 fatal("aa_bit: NOT YET\n");
2969 goto bad;
2970 }
2971 if (lk_bit) {
2972 ic->f = instr(bcl);
2973 samepage_function = instr(bcl_samepage);
2974 } else {
2975 ic->f = instr(bc);
2976 if ((bo & 0x14) == 0x04) {
2977 samepage_function = bo & 8?
2978 instr(bc_samepage_simple1) :
2979 instr(bc_samepage_simple0);
2980 } else
2981 samepage_function = instr(bc_samepage);
2982 }
2983 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2984 ic->arg[1] = bo;
2985 ic->arg[2] = 31-bi;
2986 /* 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 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2993 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 ic->arg[1] = (addr & 0xfff) + 4;
3006 if (cpu->machine->userland_emul != NULL)
3007 ic->f = instr(user_syscall);
3008 else if (iword == 0x44ee0002) {
3009 /* Special case/magic hack for OpenFirmware emul: */
3010 ic->f = instr(openfirmware);
3011 } else
3012 ic->f = instr(sc);
3013 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 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
3033 ic->arg[1] = (addr & 0xffc) + 4;
3034 /* 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 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
3041 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 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 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 else {
3077 ic->f = instr(bclr);
3078 if (!cpu->machine->show_trace_tree &&
3079 (bo & 0x14) == 0x14)
3080 ic->f = instr(bclr_20);
3081 }
3082 } else {
3083 if (!(bo & 4)) {
3084 if (!cpu->translation_readahead)
3085 fatal("TODO: bclr/bcctr "
3086 "bo bit 2 clear!\n");
3087 goto bad;
3088 }
3089 if (lk_bit)
3090 ic->f = instr(bcctr_l);
3091 else
3092 ic->f = instr(bcctr);
3093 }
3094 ic->arg[0] = bo;
3095 ic->arg[1] = 31 - bi;
3096 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 case PPC_19_RFID:
3109 ic->f = instr(rfid);
3110 break;
3111
3112 case PPC_19_MCRF:
3113 bf = (iword >> 23) & 7;
3114 bfa = (iword >> 18) & 7;
3115 ic->arg[0] = 28 - 4*bf;
3116 ic->arg[1] = 28 - 4*bfa;
3117 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 case PPC_19_CRORC:
3125 case PPC_19_CRNOR:
3126 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 case PPC_19_CRORC: ic->f = instr(crorc); break;
3133 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3134 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 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 case PPC_HI6_RLWIMI:
3168 rs = (iword >> 21) & 31;
3169 ra = (iword >> 16) & 31;
3170 ic->f = instr(rlwimi);
3171 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 case PPC_30_RLDICL:
3202 case PPC_30_RLDICR:
3203 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 ic->arg[0] = iword;
3210 if (cpu->cd.ppc.bits == 32) {
3211 if (!cpu->translation_readahead)
3212 fatal("TODO: rld* in 32-bit mode?\n");
3213 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 else {
3240 if (bf == 0)
3241 ic->f = instr(cmpw_cr0);
3242 else
3243 ic->f = instr(cmpw);
3244 }
3245 }
3246 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3247 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3248 ic->arg[2] = 28 - 4*bf;
3249 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 if (!cpu->translation_readahead)
3257 fatal("TODO: rc\n");
3258 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 debug_spr_usage(cpu->pc, spr);
3269 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3270 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3271 switch (spr) {
3272 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3273 default: ic->f = instr(mfspr);
3274 }
3275 break;
3276
3277 case PPC_31_MTSPR:
3278 rs = (iword >> 21) & 31;
3279 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3280 debug_spr_usage(cpu->pc, spr);
3281 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3282 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3283 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 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 case PPC_31_MTMSRD:
3308 rs = (iword >> 21) & 31;
3309 l_bit = (iword >> 16) & 1;
3310 if (l_bit) {
3311 if (!cpu->translation_readahead)
3312 fatal("TODO: mtmsr l-bit\n");
3313 goto bad;
3314 }
3315 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3316 ic->arg[1] = (addr & 0xfff) + 4;
3317 ic->arg[2] = xo == PPC_31_MTMSRD;
3318 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 if (!cpu->translation_readahead)
3349 fatal("Not yet for 64-bit mode\n");
3350 goto bad;
3351 }
3352 break;
3353
3354 case PPC_31_MFSR:
3355 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 switch (xo) {
3360 case PPC_31_MFSR: ic->f = instr(mfsr); break;
3361 case PPC_31_MTSR: ic->f = instr(mtsr); break;
3362 }
3363 if (cpu->cd.ppc.bits == 64) {
3364 if (!cpu->translation_readahead)
3365 fatal("Not yet for 64-bit mode\n");
3366 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 case PPC_31_DSSALL:
3386 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 ic->arg[2] = addr & 0xfff;
3404 ic->f = instr(dcbz);
3405 break;
3406
3407 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 case PPC_31_TLBIE:
3420 /* TODO: POWER also uses ra? */
3421 rb = (iword >> 11) & 31;
3422 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3423 ic->f = instr(tlbie);
3424 break;
3425
3426 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 case PPC_31_TLBSX_DOT:
3439 /* TODO */
3440 ic->f = instr(tlbsx_dot);
3441 break;
3442
3443 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 default:if (!cpu->translation_readahead)
3451 fatal("mftb spr=%i?\n", spr);
3452 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 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 case PPC_31_WRTEEI:
3494 ic->arg[0] = iword & 0x8000;
3495 ic->f = instr(wrteei);
3496 break;
3497
3498 case 0x1c3:
3499 fatal("[ mtdcr: TODO ]\n");
3500 ic->f = instr(nop);
3501 break;
3502
3503 case PPC_31_LBZX:
3504 case PPC_31_LBZUX:
3505 case PPC_31_LHAX:
3506 case PPC_31_LHAUX:
3507 case PPC_31_LHZX:
3508 case PPC_31_LHZUX:
3509 case PPC_31_LWZX:
3510 case PPC_31_LWZUX:
3511 case PPC_31_LHBRX:
3512 case PPC_31_LWBRX:
3513 case PPC_31_LFDX:
3514 case PPC_31_LFSX:
3515 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 case PPC_31_STHBRX:
3524 case PPC_31_STWBRX:
3525 case PPC_31_STFDX:
3526 case PPC_31_STFSX:
3527 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 byterev = 0; fp = 0;
3537 ic->f = NULL;
3538 switch (xo) {
3539 case PPC_31_LBZX: load = 1; break;
3540 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 case PPC_31_STBX: break;
3556 case PPC_31_STBUX: update = 1; break;
3557 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 }
3572 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 #ifdef MODE32
3579 ppc32_loadstore_indexed
3580 #else
3581 ppc_loadstore_indexed
3582 #endif
3583 [size + 4*zero + 8*load + 16*update];
3584 }
3585 if (ra == 0 && update) {
3586 if (!cpu->translation_readahead)
3587 fatal("TODO: ra=0 && update?\n");
3588 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 case PPC_31_SLD:
3597 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 case PPC_31_EQV:
3607 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 case PPC_31_SLD: ic->f = instr(sld);
3622 rc_f = instr(sld_dot); break;
3623 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 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3636 : instr(or);
3637 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 case PPC_31_EQV: ic->f = instr(eqv);
3643 rc_f = instr(eqv_dot); break;
3644 }
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 case PPC_31_SUBFME:
3666 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 if (!cpu->translation_readahead)
3674 fatal("oe_bit not yet implemented\n");
3675 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 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3692 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 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 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 case PPC_31_SUBFME:
3721 ic->f = instr(subfme_dot); break;
3722 case PPC_31_SUBFZE:
3723 ic->f = instr(subfze_dot); break;
3724 default:if (!cpu->translation_readahead)
3725 fatal("RC bit not yet "
3726 "implemented\n");
3727 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 if (!cpu->translation_readahead)
3735 fatal("Not yet for 64-bit mode\n");
3736 goto bad;
3737 }
3738 break;
3739
3740 case PPC_31_LVX:
3741 case PPC_31_LVXL:
3742 case PPC_31_STVX:
3743 case PPC_31_STVXL:
3744 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 ic->arg[0] = rs;
3754 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 ic->f = load? instr(lvx) : instr(stvx);
3760 break;
3761
3762 default:goto bad;
3763 }
3764 break;
3765
3766 case PPC_HI6_59:
3767 xo = (iword >> 1) & 1023;
3768 rt = (iword >> 21) & 31;
3769 ra = (iword >> 16) & 31;
3770 rb = (iword >> 11) & 31;
3771 rs = (iword >> 6) & 31; /* actually frc */
3772 rc = iword & 1;
3773
3774 if (rc) {
3775 if (!cpu->translation_readahead)
3776 fatal("Floating point (59) "
3777 "with rc bit! TODO\n");
3778 goto bad;
3779 }
3780
3781 /* 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 }
3792 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 break;
3796 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
3809 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 if (!cpu->translation_readahead)
3819 fatal("Floating point (63) "
3820 "with rc bit! TODO\n");
3821 goto bad;
3822 }
3823
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 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