/[gxemul]/upstream/0.4.2/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 /upstream/0.4.2/src/cpus/cpu_ppc_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26