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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (show annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 91889 byte(s)
0.4.4
1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc_instr.c,v 1.73 2007/02/17 10:06:19 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 * lvx, stvx: Vector (16-byte) load/store (slow implementation)
2477 *
2478 * arg[0] = v-register nr of rs
2479 * arg[1] = pointer to ra
2480 * arg[2] = pointer to rb
2481 */
2482 X(lvx)
2483 {
2484 MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2485 uint8_t data[16];
2486 uint64_t hi, lo;
2487 int rs = ic->arg[0];
2488
2489 if (cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
2490 MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) {
2491 /* exception */
2492 return;
2493 }
2494
2495 hi = ((uint64_t)data[0] << 56) +
2496 ((uint64_t)data[1] << 48) +
2497 ((uint64_t)data[2] << 40) +
2498 ((uint64_t)data[3] << 32) +
2499 ((uint64_t)data[4] << 24) +
2500 ((uint64_t)data[5] << 16) +
2501 ((uint64_t)data[6] << 8) +
2502 ((uint64_t)data[7]);
2503 lo = ((uint64_t)data[8] << 56) +
2504 ((uint64_t)data[9] << 48) +
2505 ((uint64_t)data[10] << 40) +
2506 ((uint64_t)data[11] << 32) +
2507 ((uint64_t)data[12] << 24) +
2508 ((uint64_t)data[13] << 16) +
2509 ((uint64_t)data[14] << 8) +
2510 ((uint64_t)data[15]);
2511
2512 cpu->cd.ppc.vr_hi[rs] = hi; cpu->cd.ppc.vr_lo[rs] = lo;
2513 }
2514 X(stvx)
2515 {
2516 uint8_t data[16];
2517 MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]);
2518 int rs = ic->arg[0];
2519 uint64_t hi = cpu->cd.ppc.vr_hi[rs], lo = cpu->cd.ppc.vr_lo[rs];
2520
2521 data[0] = hi >> 56;
2522 data[1] = hi >> 48;
2523 data[2] = hi >> 40;
2524 data[3] = hi >> 32;
2525 data[4] = hi >> 24;
2526 data[5] = hi >> 16;
2527 data[6] = hi >> 8;
2528 data[7] = hi;
2529 data[8] = lo >> 56;
2530 data[9] = lo >> 48;
2531 data[10] = lo >> 40;
2532 data[11] = lo >> 32;
2533 data[12] = lo >> 24;
2534 data[13] = lo >> 16;
2535 data[14] = lo >> 8;
2536 data[15] = lo;
2537
2538 cpu->memory_rw(cpu, cpu->mem, addr, data,
2539 sizeof(data), MEM_WRITE, CACHE_DATA);
2540 }
2541
2542
2543 /*
2544 * vxor: Vector (16-byte) XOR
2545 *
2546 * arg[0] = v-register nr of source 1
2547 * arg[1] = v-register nr of source 2
2548 * arg[2] = v-register nr of destination
2549 */
2550 X(vxor)
2551 {
2552 cpu->cd.ppc.vr_hi[ic->arg[2]] =
2553 cpu->cd.ppc.vr_hi[ic->arg[0]] ^ cpu->cd.ppc.vr_hi[ic->arg[1]];
2554 cpu->cd.ppc.vr_lo[ic->arg[2]] =
2555 cpu->cd.ppc.vr_lo[ic->arg[0]] ^ cpu->cd.ppc.vr_lo[ic->arg[1]];
2556 }
2557
2558
2559 /*
2560 * tlbia: TLB invalidate all
2561 */
2562 X(tlbia)
2563 {
2564 fatal("[ tlbia ]\n");
2565 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2566 }
2567
2568
2569 /*
2570 * tlbie: TLB invalidate
2571 */
2572 X(tlbie)
2573 {
2574 /* fatal("[ tlbie ]\n"); */
2575 cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2576 INVALIDATE_VADDR);
2577 }
2578
2579
2580 /*
2581 * sc: Syscall.
2582 */
2583 X(sc)
2584 {
2585 /* Synchronize the PC (pointing to _after_ this instruction) */
2586 cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2587
2588 ppc_exception(cpu, PPC_EXCEPTION_SC);
2589
2590 /* This caused an update to the PC register, so there is no need
2591 to worry about the next instruction being an end_of_page. */
2592 }
2593
2594
2595 /*
2596 * user_syscall: Userland syscall.
2597 *
2598 * arg[0] = syscall "level" (usually 0)
2599 */
2600 X(user_syscall)
2601 {
2602 useremul_syscall(cpu, ic->arg[0]);
2603
2604 if (!cpu->running) {
2605 cpu->n_translated_instrs --;
2606 cpu->cd.ppc.next_ic = &nothing_call;
2607 }
2608 }
2609
2610
2611 /*
2612 * openfirmware:
2613 */
2614 X(openfirmware)
2615 {
2616 of_emul(cpu);
2617 if (cpu->running == 0) {
2618 cpu->n_translated_instrs --;
2619 cpu->cd.ppc.next_ic = &nothing_call;
2620 }
2621 cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2622 if (cpu->machine->show_trace_tree)
2623 cpu_functioncall_trace_return(cpu);
2624 quick_pc_to_pointers(cpu);
2625 }
2626
2627
2628 /*
2629 * tlbsx_dot: TLB scan
2630 */
2631 X(tlbsx_dot)
2632 {
2633 /* TODO */
2634 cpu->cd.ppc.cr &= ~(0xf0000000);
2635 cpu->cd.ppc.cr |= 0x20000000;
2636 cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2637 }
2638
2639
2640 /*
2641 * tlbli:
2642 */
2643 X(tlbli)
2644 {
2645 fatal("tlbli\n");
2646 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2647 }
2648
2649
2650 /*
2651 * tlbld:
2652 */
2653 X(tlbld)
2654 {
2655 /* MODE_uint_t vaddr = reg(ic->arg[0]);
2656 MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA]; */
2657
2658 fatal("tlbld\n");
2659 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2660 }
2661
2662
2663 /*****************************************************************************/
2664
2665
2666 X(end_of_page)
2667 {
2668 /* Update the PC: (offset 0, but on the next page) */
2669 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2670 cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2671
2672 /* Find the new physical page and update the translation pointers: */
2673 quick_pc_to_pointers(cpu);
2674
2675 /* end_of_page doesn't count as an executed instruction: */
2676 cpu->n_translated_instrs --;
2677 }
2678
2679
2680 /*****************************************************************************/
2681
2682
2683 /*
2684 * ppc_instr_to_be_translated():
2685 *
2686 * Translate an instruction word into a ppc_instr_call. ic is filled in with
2687 * valid data for the translated instruction, or a "nothing" instruction if
2688 * there was a translation failure. The newly translated instruction is then
2689 * executed.
2690 */
2691 X(to_be_translated)
2692 {
2693 uint64_t addr, low_pc, tmp_addr;
2694 uint32_t iword, mask;
2695 unsigned char *page;
2696 unsigned char ib[4];
2697 int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
2698 xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,
2699 bfa, fp, byterev, nb, mb, me;
2700 void (*samepage_function)(struct cpu *, struct ppc_instr_call *);
2701 void (*rc_f)(struct cpu *, struct ppc_instr_call *);
2702
2703 /* Figure out the (virtual) address of the instruction: */
2704 low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
2705 / sizeof(struct ppc_instr_call);
2706 addr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
2707 << PPC_INSTR_ALIGNMENT_SHIFT);
2708 addr += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2709 cpu->pc = addr;
2710 addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
2711
2712 /* Read the instruction word from memory: */
2713 #ifdef MODE32
2714 page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12];
2715 #else
2716 {
2717 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2718 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2719 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2720 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2721 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2722 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2723 DYNTRANS_L3N)) & mask3;
2724 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1];
2725 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2726 page = l3->host_load[x3];
2727 }
2728 #endif
2729
2730 if (page != NULL) {
2731 /* fatal("TRANSLATION HIT!\n"); */
2732 memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2733 } else {
2734 /* fatal("TRANSLATION MISS!\n"); */
2735 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2736 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2737 fatal("PPC to_be_translated(): "
2738 "read failed: TODO\n");
2739 exit(1);
2740 /* goto bad; */
2741 }
2742 }
2743
2744 iword = *((uint32_t *)&ib[0]);
2745 iword = BE32_TO_HOST(iword);
2746
2747
2748 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2749 #include "cpu_dyntrans.c"
2750 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2751
2752
2753 /*
2754 * Translate the instruction:
2755 */
2756
2757 main_opcode = iword >> 26;
2758
2759 switch (main_opcode) {
2760
2761 case 0x04:
2762 if (iword == 0x12739cc4) {
2763 /* vxor v19,v19,v19 */
2764 ic->f = instr(vxor);
2765 ic->arg[0] = 19;
2766 ic->arg[1] = 19;
2767 ic->arg[2] = 19;
2768 } else {
2769 fatal("[ TODO: Unimplemented ALTIVEC, iword"
2770 " = 0x%08"PRIx32"x ]\n", iword);
2771 goto bad;
2772 }
2773 break;
2774
2775 case PPC_HI6_MULLI:
2776 rt = (iword >> 21) & 31;
2777 ra = (iword >> 16) & 31;
2778 imm = (int16_t)(iword & 0xffff);
2779 ic->f = instr(mulli);
2780 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2781 ic->arg[1] = (ssize_t)imm;
2782 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2783 break;
2784
2785 case PPC_HI6_SUBFIC:
2786 rt = (iword >> 21) & 31;
2787 ra = (iword >> 16) & 31;
2788 imm = (int16_t)(iword & 0xffff);
2789 ic->f = instr(subfic);
2790 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2791 ic->arg[1] = (ssize_t)imm;
2792 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2793 break;
2794
2795 case PPC_HI6_CMPLI:
2796 case PPC_HI6_CMPI:
2797 bf = (iword >> 23) & 7;
2798 l_bit = (iword >> 21) & 1;
2799 ra = (iword >> 16) & 31;
2800 if (main_opcode == PPC_HI6_CMPLI) {
2801 imm = iword & 0xffff;
2802 if (l_bit)
2803 ic->f = instr(cmpldi);
2804 else
2805 ic->f = instr(cmplwi);
2806 } else {
2807 imm = (int16_t)(iword & 0xffff);
2808 if (l_bit)
2809 ic->f = instr(cmpdi);
2810 else {
2811 if (bf == 0)
2812 ic->f = instr(cmpwi_cr0);
2813 else
2814 ic->f = instr(cmpwi);
2815 }
2816 }
2817 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2818 ic->arg[1] = (ssize_t)imm;
2819 ic->arg[2] = 28 - 4 * bf;
2820 break;
2821
2822 case PPC_HI6_ADDIC:
2823 case PPC_HI6_ADDIC_DOT:
2824 if (cpu->cd.ppc.bits == 64) {
2825 fatal("addic for 64-bit: TODO\n");
2826 goto bad;
2827 }
2828 rt = (iword >> 21) & 31;
2829 ra = (iword >> 16) & 31;
2830 imm = (int16_t)(iword & 0xffff);
2831 if (main_opcode == PPC_HI6_ADDIC)
2832 ic->f = instr(addic);
2833 else
2834 ic->f = instr(addic_dot);
2835 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2836 ic->arg[1] = imm;
2837 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2838 break;
2839
2840 case PPC_HI6_ADDI:
2841 case PPC_HI6_ADDIS:
2842 rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2843 ic->f = instr(addi);
2844 if (ra == 0)
2845 ic->f = instr(li);
2846 else
2847 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2848 ic->arg[1] = (int16_t)(iword & 0xffff);
2849 if (main_opcode == PPC_HI6_ADDIS)
2850 ic->arg[1] <<= 16;
2851 if (ra == 0 && ic->arg[1] == 0)
2852 ic->f = instr(li_0);
2853 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2854 break;
2855
2856 case PPC_HI6_ANDI_DOT:
2857 case PPC_HI6_ANDIS_DOT:
2858 rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2859 ic->f = instr(andi_dot);
2860 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2861 ic->arg[1] = iword & 0xffff;
2862 if (main_opcode == PPC_HI6_ANDIS_DOT)
2863 ic->arg[1] <<= 16;
2864 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2865 break;
2866
2867 case PPC_HI6_ORI:
2868 case PPC_HI6_ORIS:
2869 case PPC_HI6_XORI:
2870 case PPC_HI6_XORIS:
2871 rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2872 if (main_opcode == PPC_HI6_ORI ||
2873 main_opcode == PPC_HI6_ORIS)
2874 ic->f = instr(ori);
2875 else
2876 ic->f = instr(xori);
2877 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2878 ic->arg[1] = iword & 0xffff;
2879 if (main_opcode == PPC_HI6_ORIS ||
2880 main_opcode == PPC_HI6_XORIS)
2881 ic->arg[1] <<= 16;
2882 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2883 break;
2884
2885 case PPC_HI6_LBZ:
2886 case PPC_HI6_LBZU:
2887 case PPC_HI6_LHZ:
2888 case PPC_HI6_LHZU:
2889 case PPC_HI6_LHA:
2890 case PPC_HI6_LHAU:
2891 case PPC_HI6_LWZ:
2892 case PPC_HI6_LWZU:
2893 case PPC_HI6_LD:
2894 case PPC_HI6_LFD:
2895 case PPC_HI6_LFS:
2896 case PPC_HI6_STB:
2897 case PPC_HI6_STBU:
2898 case PPC_HI6_STH:
2899 case PPC_HI6_STHU:
2900 case PPC_HI6_STW:
2901 case PPC_HI6_STWU:
2902 case PPC_HI6_STD:
2903 case PPC_HI6_STFD:
2904 case PPC_HI6_STFS:
2905 rs = (iword >> 21) & 31;
2906 ra = (iword >> 16) & 31;
2907 imm = (int16_t)iword;
2908 load = 0; zero = 1; size = 0; update = 0; fp = 0;
2909 ic->f = NULL;
2910 switch (main_opcode) {
2911 case PPC_HI6_LBZ: load=1; break;
2912 case PPC_HI6_LBZU: load=1; update=1; break;
2913 case PPC_HI6_LHA: load=1; size=1; zero=0; break;
2914 case PPC_HI6_LHAU: load=1; size=1; zero=0; update=1; break;
2915 case PPC_HI6_LHZ: load=1; size=1; break;
2916 case PPC_HI6_LHZU: load=1; size=1; update=1; break;
2917 case PPC_HI6_LWZ: load=1; size=2; break;
2918 case PPC_HI6_LWZU: load=1; size=2; update=1; break;
2919 case PPC_HI6_LD: load=1; size=3; break;
2920 case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break;
2921 case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break;
2922 case PPC_HI6_STB: break;
2923 case PPC_HI6_STBU: update=1; break;
2924 case PPC_HI6_STH: size=1; break;
2925 case PPC_HI6_STHU: size=1; update=1; break;
2926 case PPC_HI6_STW: size=2; break;
2927 case PPC_HI6_STWU: size=2; update=1; break;
2928 case PPC_HI6_STD: size=3; break;
2929 case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;
2930 case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;
2931 }
2932 if (ic->f == NULL) {
2933 ic->f =
2934 #ifdef MODE32
2935 ppc32_loadstore
2936 #else
2937 ppc_loadstore
2938 #endif
2939 [size + 4*zero + 8*load + (imm==0? 16 : 0)
2940 + 32*update];
2941 }
2942 if (ra == 0 && update) {
2943 fatal("TODO: ra=0 && update?\n");
2944 goto bad;
2945 }
2946 if (fp)
2947 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
2948 else
2949 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
2950 if (ra == 0)
2951 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
2952 else
2953 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2954 ic->arg[2] = (ssize_t)imm;
2955 break;
2956
2957 case PPC_HI6_BC:
2958 aa_bit = (iword >> 1) & 1;
2959 lk_bit = iword & 1;
2960 bo = (iword >> 21) & 31;
2961 bi = (iword >> 16) & 31;
2962 tmp_addr = (int64_t)(int16_t)(iword & 0xfffc);
2963 if (aa_bit) {
2964 fatal("aa_bit: NOT YET\n");
2965 goto bad;
2966 }
2967 if (lk_bit) {
2968 ic->f = instr(bcl);
2969 samepage_function = instr(bcl_samepage);
2970 } else {
2971 ic->f = instr(bc);
2972 if ((bo & 0x14) == 0x04) {
2973 samepage_function = bo & 8?
2974 instr(bc_samepage_simple1) :
2975 instr(bc_samepage_simple0);
2976 } else
2977 samepage_function = instr(bc_samepage);
2978 }
2979 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2980 ic->arg[1] = bo;
2981 ic->arg[2] = 31-bi;
2982 /* Branches are calculated as cur PC + offset. */
2983 /* Special case: branch within the same page: */
2984 {
2985 uint64_t mask_within_page =
2986 ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2987 uint64_t old_pc = addr;
2988 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2989 if ((old_pc & ~mask_within_page) ==
2990 (new_pc & ~mask_within_page)) {
2991 ic->f = samepage_function;
2992 ic->arg[0] = (size_t) (
2993 cpu->cd.ppc.cur_ic_page +
2994 ((new_pc & mask_within_page) >> 2));
2995 }
2996 }
2997 break;
2998
2999 case PPC_HI6_SC:
3000 ic->arg[0] = (iword >> 5) & 0x7f;
3001 ic->arg[1] = (addr & 0xfff) + 4;
3002 if (cpu->machine->userland_emul != NULL)
3003 ic->f = instr(user_syscall);
3004 else if (iword == 0x44ee0002) {
3005 /* Special case/magic hack for OpenFirmware emul: */
3006 ic->f = instr(openfirmware);
3007 } else
3008 ic->f = instr(sc);
3009 break;
3010
3011 case PPC_HI6_B:
3012 aa_bit = (iword & 2) >> 1;
3013 lk_bit = iword & 1;
3014 tmp_addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
3015 tmp_addr = (int64_t)tmp_addr >> 6;
3016 if (lk_bit) {
3017 if (cpu->machine->show_trace_tree) {
3018 ic->f = instr(bl_trace);
3019 samepage_function = instr(bl_samepage_trace);
3020 } else {
3021 ic->f = instr(bl);
3022 samepage_function = instr(bl_samepage);
3023 }
3024 } else {
3025 ic->f = instr(b);
3026 samepage_function = instr(b_samepage);
3027 }
3028 ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
3029 ic->arg[1] = (addr & 0xffc) + 4;
3030 /* Branches are calculated as cur PC + offset. */
3031 /* Special case: branch within the same page: */
3032 {
3033 uint64_t mask_within_page =
3034 ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
3035 uint64_t old_pc = addr;
3036 uint64_t new_pc = old_pc + (int32_t)tmp_addr;
3037 if ((old_pc & ~mask_within_page) ==
3038 (new_pc & ~mask_within_page)) {
3039 ic->f = samepage_function;
3040 ic->arg[0] = (size_t) (
3041 cpu->cd.ppc.cur_ic_page +
3042 ((new_pc & mask_within_page) >> 2));
3043 }
3044 }
3045 if (aa_bit) {
3046 if (lk_bit) {
3047 if (cpu->machine->show_trace_tree) {
3048 ic->f = instr(bla_trace);
3049 } else {
3050 ic->f = instr(bla);
3051 }
3052 } else {
3053 ic->f = instr(ba);
3054 }
3055 ic->arg[0] = (ssize_t)tmp_addr;
3056 }
3057 break;
3058
3059 case PPC_HI6_19:
3060 xo = (iword >> 1) & 1023;
3061 switch (xo) {
3062
3063 case PPC_19_BCLR:
3064 case PPC_19_BCCTR:
3065 bo = (iword >> 21) & 31;
3066 bi = (iword >> 16) & 31;
3067 bh = (iword >> 11) & 3;
3068 lk_bit = iword & 1;
3069 if (xo == PPC_19_BCLR) {
3070 if (lk_bit)
3071 ic->f = instr(bclr_l);
3072 else {
3073 ic->f = instr(bclr);
3074 if (!cpu->machine->show_trace_tree &&
3075 (bo & 0x14) == 0x14)
3076 ic->f = instr(bclr_20);
3077 }
3078 } else {
3079 if (lk_bit)
3080 ic->f = instr(bcctr_l);
3081 else
3082 ic->f = instr(bcctr);
3083 }
3084 ic->arg[0] = bo;
3085 ic->arg[1] = 31 - bi;
3086 ic->arg[2] = bh;
3087 break;
3088
3089 case PPC_19_ISYNC:
3090 /* TODO */
3091 ic->f = instr(nop);
3092 break;
3093
3094 case PPC_19_RFI:
3095 ic->f = instr(rfi);
3096 break;
3097
3098 case PPC_19_RFID:
3099 ic->f = instr(rfid);
3100 break;
3101
3102 case PPC_19_MCRF:
3103 bf = (iword >> 23) & 7;
3104 bfa = (iword >> 18) & 7;
3105 ic->arg[0] = 28 - 4*bf;
3106 ic->arg[1] = 28 - 4*bfa;
3107 ic->f = instr(mcrf);
3108 break;
3109
3110 case PPC_19_CRAND:
3111 case PPC_19_CRANDC:
3112 case PPC_19_CREQV:
3113 case PPC_19_CROR:
3114 case PPC_19_CRORC:
3115 case PPC_19_CRNOR:
3116 case PPC_19_CRXOR:
3117 switch (xo) {
3118 case PPC_19_CRAND: ic->f = instr(crand); break;
3119 case PPC_19_CRANDC: ic->f = instr(crandc); break;
3120 case PPC_19_CREQV: ic->f = instr(creqv); break;
3121 case PPC_19_CROR: ic->f = instr(cror); break;
3122 case PPC_19_CRORC: ic->f = instr(crorc); break;
3123 case PPC_19_CRNOR: ic->f = instr(crnor); break;
3124 case PPC_19_CRXOR: ic->f = instr(crxor); break;
3125 }
3126 ic->arg[0] = iword;
3127 break;
3128
3129 default:goto bad;
3130 }
3131 break;
3132
3133 case PPC_HI6_RLWNM:
3134 case PPC_HI6_RLWINM:
3135 ra = (iword >> 16) & 31;
3136 mb = (iword >> 6) & 31;
3137 me = (iword >> 1) & 31;
3138 rc = iword & 1;
3139 mask = 0;
3140 for (;;) {
3141 mask |= ((uint32_t)0x80000000 >> mb);
3142 if (mb == me)
3143 break;
3144 mb ++; mb &= 31;
3145 }
3146 switch (main_opcode) {
3147 case PPC_HI6_RLWNM:
3148 ic->f = rc? instr(rlwnm_dot) : instr(rlwnm); break;
3149 case PPC_HI6_RLWINM:
3150 ic->f = rc? instr(rlwinm_dot) : instr(rlwinm); break;
3151 }
3152 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3153 ic->arg[1] = mask;
3154 ic->arg[2] = (uint32_t)iword;
3155 break;
3156
3157 case PPC_HI6_RLWIMI:
3158 rs = (iword >> 21) & 31;
3159 ra = (iword >> 16) & 31;
3160 ic->f = instr(rlwimi);
3161 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3162 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3163 ic->arg[2] = (uint32_t)iword;
3164 break;
3165
3166 case PPC_HI6_LMW:
3167 case PPC_HI6_STMW:
3168 /* NOTE: Loads use rt, not rs. */
3169 rs = (iword >> 21) & 31;
3170 ra = (iword >> 16) & 31;
3171 ic->arg[0] = rs;
3172 if (ra == 0)
3173 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3174 else
3175 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3176 ic->arg[2] = (int32_t)(int16_t)iword;
3177 switch (main_opcode) {
3178 case PPC_HI6_LMW:
3179 ic->f = instr(lmw);
3180 break;
3181 case PPC_HI6_STMW:
3182 ic->f = instr(stmw);
3183 break;
3184 }
3185 break;
3186
3187 case PPC_HI6_30:
3188 xo = (iword >> 2) & 7;
3189 switch (xo) {
3190
3191 case PPC_30_RLDICL:
3192 case PPC_30_RLDICR:
3193 case PPC_30_RLDIMI:
3194 switch (xo) {
3195 case PPC_30_RLDICL: ic->f = instr(rldicl); break;
3196 case PPC_30_RLDICR: ic->f = instr(rldicr); break;
3197 case PPC_30_RLDIMI: ic->f = instr(rldimi); break;
3198 }
3199 ic->arg[0] = iword;
3200 if (cpu->cd.ppc.bits == 32) {
3201 fatal("TODO: rld* in 32-bit mode?\n");
3202 goto bad;
3203 }
3204 break;
3205
3206 default:goto bad;
3207 }
3208 break;
3209
3210 case PPC_HI6_31:
3211 xo = (iword >> 1) & 1023;
3212 switch (xo) {
3213
3214 case PPC_31_CMPL:
3215 case PPC_31_CMP:
3216 bf = (iword >> 23) & 7;
3217 l_bit = (iword >> 21) & 1;
3218 ra = (iword >> 16) & 31;
3219 rb = (iword >> 11) & 31;
3220 if (xo == PPC_31_CMPL) {
3221 if (l_bit)
3222 ic->f = instr(cmpld);
3223 else
3224 ic->f = instr(cmplw);
3225 } else {
3226 if (l_bit)
3227 ic->f = instr(cmpd);
3228 else {
3229 if (bf == 0)
3230 ic->f = instr(cmpw_cr0);
3231 else
3232 ic->f = instr(cmpw);
3233 }
3234 }
3235 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3236 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3237 ic->arg[2] = 28 - 4*bf;
3238 break;
3239
3240 case PPC_31_CNTLZW:
3241 rs = (iword >> 21) & 31;
3242 ra = (iword >> 16) & 31;
3243 rc = iword & 1;
3244 if (rc) {
3245 fatal("TODO: rc\n");
3246 goto bad;
3247 }
3248 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3249 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3250 ic->f = instr(cntlzw);
3251 break;
3252
3253 case PPC_31_MFSPR:
3254 rt = (iword >> 21) & 31;
3255 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3256 debug_spr_usage(cpu->pc, spr);
3257 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3258 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3259 switch (spr) {
3260 case SPR_PMC1: ic->f = instr(mfspr_pmc1); break;
3261 default: ic->f = instr(mfspr);
3262 }
3263 break;
3264
3265 case PPC_31_MTSPR:
3266 rs = (iword >> 21) & 31;
3267 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3268 debug_spr_usage(cpu->pc, spr);
3269 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3270 ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3271 switch (spr) {
3272 case SPR_LR:
3273 ic->f = instr(mtlr);
3274 break;
3275 case SPR_CTR:
3276 ic->f = instr(mtctr);
3277 break;
3278 default:ic->f = instr(mtspr);
3279 }
3280 break;
3281
3282 case PPC_31_MFCR:
3283 rt = (iword >> 21) & 31;
3284 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3285 ic->f = instr(mfcr);
3286 break;
3287
3288 case PPC_31_MFMSR:
3289 rt = (iword >> 21) & 31;
3290 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3291 ic->f = instr(mfmsr);
3292 break;
3293
3294 case PPC_31_MTMSR:
3295 case PPC_31_MTMSRD:
3296 rs = (iword >> 21) & 31;
3297 l_bit = (iword >> 16) & 1;
3298 if (l_bit) {
3299 fatal("TODO: mtmsr l-bit\n");
3300 goto bad;
3301 }
3302 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3303 ic->arg[1] = (addr & 0xfff) + 4;
3304 ic->arg[2] = xo == PPC_31_MTMSRD;
3305 ic->f = instr(mtmsr);
3306 break;
3307
3308 case PPC_31_MTCRF:
3309 rs = (iword >> 21) & 31;
3310 {
3311 int i, fxm = (iword >> 12) & 255;
3312 uint32_t tmp = 0;
3313 for (i=0; i<8; i++, fxm <<= 1) {
3314 tmp <<= 4;
3315 if (fxm & 128)
3316 tmp |= 0xf;
3317 }
3318 ic->arg[1] = (uint32_t)tmp;
3319 }
3320 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3321 ic->f = instr(mtcrf);
3322 break;
3323
3324 case PPC_31_MFSRIN:
3325 case PPC_31_MTSRIN:
3326 rt = (iword >> 21) & 31;
3327 rb = (iword >> 11) & 31;
3328 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3329 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3330 switch (xo) {
3331 case PPC_31_MFSRIN: ic->f = instr(mfsrin); break;
3332 case PPC_31_MTSRIN: ic->f = instr(mtsrin); break;
3333 }
3334 if (cpu->cd.ppc.bits == 64) {
3335 fatal("Not yet for 64-bit mode\n");
3336 goto bad;
3337 }
3338 break;
3339
3340 case PPC_31_MFSR:
3341 case PPC_31_MTSR:
3342 rt = (iword >> 21) & 31;
3343 ic->arg[0] = (iword >> 16) & 15;
3344 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3345 switch (xo) {
3346 case PPC_31_MFSR: ic->f = instr(mfsr); break;
3347 case PPC_31_MTSR: ic->f = instr(mtsr); break;
3348 }
3349 if (cpu->cd.ppc.bits == 64) {
3350 fatal("Not yet for 64-bit mode\n");
3351 goto bad;
3352 }
3353 break;
3354
3355 case PPC_31_SRAWI:
3356 rs = (iword >> 21) & 31;
3357 ra = (iword >> 16) & 31;
3358 sh = (iword >> 11) & 31;
3359 rc = iword & 1;
3360 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3361 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3362 ic->arg[2] = sh;
3363 if (rc)
3364 ic->f = instr(srawi_dot);
3365 else
3366 ic->f = instr(srawi);
3367 break;
3368
3369 case PPC_31_SYNC:
3370 case PPC_31_DSSALL:
3371 case PPC_31_EIEIO:
3372 case PPC_31_DCBST:
3373 case PPC_31_DCBTST:
3374 case PPC_31_DCBF:
3375 case PPC_31_DCBT:
3376 case PPC_31_ICBI:
3377 ic->f = instr(nop);
3378 break;
3379
3380 case PPC_31_DCBZ:
3381 ra = (iword >> 16) & 31;
3382 rb = (iword >> 11) & 31;
3383 if (ra == 0)
3384 ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);
3385 else
3386 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3387 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3388 ic->arg[2] = addr & 0xfff;
3389 ic->f = instr(dcbz);
3390 break;
3391
3392 case PPC_31_TLBIA:
3393 ic->f = instr(tlbia);
3394 break;
3395
3396 case PPC_31_TLBSYNC:
3397 /* According to IBM, "Ensures that a tlbie and
3398 tlbia instruction executed by one processor has
3399 completed on all other processors.", which in
3400 GXemul means a nop :-) */
3401 ic->f = instr(nop);
3402 break;
3403
3404 case PPC_31_TLBIE:
3405 /* TODO: POWER also uses ra? */
3406 rb = (iword >> 11) & 31;
3407 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3408 ic->f = instr(tlbie);
3409 break;
3410
3411 case PPC_31_TLBLD: /* takes an arg */
3412 rb = (iword >> 11) & 31;
3413 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3414 ic->f = instr(tlbld);
3415 break;
3416
3417 case PPC_31_TLBLI: /* takes an arg */
3418 rb = (iword >> 11) & 31;
3419 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3420 ic->f = instr(tlbli);
3421 break;
3422
3423 case PPC_31_TLBSX_DOT:
3424 /* TODO */
3425 ic->f = instr(tlbsx_dot);
3426 break;
3427
3428 case PPC_31_MFTB:
3429 rt = (iword >> 21) & 31;
3430 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
3431 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3432 switch (spr) {
3433 case 268: ic->f = instr(mftb); break;
3434 case 269: ic->f = instr(mftbu); break;
3435 default:fatal("mftb spr=%i?\n", spr);
3436 goto bad;
3437 }
3438 break;
3439
3440 case PPC_31_NEG:
3441 rt = (iword >> 21) & 31;
3442 ra = (iword >> 16) & 31;
3443 rc = iword & 1;
3444 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3445 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3446 if (rc)
3447 ic->f = instr(neg_dot);
3448 else
3449 ic->f = instr(neg);
3450 break;
3451
3452 case PPC_31_LWARX:
3453 case PPC_31_LDARX:
3454 case PPC_31_STWCX_DOT:
3455 case PPC_31_STDCX_DOT:
3456 ic->arg[0] = iword;
3457 ic->f = instr(llsc);
3458 break;
3459
3460 case PPC_31_LSWI:
3461 case PPC_31_STSWI:
3462 rs = (iword >> 21) & 31;
3463 ra = (iword >> 16) & 31;
3464 nb = (iword >> 11) & 31;
3465 ic->arg[0] = rs;
3466 if (ra == 0)
3467 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3468 else
3469 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3470 ic->arg[2] = nb == 0? 32 : nb;
3471 switch (xo) {
3472 case PPC_31_LSWI: ic->f = instr(lswi); break;
3473 case PPC_31_STSWI: ic->f = instr(stswi); break;
3474 }
3475 break;
3476
3477 case PPC_31_WRTEEI:
3478 ic->arg[0] = iword & 0x8000;
3479 ic->f = instr(wrteei);
3480 break;
3481
3482 case 0x1c3:
3483 fatal("[ mtdcr: TODO ]\n");
3484 ic->f = instr(nop);
3485 break;
3486
3487 case PPC_31_LBZX:
3488 case PPC_31_LBZUX:
3489 case PPC_31_LHAX:
3490 case PPC_31_LHAUX:
3491 case PPC_31_LHZX:
3492 case PPC_31_LHZUX:
3493 case PPC_31_LWZX:
3494 case PPC_31_LWZUX:
3495 case PPC_31_LHBRX:
3496 case PPC_31_LWBRX:
3497 case PPC_31_LFDX:
3498 case PPC_31_LFSX:
3499 case PPC_31_STBX:
3500 case PPC_31_STBUX:
3501 case PPC_31_STHX:
3502 case PPC_31_STHUX:
3503 case PPC_31_STWX:
3504 case PPC_31_STWUX:
3505 case PPC_31_STDX:
3506 case PPC_31_STDUX:
3507 case PPC_31_STHBRX:
3508 case PPC_31_STWBRX:
3509 case PPC_31_STFDX:
3510 case PPC_31_STFSX:
3511 rs = (iword >> 21) & 31;
3512 ra = (iword >> 16) & 31;
3513 rb = (iword >> 11) & 31;
3514 if (ra == 0)
3515 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3516 else
3517 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3518 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3519 load = 0; zero = 1; size = 0; update = 0;
3520 byterev = 0; fp = 0;
3521 ic->f = NULL;
3522 switch (xo) {
3523 case PPC_31_LBZX: load = 1; break;
3524 case PPC_31_LBZUX: load=update=1; break;
3525 case PPC_31_LHAX: size=1; load=1; zero=0; break;
3526 case PPC_31_LHAUX: size=1; load=update=1; zero=0; break;
3527 case PPC_31_LHZX: size=1; load=1; break;
3528 case PPC_31_LHZUX: size=1; load=update = 1; break;
3529 case PPC_31_LWZX: size=2; load=1; break;
3530 case PPC_31_LWZUX: size=2; load=update = 1; break;
3531 case PPC_31_LHBRX: size=1; load=1; byterev=1;
3532 ic->f = instr(lhbrx); break;
3533 case PPC_31_LWBRX: size=2; load=1; byterev=1;
3534 ic->f = instr(lwbrx); break;
3535 case PPC_31_LFDX: size=3; load=1; fp=1;
3536 ic->f = instr(lfdx); break;
3537 case PPC_31_LFSX: size=2; load=1; fp=1;
3538 ic->f = instr(lfsx); break;
3539 case PPC_31_STBX: break;
3540 case PPC_31_STBUX: update = 1; break;
3541 case PPC_31_STHX: size=1; break;
3542 case PPC_31_STHUX: size=1; update = 1; break;
3543 case PPC_31_STWX: size=2; break;
3544 case PPC_31_STWUX: size=2; update = 1; break;
3545 case PPC_31_STDX: size=3; break;
3546 case PPC_31_STDUX: size=3; update = 1; break;
3547 case PPC_31_STHBRX:size=1; byterev = 1;
3548 ic->f = instr(sthbrx); break;
3549 case PPC_31_STWBRX:size=2; byterev = 1;
3550 ic->f = instr(stwbrx); break;
3551 case PPC_31_STFDX: size=3; fp=1;
3552 ic->f = instr(stfdx); break;
3553 case PPC_31_STFSX: size=2; fp=1;
3554 ic->f = instr(stfsx); break;
3555 }
3556 if (fp)
3557 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rs]);
3558 else
3559 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3560 if (!byterev && ic->f == NULL) {
3561 ic->f =
3562 #ifdef MODE32
3563 ppc32_loadstore_indexed
3564 #else
3565 ppc_loadstore_indexed
3566 #endif
3567 [size + 4*zero + 8*load + 16*update];
3568 }
3569 if (ra == 0 && update) {
3570 fatal("TODO: ra=0 && update?\n");
3571 goto bad;
3572 }
3573 break;
3574
3575 case PPC_31_EXTSB:
3576 case PPC_31_EXTSH:
3577 case PPC_31_EXTSW:
3578 case PPC_31_SLW:
3579 case PPC_31_SLD:
3580 case PPC_31_SRAW:
3581 case PPC_31_SRW:
3582 case PPC_31_AND:
3583 case PPC_31_NAND:
3584 case PPC_31_ANDC:
3585 case PPC_31_NOR:
3586 case PPC_31_OR:
3587 case PPC_31_ORC:
3588 case PPC_31_XOR:
3589 case PPC_31_EQV:
3590 rs = (iword >> 21) & 31;
3591 ra = (iword >> 16) & 31;
3592 rb = (iword >> 11) & 31;
3593 rc = iword & 1;
3594 rc_f = NULL;
3595 switch (xo) {
3596 case PPC_31_EXTSB:ic->f = instr(extsb);
3597 rc_f = instr(extsb_dot); break;
3598 case PPC_31_EXTSH:ic->f = instr(extsh);
3599 rc_f = instr(extsh_dot); break;
3600 case PPC_31_EXTSW:ic->f = instr(extsw);
3601 rc_f = instr(extsw_dot); break;
3602 case PPC_31_SLW: ic->f = instr(slw);
3603 rc_f = instr(slw_dot); break;
3604 case PPC_31_SLD: ic->f = instr(sld);
3605 rc_f = instr(sld_dot); break;
3606 case PPC_31_SRAW: ic->f = instr(sraw);
3607 rc_f = instr(sraw_dot); break;
3608 case PPC_31_SRW: ic->f = instr(srw);
3609 rc_f = instr(srw_dot); break;
3610 case PPC_31_AND: ic->f = instr(and);
3611 rc_f = instr(and_dot); break;
3612 case PPC_31_NAND: ic->f = instr(nand);
3613 rc_f = instr(nand_dot); break;
3614 case PPC_31_ANDC: ic->f = instr(andc);
3615 rc_f = instr(andc_dot); break;
3616 case PPC_31_NOR: ic->f = instr(nor);
3617 rc_f = instr(nor_dot); break;
3618 case PPC_31_OR: ic->f = rs == rb? instr(mr)
3619 : instr(or);
3620 rc_f = instr(or_dot); break;
3621 case PPC_31_ORC: ic->f = instr(orc);
3622 rc_f = instr(orc_dot); break;
3623 case PPC_31_XOR: ic->f = instr(xor);
3624 rc_f = instr(xor_dot); break;
3625 case PPC_31_EQV: ic->f = instr(eqv);
3626 rc_f = instr(eqv_dot); break;
3627 }
3628 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3629 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3630 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3631 if (rc)
3632 ic->f = rc_f;
3633 break;
3634
3635 case PPC_31_MULLW:
3636 case PPC_31_MULHW:
3637 case PPC_31_MULHWU:
3638 case PPC_31_DIVW:
3639 case PPC_31_DIVWU:
3640 case PPC_31_ADD:
3641 case PPC_31_ADDC:
3642 case PPC_31_ADDE:
3643 case PPC_31_ADDME:
3644 case PPC_31_ADDZE:
3645 case PPC_31_SUBF:
3646 case PPC_31_SUBFC:
3647 case PPC_31_SUBFE:
3648 case PPC_31_SUBFME:
3649 case PPC_31_SUBFZE:
3650 rt = (iword >> 21) & 31;
3651 ra = (iword >> 16) & 31;
3652 rb = (iword >> 11) & 31;
3653 oe_bit = (iword >> 10) & 1;
3654 rc = iword & 1;
3655 if (oe_bit) {
3656 fatal("oe_bit not yet implemented\n");
3657 goto bad;
3658 }
3659 switch (xo) {
3660 case PPC_31_MULLW: ic->f = instr(mullw); break;
3661 case PPC_31_MULHW: ic->f = instr(mulhw); break;
3662 case PPC_31_MULHWU: ic->f = instr(mulhwu); break;
3663 case PPC_31_DIVW: ic->f = instr(divw); n64=1; break;
3664 case PPC_31_DIVWU: ic->f = instr(divwu); n64=1; break;
3665 case PPC_31_ADD: ic->f = instr(add); break;
3666 case PPC_31_ADDC: ic->f = instr(addc); n64=1; break;
3667 case PPC_31_ADDE: ic->f = instr(adde); n64=1; break;
3668 case PPC_31_ADDME: ic->f = instr(addme); n64=1; break;
3669 case PPC_31_ADDZE: ic->f = instr(addze); n64=1; break;
3670 case PPC_31_SUBF: ic->f = instr(subf); break;
3671 case PPC_31_SUBFC: ic->f = instr(subfc); break;
3672 case PPC_31_SUBFE: ic->f = instr(subfe); n64=1; break;
3673 case PPC_31_SUBFME: ic->f = instr(subfme); n64=1; break;
3674 case PPC_31_SUBFZE: ic->f = instr(subfze); n64=1;break;
3675 }
3676 if (rc) {
3677 switch (xo) {
3678 case PPC_31_ADD:
3679 ic->f = instr(add_dot); break;
3680 case PPC_31_ADDE:
3681 ic->f = instr(adde_dot); break;
3682 case PPC_31_ADDME:
3683 ic->f = instr(addme_dot); break;
3684 case PPC_31_ADDZE:
3685 ic->f = instr(addze_dot); break;
3686 case PPC_31_DIVW:
3687 ic->f = instr(divw_dot); break;
3688 case PPC_31_DIVWU:
3689 ic->f = instr(divwu_dot); break;
3690 case PPC_31_MULLW:
3691 ic->f = instr(mullw_dot); break;
3692 case PPC_31_MULHW:
3693 ic->f = instr(mulhw_dot); break;
3694 case PPC_31_MULHWU:
3695 ic->f = instr(mulhwu_dot); break;
3696 case PPC_31_SUBF:
3697 ic->f = instr(subf_dot); break;
3698 case PPC_31_SUBFC:
3699 ic->f = instr(subfc_dot); break;
3700 case PPC_31_SUBFE:
3701 ic->f = instr(subfe_dot); break;
3702 case PPC_31_SUBFME:
3703 ic->f = instr(subfme_dot); break;
3704 case PPC_31_SUBFZE:
3705 ic->f = instr(subfze_dot); break;
3706 default:fatal("RC bit not yet implemented\n");
3707 goto bad;
3708 }
3709 }
3710 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3711 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3712 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
3713 if (cpu->cd.ppc.bits == 64 && n64) {
3714 fatal("Not yet for 64-bit mode\n");
3715 goto bad;
3716 }
3717 break;
3718
3719 case PPC_31_LVX:
3720 case PPC_31_LVXL:
3721 case PPC_31_STVX:
3722 case PPC_31_STVXL:
3723 load = 0;
3724 switch (xo) {
3725 case PPC_31_LVX:
3726 case PPC_31_LVXL:
3727 load = 1; break;
3728 }
3729 rs = (iword >> 21) & 31;
3730 ra = (iword >> 16) & 31;
3731 rb = (iword >> 11) & 31;
3732 ic->arg[0] = rs;
3733 if (ra == 0)
3734 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3735 else
3736 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3737 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3738 ic->f = load? instr(lvx) : instr(stvx);
3739 break;
3740
3741 default:goto bad;
3742 }
3743 break;
3744
3745 case PPC_HI6_59:
3746 xo = (iword >> 1) & 1023;
3747 rt = (iword >> 21) & 31;
3748 ra = (iword >> 16) & 31;
3749 rb = (iword >> 11) & 31;
3750 rs = (iword >> 6) & 31; /* actually frc */
3751 rc = iword & 1;
3752
3753 if (rc) {
3754 fatal("Floating point (59) with rc bit! TODO\n");
3755 goto bad;
3756 }
3757
3758 /* NOTE: Some floating-point instructions are selected
3759 using only the lowest 5 bits, not all 10! */
3760 switch (xo & 31) {
3761 case PPC_59_FDIVS:
3762 case PPC_59_FSUBS:
3763 case PPC_59_FADDS:
3764 switch (xo & 31) {
3765 case PPC_59_FDIVS: ic->f = instr(fdivs); break;
3766 case PPC_59_FSUBS: ic->f = instr(fsubs); break;
3767 case PPC_59_FADDS: ic->f = instr(fadds); break;
3768 }
3769 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3770 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3771 ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3772 break;
3773 case PPC_59_FMULS:
3774 ic->f = instr(fmuls);
3775 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3776 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3777 ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3778 break;
3779 default:/* Use all 10 bits of xo: */
3780 switch (xo) {
3781 default:goto bad;
3782 }
3783 }
3784 break;
3785
3786 case PPC_HI6_63:
3787 xo = (iword >> 1) & 1023;
3788 rt = (iword >> 21) & 31;
3789 ra = (iword >> 16) & 31;
3790 rb = (iword >> 11) & 31;
3791 rs = (iword >> 6) & 31; /* actually frc */
3792 rc = iword & 1;
3793
3794 if (rc) {
3795 fatal("Floating point (63) with rc bit! TODO\n");
3796 goto bad;
3797 }
3798
3799 /* NOTE: Some floating-point instructions are selected
3800 using only the lowest 5 bits, not all 10! */
3801 switch (xo & 31) {
3802 case PPC_63_FDIV:
3803 case PPC_63_FSUB:
3804 case PPC_63_FADD:
3805 switch (xo & 31) {
3806 case PPC_63_FDIV: ic->f = instr(fdiv); break;
3807 case PPC_63_FSUB: ic->f = instr(fsub); break;
3808 case PPC_63_FADD: ic->f = instr(fadd); break;
3809 }
3810 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3811 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3812 ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3813 break;
3814 case PPC_63_FMUL:
3815 ic->f = instr(fmul);
3816 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3817 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3818 ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rs]); /* frc */
3819 break;
3820 case PPC_63_FMSUB:
3821 case PPC_63_FMADD:
3822 switch (xo & 31) {
3823 case PPC_63_FMSUB: ic->f = instr(fmsub); break;
3824 case PPC_63_FMADD: ic->f = instr(fmadd); break;
3825 }
3826 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3827 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3828 ic->arg[2] = iword;
3829 break;
3830 default:/* Use all 10 bits of xo: */
3831 switch (xo) {
3832 case PPC_63_FCMPU:
3833 ic->f = instr(fcmpu);
3834 ic->arg[0] = 28 - 4*(rt >> 2);
3835 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[ra]);
3836 ic->arg[2] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3837 break;
3838 case PPC_63_FRSP:
3839 case PPC_63_FCTIWZ:
3840 case PPC_63_FNEG:
3841 case PPC_63_FMR:
3842 switch (xo) {
3843 case PPC_63_FRSP: ic->f = instr(frsp); break;
3844 case PPC_63_FCTIWZ: ic->f = instr(fctiwz);break;
3845 case PPC_63_FNEG: ic->f = instr(fneg); break;
3846 case PPC_63_FMR: ic->f = instr(fmr); break;
3847 }
3848 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3849 ic->arg[1] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3850 break;
3851 case PPC_63_MFFS:
3852 ic->f = instr(mffs);
3853 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rt]);
3854 break;
3855 case PPC_63_MTFSF:
3856 ic->f = instr(mtfsf);
3857 ic->arg[0] = (size_t)(&cpu->cd.ppc.fpr[rb]);
3858 ic->arg[1] = 0;
3859 for (bi=7; bi>=0; bi--) {
3860 ic->arg[1] <<= 8;
3861 if (iword & (1 << (17+bi)))
3862 ic->arg[1] |= 0xf;
3863 }
3864 break;
3865 default:goto bad;
3866 }
3867 }
3868 break;
3869
3870 default:goto bad;
3871 }
3872
3873
3874 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3875 #include "cpu_dyntrans.c"
3876 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3877 }
3878

  ViewVC Help
Powered by ViewVC 1.1.26