2 # This file is part of the program psim.
4 # Copyright 1994, 1995, 1996, 1997, 2003, 2004 Andrew Cagney
8 # The pseudo-code that appears below, translated into C, was copied
9 # by Andrew Cagney of Moss Vale, Australia.
11 # This pseudo-code is copied by permission from the publication
12 # "The PowerPC Architecture: A Specification for A New Family of
13 # RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by
14 # International Business Machines Corporation.
16 # THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER
17 # EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
18 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 # This program is free software; you can redistribute it and/or modify
23 # it under the terms of the GNU General Public License as published by
24 # the Free Software Foundation; either version 2 of the License, or
25 # (at your option) any later version.
27 # This program is distributed in the hope that it will be useful,
28 # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 # GNU General Public License for more details.
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 :cache:::signed_word *:rA:RA:(cpu_registers(processor)->gpr + RA)
39 :cache:::unsigned32:RA_BITMASK:RA:(1 << RA)
40 :compute:::int:RA_is_0:RA:(RA == 0)
42 :cache:::signed_word *:rT:RT:(cpu_registers(processor)->gpr + RT)
43 :cache:::unsigned32:RT_BITMASK:RT:(1 << RT)
45 :cache:::signed_word *:rS:RS:(cpu_registers(processor)->gpr + RS)
46 :cache:::unsigned32:RS_BITMASK:RS:(1 << RS)
48 :cache:::signed_word *:rB:RB:(cpu_registers(processor)->gpr + RB)
49 :cache:::unsigned32:RB_BITMASK:RB:(1 << RB)
51 :cache:::unsigned64 *:frA:FRA:(cpu_registers(processor)->fpr + FRA)
52 :cache:::unsigned32:FRA_BITMASK:FRA:(1 << FRA)
54 :cache:::unsigned64 *:frB:FRB:(cpu_registers(processor)->fpr + FRB)
55 :cache:::unsigned32:FRB_BITMASK:FRB:(1 << FRB)
57 :cache:::unsigned64 *:frC:FRC:(cpu_registers(processor)->fpr + FRC)
58 :cache:::unsigned32:FRC_BITMASK:FRC:(1 << FRC)
60 :cache:::unsigned64 *:frS:FRS:(cpu_registers(processor)->fpr + FRS)
61 :cache:::unsigned32:FRS_BITMASK:FRS:(1 << FRS)
63 :cache:::unsigned64 *:frT:FRT:(cpu_registers(processor)->fpr + FRT)
64 :cache:::unsigned32:FRT_BITMASK:FRT:(1 << FRT)
65 :cache:::unsigned_word:EXTS_SI:SI:((signed_word)(signed16)instruction)
67 :cache::::BIT32_BI:BI:BIT32(BI)
69 :cache:::unsigned32:BF_BITMASK:BF:(1 << BF)
71 :cache::::BIT32_BA:BA:BIT32(BA)
72 :cache:::unsigned32:BA_BITMASK:BA:(1 << BA)
74 :cache::::BIT32_BB:BB:BIT32(BB)
75 :cache:::unsigned32:BB_BITMASK:BB:(1 << BB)
77 :cache:::unsigned32:BT_BITMASK:BT:(1 << BT)
78 :cache:::unsigned_word:EXTS_BD_0b00:BD:(((signed_word)(signed16)instruction) & ~3)
79 :cache:::unsigned_word:EXTS_LI_0b00:LI:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
80 :cache:::unsigned_word:EXTS_D:D:((signed_word)(signed16)(instruction))
81 :cache:::unsigned_word:EXTS_DS_0b00:DS:(((signed_word)(signed16)instruction) & ~0x3)
82 #:compute:::int:SPR_is_256:SPR:(SPR == 256)
85 ::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
86 ::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
87 ::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
88 ::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
92 #define PPC_INSN_INT(OUT_MASK, IN_MASK, RC) \
94 if (CURRENT_MODEL_ISSUE > 0) { \
96 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
98 ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
102 #define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
104 if (CURRENT_MODEL_ISSUE > 0) \
105 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
108 #define PPC_INSN_CR(OUT_MASK, IN_MASK) \
110 if (CURRENT_MODEL_ISSUE > 0) \
111 ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
114 #define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
116 if (CURRENT_MODEL_ISSUE > 0) { \
118 ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
120 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
124 #define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
126 if (CURRENT_MODEL_ISSUE > 0) \
127 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
130 #define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
132 if (CURRENT_MODEL_ISSUE > 0) \
133 ppc_insn_int_float(MY_INDEX, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
136 #define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
138 if (CURRENT_MODEL_ISSUE > 0) \
139 ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
142 #define PPC_INSN_TO_SPR(INT_MASK, SPR) \
144 if (CURRENT_MODEL_ISSUE > 0) \
145 ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
148 #define PPC_INSN_MFCR(INT_MASK) \
150 if (CURRENT_MODEL_ISSUE > 0) \
151 ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
154 #define PPC_INSN_MTCR(INT_MASK, FXM) \
156 if (CURRENT_MODEL_ISSUE > 0) \
157 ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
161 typedef enum _ppc_function_unit {
162 PPC_UNIT_BAD, /* unknown function unit */
163 PPC_UNIT_IU, /* integer unit (601/603 style) */
164 PPC_UNIT_SRU, /* system register unit (601/603 style) */
165 PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
166 PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
167 PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
168 PPC_UNIT_FPU, /* floating point unit */
169 PPC_UNIT_LSU, /* load/store unit */
170 PPC_UNIT_BPU, /* branch unit */
171 nr_ppc_function_units
174 /* Structure to hold timing information on a per instruction basis */
176 ppc_function_unit first_unit; /* first functional unit this insn could use */
177 ppc_function_unit second_unit; /* second functional unit this insn could use */
178 signed16 issue; /* # cycles before function unit can process other insns */
179 signed16 done; /* # cycles before insn is done */
180 unsigned32 flags; /* any flags that are needed */
183 /* Register mappings in status masks */
184 #define PPC_CR_REG 0 /* start of CR0 .. CR7 */
185 #define PPC_FPSCR_REG (PPC_CR_REG + 8) /* start of fpscr register */
187 #define PPC_NO_SPR (-1) /* flag for no SPR register */
189 /* Return if 1 bit set */
190 #define PPC_ONE_BIT_SET_P(x) (((x) & ((x)-1)) == 0)
192 /* Structure for each functional unit that is busy */
193 typedef struct _model_busy model_busy;
195 model_busy *next; /* next function unit */
196 ppc_function_unit unit; /* function unit name */
197 unsigned32 int_busy; /* int registers that are busy */
198 unsigned32 fp_busy; /* floating point registers that are busy */
199 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
200 signed16 spr_busy; /* SPR register that is busy or PPC_NO_SPR */
201 unsigned32 vr_busy; /* AltiVec registers that are busy */
202 signed16 vscr_busy; /* AltiVec status register busy */
203 signed16 issue; /* # of cycles until unit can accept another insn */
204 signed16 done; /* # of cycles until insn is done */
205 signed16 nr_writebacks; /* # of registers this unit writes back */
208 /* Structure to hold the current state information for the simulated CPU model */
210 cpu *processor; /* point back to processor */
211 const char *name; /* model name */
212 const model_time *timing; /* timing information */
213 model_busy busy_head; /* dummy entry to head list of busy function units */
214 model_busy *busy_tail; /* tail of list of busy function units */
215 model_busy *free_list; /* list of model_busy structs not in use */
216 count_type nr_cycles; /* # cycles */
217 count_type nr_branches; /* # branches */
218 count_type nr_branches_fallthrough; /* # conditional branches that fell through */
219 count_type nr_branch_predict_trues; /* # branches predicted correctly */
220 count_type nr_branch_predict_falses; /* # branches predicted incorrectly */
221 count_type nr_branch_conditional[32]; /* # of each type of bc */
222 count_type nr_mtcrf_crs[9]; /* # of CR's moved in a mtcrf instruction */
223 count_type nr_stalls_data; /* # of stalls for data */
224 count_type nr_stalls_unit; /* # of stalls waiting for a function unit */
225 count_type nr_stalls_serialize; /* # of stalls waiting for things to quiet down */
226 count_type nr_stalls_writeback; /* # of stalls waiting for a writeback slot */
227 count_type nr_units[nr_ppc_function_units]; /* function unit counts */
228 int max_nr_writebacks; /* max # of writeback slots available */
229 unsigned32 int_busy; /* int registers that are busy */
230 unsigned32 fp_busy; /* floating point registers that are busy */
231 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
232 unsigned8 spr_busy[nr_of_sprs]; /* SPR registers that are busy */
233 unsigned32 vr_busy; /* AltiVec registers that are busy */
234 unsigned8 vscr_busy; /* AltiVec SC register busy */
235 unsigned8 busy[nr_ppc_function_units]; /* whether a function is busy or not */
238 static const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
239 "unknown functional unit instruction",
240 "integer functional unit instruction",
241 "system register functional unit instruction",
242 "1st single cycle integer functional unit instruction",
243 "2nd single cycle integer functional unit instruction",
244 "multiple cycle integer functional unit instruction",
245 "floating point functional unit instruction",
246 "load/store functional unit instruction",
247 "branch functional unit instruction",
250 static const char *const ppc_branch_conditional_name[32] = {
251 "branch if --CTR != 0 and condition is FALSE", /* 0000y */
252 "branch if --CTR != 0 and condition is FALSE, reverse branch likely",
253 "branch if --CTR == 0 and condition is FALSE", /* 0001y */
254 "branch if --CTR == 0 and condition is FALSE, reverse branch likely",
255 "branch if the condition is FALSE", /* 001zy */
256 "branch if the condition is FALSE, reverse branch likely",
257 "branch if the condition is FALSE (ignored bit 1 set to 1)", /* 001zy */
258 "branch if the condition is FALSE, reverse branch likely (ignored bit 4 set to 1)",
259 "branch if --CTR != 0 and condition is TRUE", /* 0100y */
260 "branch if --CTR != 0 and condition is TRUE, reverse branch likely",
261 "branch if --CTR == 0 and condition is TRUE", /* 0101y */
262 "branch if --CTR == 0 and condition is TRUE, reverse branch likely",
263 "branch if the condition is TRUE", /* 011zy */
264 "branch if the condition is TRUE, reverse branch likely",
265 "branch if the condition is TRUE (ignored bit 1 set to 1)", /* 011zy */
266 "branch if the condition is TRUE, reverse branch likely (ignored bit 4 set to 1)",
267 "branch if --CTR != 0", /* 1z00y */
268 "branch if --CTR != 0, reverse branch likely",
269 "branch if --CTR == 0", /* 1z01y */
270 "branch if --CTR == 0, reverse branch likely",
271 "branch always", /* 1z1zz */
272 "branch always (ignored bit 5 set to 1)",
273 "branch always (ignored bit 4 set to 1)", /* 1z1zz */
274 "branch always (ignored bits 4,5 set to 1)",
275 "branch if --CTR != 0 (ignored bit 1 set to 1)", /* 1z00y */
276 "branch if --CTR != 0, reverse branch likely (ignored bit 1 set to 1)",
277 "branch if --CTR == 0 (ignored bit 1 set to 1)", /* 1z01y */
278 "branch if --CTR == 0, reverse branch likely (ignored bit 1 set to 1)",
279 "branch always (ignored bit 1 set to 1)", /* 1z1zz */
280 "branch always (ignored bits 1,5 set to 1)",
281 "branch always (ignored bits 1,4 set to 1)", /* 1z1zz */
282 "branch always (ignored bits 1,4,5 set to 1)",
285 static const char *const ppc_nr_mtcrf_crs[9] = {
286 "mtcrf moving 0 CRs",
288 "mtcrf moving 2 CRs",
289 "mtcrf moving 3 CRs",
290 "mtcrf moving 4 CRs",
291 "mtcrf moving 5 CRs",
292 "mtcrf moving 6 CRs",
293 "mtcrf moving 7 CRs",
294 "mtcrf moving all CRs",
297 # Trace releasing resources
298 void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
300 TRACE(trace_model,("done, %s, %d writeback%s\n", ppc_function_unit_name[busy->unit],
301 busy->nr_writebacks, busy->nr_writebacks == 1 ? "" : "s"));
302 if (busy->int_busy) {
303 for(i = 0; i < 32; i++) {
304 if (((1 << i) & busy->int_busy) != 0) {
305 TRACE(trace_model, ("Register r%d is now available.\n", i));
310 for(i = 0; i < 32; i++) {
311 if (((1 << i) & busy->fp_busy) != 0) {
312 TRACE(trace_model, ("Register f%d is now available.\n", i));
316 if (busy->cr_fpscr_busy) {
317 for(i = 0; i < 8; i++) {
318 if (((1 << i) & busy->cr_fpscr_busy) != 0) {
319 TRACE(trace_model, ("Register cr%d is now available.\n", i));
322 if (busy->cr_fpscr_busy & 0x100)
323 TRACE(trace_model, ("Register fpscr is now available.\n"));
325 if (busy->spr_busy != PPC_NO_SPR)
326 TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
328 for(i = 0; i < 32; i++) {
329 if (((1 << i) & busy->vr_busy) != 0) {
330 TRACE(trace_model, ("Register v%d is now available.\n", i));
335 TRACE(trace_model, ("VSCR Register is now available.\n", spr_name(busy->spr_busy)));
337 # Trace making registers busy
338 void::model-static::model_trace_make_busy:model_data *model_ptr, unsigned32 int_mask, unsigned32 fp_mask, unsigned32 cr_mask
341 for(i = 0; i < 32; i++) {
342 if (((1 << i) & int_mask) != 0) {
343 TRACE(trace_model, ("Register r%d is now busy.\n", i));
348 for(i = 0; i < 32; i++) {
349 if (((1 << i) & fp_mask) != 0) {
350 TRACE(trace_model, ("Register f%d is now busy.\n", i));
355 for(i = 0; i < 8; i++) {
356 if (((1 << i) & cr_mask) != 0) {
357 TRACE(trace_model, ("Register cr%d is now busy.\n", i));
362 # Trace waiting for registers to become available
363 void::model-static::model_trace_busy_p:model_data *model_ptr, unsigned32 int_busy, unsigned32 fp_busy, unsigned32 cr_or_fpscr_busy, int spr_busy
366 int_busy &= model_ptr->int_busy;
367 for(i = 0; i < 32; i++) {
368 if (((1 << i) & int_busy) != 0) {
369 TRACE(trace_model, ("Waiting for register r%d.\n", i));
374 fp_busy &= model_ptr->fp_busy;
375 for(i = 0; i < 32; i++) {
376 if (((1 << i) & fp_busy) != 0) {
377 TRACE(trace_model, ("Waiting for register f%d.\n", i));
381 if (cr_or_fpscr_busy) {
382 cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy;
383 for(i = 0; i < 8; i++) {
384 if (((1 << i) & cr_or_fpscr_busy) != 0) {
385 TRACE(trace_model, ("Waiting for register cr%d.\n", i));
388 if (cr_or_fpscr_busy & 0x100)
389 TRACE(trace_model, ("Waiting for register fpscr.\n"));
391 if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy])
392 TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));
394 # Advance state to next cycle, releasing any registers allocated
395 void::model-internal::model_new_cycle:model_data *model_ptr
396 model_busy *cur_busy = model_ptr->busy_head.next;
397 model_busy *free_list = model_ptr->free_list;
398 model_busy *busy_tail = &model_ptr->busy_head;
399 int nr_writebacks = model_ptr->max_nr_writebacks;
402 model_ptr->nr_cycles++;
403 TRACE(trace_model,("New cycle %lu\n", (unsigned long)model_ptr->nr_cycles));
404 for ( ; cur_busy; cur_busy = next) {
405 next = cur_busy->next;
406 if (--cur_busy->done <= 0) { /* function unit done, release registers if we have writeback slots */
407 nr_writebacks -= cur_busy->nr_writebacks;
408 if (nr_writebacks >= 0) {
409 model_ptr->int_busy &= ~cur_busy->int_busy;
410 model_ptr->fp_busy &= ~cur_busy->fp_busy;
411 model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy;
412 if (cur_busy->spr_busy != PPC_NO_SPR)
413 model_ptr->spr_busy[cur_busy->spr_busy] = 0;
414 model_ptr->vr_busy &= ~cur_busy->vr_busy;
415 model_ptr->vscr_busy = ~cur_busy->vscr_busy;
417 if (WITH_TRACE && ppc_trace[trace_model])
418 model_trace_release(model_ptr, cur_busy);
420 model_ptr->busy[cur_busy->unit] = 0;
421 cur_busy->next = free_list;
422 free_list = cur_busy;
424 else { /* writeback slots not available */
425 TRACE(trace_model,("%d writeback slot%s not available for %s\n",
426 cur_busy->nr_writebacks,
427 cur_busy->nr_writebacks == 1 ? " is" : "s are",
428 ppc_function_unit_name[cur_busy->unit]));
429 cur_busy->done++; /* undo -- above */
430 model_ptr->nr_stalls_writeback++;
431 busy_tail->next = cur_busy;
432 busy_tail = cur_busy;
435 else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
436 TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
437 model_ptr->busy[cur_busy->unit] = 0;
438 busy_tail->next = cur_busy;
439 busy_tail = cur_busy;
442 TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
443 ppc_function_unit_name[cur_busy->unit],
446 busy_tail->next = cur_busy;
447 busy_tail = cur_busy;
451 busy_tail->next = (model_busy *)0;
452 model_ptr->busy_tail = busy_tail;
453 model_ptr->free_list = free_list;
455 # Mark a function unit as busy, return the busy structure
456 model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
459 TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
461 if (!model_ptr->free_list) {
462 busy = ZALLOC(model_busy);
465 busy = model_ptr->free_list;
466 model_ptr->free_list = busy->next;
467 busy->next = (model_busy *)0;
470 busy->cr_fpscr_busy = 0;
471 busy->nr_writebacks = 0;
479 busy->spr_busy = PPC_NO_SPR;
480 model_ptr->busy_tail->next = busy;
481 model_ptr->busy_tail = busy;
482 model_ptr->busy[unit] = 1;
483 model_ptr->nr_units[unit]++;
486 # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
487 model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
488 ppc_function_unit first_unit = time_ptr->first_unit;
489 ppc_function_unit second_unit = time_ptr->second_unit;
490 int stall_increment = 0;
493 if (!model_ptr->busy[first_unit])
494 return model_make_busy(model_ptr, first_unit,
495 model_ptr->timing[index].issue,
496 model_ptr->timing[index].done);
498 if (!model_ptr->busy[second_unit])
499 return model_make_busy(model_ptr, second_unit,
500 model_ptr->timing[index].issue,
501 model_ptr->timing[index].done);
503 TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
504 model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
506 model_new_cycle(model_ptr);
509 # Serialize the processor, waiting for all instructions to drain out before adding an instruction.
510 void::model-function::model_serialize:itable_index index, model_data *model_ptr
511 while (model_ptr->busy_head.next) {
512 TRACE(trace_model,("waiting for pipeline to empty\n"));
513 model_ptr->nr_stalls_serialize++;
514 model_new_cycle(model_ptr);
516 (void) model_make_busy(model_ptr,
517 model_ptr->timing[index].first_unit,
518 model_ptr->timing[index].issue,
519 model_ptr->timing[index].done);
521 # Wait for a CR to become unbusy
522 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
526 for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
529 cr_mask = (1 << cr_var);
530 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
531 TRACE(trace_model,("waiting for CR %d\n", cr_var));
532 model_ptr->nr_stalls_data++;
533 model_new_cycle(model_ptr);
536 # Schedule an instruction that takes integer input registers and produces output registers
537 void::model-function::ppc_insn_int:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
538 const unsigned32 int_mask = out_mask | in_mask;
539 model_busy *busy_ptr;
541 if ((model_ptr->int_busy & int_mask) != 0) {
542 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
544 while ((model_ptr->int_busy & int_mask) != 0) {
545 if (WITH_TRACE && ppc_trace[trace_model])
546 model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
548 model_ptr->nr_stalls_data++;
549 model_new_cycle(model_ptr);
553 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
554 model_ptr->int_busy |= out_mask;
555 busy_ptr->int_busy |= out_mask;
557 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
559 if (WITH_TRACE && ppc_trace[trace_model])
560 model_trace_make_busy(model_ptr, out_mask, 0, 0);
562 # Schedule an instruction that takes integer input registers and produces output registers & sets a CR register
563 void::model-function::ppc_insn_int_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
564 const unsigned32 int_mask = out_mask | in_mask;
565 model_busy *busy_ptr;
567 if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
568 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
570 while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
571 if (WITH_TRACE && ppc_trace[trace_model])
572 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
574 model_ptr->nr_stalls_data++;
575 model_new_cycle(model_ptr);
579 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
580 model_ptr->int_busy |= out_mask;
581 busy_ptr->int_busy |= out_mask;
582 model_ptr->cr_fpscr_busy |= cr_mask;
583 busy_ptr->cr_fpscr_busy |= cr_mask;
585 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
588 busy_ptr->nr_writebacks++;
590 if (WITH_TRACE && ppc_trace[trace_model])
591 model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);
594 # Schedule an instruction that takes CR input registers and produces output CR registers
595 void::model-function::ppc_insn_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
596 const unsigned32 cr_mask = out_mask | in_mask;
597 model_busy *busy_ptr;
599 if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
600 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
602 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
603 if (WITH_TRACE && ppc_trace[trace_model])
604 model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
606 model_ptr->nr_stalls_data++;
607 model_new_cycle(model_ptr);
611 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
612 model_ptr->cr_fpscr_busy |= out_mask;
613 busy_ptr->cr_fpscr_busy |= out_mask;
615 busy_ptr->nr_writebacks = 1;
617 if (WITH_TRACE && ppc_trace[trace_model])
618 model_trace_make_busy(model_ptr, 0, 0, out_mask);
621 # Schedule an instruction that takes floating point input registers and produces an output fp register
622 void::model-function::ppc_insn_float:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
623 const unsigned32 fp_mask = out_mask | in_mask;
624 model_busy *busy_ptr;
626 if ((model_ptr->fp_busy & fp_mask) != 0) {
627 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
629 while ((model_ptr->fp_busy & fp_mask) != 0) {
630 if (WITH_TRACE && ppc_trace[trace_model])
631 model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
633 model_ptr->nr_stalls_data++;
634 model_new_cycle(model_ptr);
638 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
639 model_ptr->fp_busy |= out_mask;
640 busy_ptr->fp_busy |= out_mask;
641 busy_ptr->nr_writebacks = 1;
642 if (WITH_TRACE && ppc_trace[trace_model])
643 model_trace_make_busy(model_ptr, 0, out_mask, 0);
646 # Schedule an instruction that takes floating point input registers and produces an output fp register & sets a CR reg
647 void::model-function::ppc_insn_float_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
648 const unsigned32 fp_mask = out_mask | in_mask;
649 model_busy *busy_ptr;
651 if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
652 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
654 while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
655 if (WITH_TRACE && ppc_trace[trace_model])
656 model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
658 model_ptr->nr_stalls_data++;
659 model_new_cycle(model_ptr);
663 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
664 model_ptr->fp_busy |= out_mask;
665 busy_ptr->fp_busy |= out_mask;
666 model_ptr->cr_fpscr_busy |= cr_mask;
667 busy_ptr->cr_fpscr_busy |= cr_mask;
668 busy_ptr->nr_writebacks = (cr_mask) ? 2 : 1;
669 if (WITH_TRACE && ppc_trace[trace_model])
670 model_trace_make_busy(model_ptr, 0, out_mask, cr_mask);
673 # Schedule an instruction that takes both int/float input registers and produces output int/float registers
674 void::model-function::ppc_insn_int_float:itable_index index, model_data *model_ptr, const unsigned32 out_int_mask, const unsigned32 out_fp_mask, const unsigned32 in_int_mask, const unsigned32 in_fp_mask
675 const unsigned32 int_mask = out_int_mask | in_int_mask;
676 const unsigned32 fp_mask = out_fp_mask | in_fp_mask;
677 model_busy *busy_ptr;
679 if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
680 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
682 while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
683 if (WITH_TRACE && ppc_trace[trace_model])
684 model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
686 model_ptr->nr_stalls_data++;
687 model_new_cycle(model_ptr);
690 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
691 model_ptr->int_busy |= out_int_mask;
692 busy_ptr->int_busy |= out_int_mask;
693 model_ptr->fp_busy |= out_fp_mask;
694 busy_ptr->fp_busy |= out_fp_mask;
695 busy_ptr->nr_writebacks = ((out_int_mask) ? 1 : 0) + ((out_fp_mask) ? 1 : 0);
696 if (WITH_TRACE && ppc_trace[trace_model])
697 model_trace_make_busy(model_ptr, out_int_mask, out_fp_mask, 0);
701 # Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
702 void::model-function::ppc_insn_from_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
703 model_busy *busy_ptr;
705 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
706 if (WITH_TRACE && ppc_trace[trace_model])
707 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
709 model_ptr->nr_stalls_data++;
710 model_new_cycle(model_ptr);
713 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
714 model_ptr->int_busy |= int_mask;
715 busy_ptr->int_busy |= int_mask;
716 busy_ptr->nr_writebacks = 1;
717 if (WITH_TRACE && ppc_trace[trace_model])
718 model_trace_make_busy(model_ptr, int_mask, 0, 0);
720 # Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
721 void::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
722 model_busy *busy_ptr;
724 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
725 if (WITH_TRACE && ppc_trace[trace_model])
726 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
728 model_ptr->nr_stalls_data++;
729 model_new_cycle(model_ptr);
732 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
733 busy_ptr->spr_busy = nSPR;
734 model_ptr->spr_busy[nSPR] = 1;
735 busy_ptr->nr_writebacks = 1;
736 TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));
738 # Schedule a MFCR instruction that moves the CR into an integer regsiter
739 void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, unsigned32 int_mask
740 const unsigned32 cr_mask = 0xff;
741 model_busy *busy_ptr;
743 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
744 if (WITH_TRACE && ppc_trace[trace_model])
745 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
747 model_ptr->nr_stalls_data++;
748 model_new_cycle(model_ptr);
751 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
752 model_ptr->int_busy |= int_mask;
753 busy_ptr->int_busy |= int_mask;
754 busy_ptr->nr_writebacks = 1;
755 if (WITH_TRACE && ppc_trace[trace_model])
756 model_trace_make_busy(model_ptr, int_mask, 0, 0);
758 # Schedule a MTCR instruction that moves an integer register into the CR
759 void::model-function::ppc_insn_mtcr:itable_index index, model_data *model_ptr, unsigned32 int_mask, unsigned FXM
762 unsigned32 cr_mask = 0;
763 const model_time *normal_time = &model_ptr->timing[index];
764 static const model_time ppc604_1bit_time = { PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 };
765 model_busy *busy_ptr;
767 for (f = 0; f < 8; f++) {
768 if (FXM & (0x80 >> f)) {
774 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
775 if (WITH_TRACE && ppc_trace[trace_model])
776 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
778 model_ptr->nr_stalls_data++;
779 model_new_cycle(model_ptr);
782 /* If only one CR is being moved, use the SCIU, not the MCIU on the 604 */
783 if (CURRENT_MODEL == MODEL_ppc604 && nr_crs == 1) {
784 normal_time = &ppc604_1bit_time;
787 busy_ptr = model_wait_for_unit(index, model_ptr, normal_time);
788 busy_ptr->cr_fpscr_busy |= cr_mask;
789 model_ptr->cr_fpscr_busy |= cr_mask;
790 model_ptr->nr_mtcrf_crs[nr_crs]++;
791 busy_ptr->nr_writebacks = 1;
792 if (WITH_TRACE && ppc_trace[trace_model])
793 model_trace_make_busy(model_ptr, 0, 0, cr_mask);
795 model_data *::model-function::model_create:cpu *processor
796 model_data *model_ptr = ZALLOC(model_data);
797 model_ptr->name = model_name[CURRENT_MODEL];
798 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
799 model_ptr->processor = processor;
800 model_ptr->nr_cycles = 1;
801 model_ptr->busy_tail = &model_ptr->busy_head;
802 switch (CURRENT_MODEL) {
803 case MODEL_ppc601: model_ptr->max_nr_writebacks = 1; break; /* ??? */
804 case MODEL_ppc603: model_ptr->max_nr_writebacks = 2; break;
805 case MODEL_ppc603e: model_ptr->max_nr_writebacks = 2; break;
806 case MODEL_ppc604: model_ptr->max_nr_writebacks = 2; break;
807 default: error ("Unknown model %d\n", CURRENT_MODEL);
811 void::model-function::model_init:model_data *model_ptr
813 void::model-function::model_halt:model_data *model_ptr
814 /* Let pipeline drain */
815 while (model_ptr->busy_head.next)
816 model_new_cycle(model_ptr);
818 unsigned_word::model-function::model_get_number_of_stalls:model_data *model_ptr
819 return (model_ptr->nr_stalls_data
820 + model_ptr->nr_stalls_unit
821 + model_ptr->nr_stalls_serialize
822 + model_ptr->nr_stalls_writeback);
824 unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
825 return (model_ptr->nr_cycles);
827 model_print *::model-function::model_mon_info:model_data *model_ptr
834 head = tail = ZALLOC(model_print);
835 tail->count = model_ptr->nr_cycles;
836 tail->name = "cycle";
837 tail->suffix_plural = "s";
838 tail->suffix_singular = "";
840 if (model_ptr->nr_stalls_data) {
841 tail->next = ZALLOC(model_print);
843 tail->count = model_ptr->nr_stalls_data;
844 tail->name = "stall";
845 tail->suffix_plural = "s waiting for data";
846 tail->suffix_singular = " waiting for data";
849 if (model_ptr->nr_stalls_unit) {
850 tail->next = ZALLOC(model_print);
852 tail->count = model_ptr->nr_stalls_unit;
853 tail->name = "stall";
854 tail->suffix_plural = "s waiting for a function unit";
855 tail->suffix_singular = " waiting for a function unit";
858 if (model_ptr->nr_stalls_serialize) {
859 tail->next = ZALLOC(model_print);
861 tail->count = model_ptr->nr_stalls_serialize;
862 tail->name = "stall";
863 tail->suffix_plural = "s waiting for serialization";
864 tail->suffix_singular = " waiting for serialization";
867 if (model_ptr->nr_stalls_writeback) {
868 tail->next = ZALLOC(model_print);
870 tail->count = model_ptr->nr_stalls_writeback;
872 tail->suffix_plural = "times a write-back slot was unavailable";
873 tail->suffix_singular = "time a writeback was unavailable";
876 if (model_ptr->nr_branches) {
877 tail->next = ZALLOC(model_print);
879 tail->count = model_ptr->nr_branches;
880 tail->name = "branch";
881 tail->suffix_plural = "es";
882 tail->suffix_singular = "";
885 if (model_ptr->nr_branches_fallthrough) {
886 tail->next = ZALLOC(model_print);
888 tail->count = model_ptr->nr_branches_fallthrough;
889 tail->name = "conditional branch";
890 tail->suffix_plural = "es fell through";
891 tail->suffix_singular = " fell through";
894 if (model_ptr->nr_branch_predict_trues) {
895 tail->next = ZALLOC(model_print);
897 tail->count = model_ptr->nr_branch_predict_trues;
898 tail->name = "successful branch prediction";
899 tail->suffix_plural = "s";
900 tail->suffix_singular = "";
903 if (model_ptr->nr_branch_predict_falses) {
904 tail->next = ZALLOC(model_print);
906 tail->count = model_ptr->nr_branch_predict_falses;
907 tail->name = "unsuccessful branch prediction";
908 tail->suffix_plural = "s";
909 tail->suffix_singular = "";
912 for (j = 0; j < (sizeof(ppc_branch_conditional_name) / sizeof(ppc_branch_conditional_name[0])) ; j++) {
913 if (model_ptr->nr_branch_conditional[j]) {
914 tail->next = ZALLOC(model_print);
916 tail->count = model_ptr->nr_branch_conditional[j];
917 tail->name = ppc_branch_conditional_name[j];
918 tail->suffix_plural = " conditional branches";
919 tail->suffix_singular = " conditional branch";
923 for (j = 0; j < 9; j++) {
924 if (model_ptr->nr_mtcrf_crs[j]) {
925 tail->next = ZALLOC(model_print);
927 tail->count = model_ptr->nr_mtcrf_crs[j];
928 tail->name = ppc_nr_mtcrf_crs[j];
929 tail->suffix_plural = " instructions";
930 tail->suffix_singular = " instruction";
935 for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
936 if (model_ptr->nr_units[i]) {
937 nr_insns += model_ptr->nr_units[i];
938 tail->next = ZALLOC(model_print);
940 tail->count = model_ptr->nr_units[i];
941 tail->name = ppc_function_unit_name[i];
942 tail->suffix_plural = "s";
943 tail->suffix_singular = "";
947 tail->next = ZALLOC(model_print);
949 tail->count = nr_insns;
950 tail->name = "instruction";
951 tail->suffix_plural = "s that were accounted for in timing info";
952 tail->suffix_singular = " that was accounted for in timing info";
954 tail->next = (model_print *)0;
957 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
959 model_print *next = ptr->next;
964 void::model-function::model_branches:model_data *model_ptr, int failed, int conditional
965 model_ptr->nr_units[PPC_UNIT_BPU]++;
967 model_ptr->nr_branches_fallthrough++;
969 model_ptr->nr_branches++;
970 if (conditional >= 0)
971 model_ptr->nr_branch_conditional[conditional]++;
972 model_new_cycle(model_ptr); /* A branch always ends the current cycle */
974 void::model-function::model_branch_predict:model_data *model_ptr, int success
976 model_ptr->nr_branch_predict_trues++;
978 model_ptr->nr_branch_predict_falses++;
981 # The following (illegal) instruction is `known' by gen and is
982 # called when ever an illegal instruction is encountered
984 program_interrupt(processor, cia,
985 illegal_instruction_program_interrupt);
988 # The following (floating point unavailable) instruction is `known' by gen
989 # and is called when ever an a floating point instruction is to be
990 # executed but floating point is make unavailable by the MSR
991 ::internal::floating_point_unavailable
992 floating_point_unavailable_interrupt(processor, cia);
996 # Floating point support functions
999 # Convert 32bit single to 64bit double
1000 unsigned64::function::DOUBLE:unsigned32 WORD
1002 if (EXTRACTED32(WORD, 1, 8) > 0
1003 && EXTRACTED32(WORD, 1, 8) < 255) {
1004 /* normalized operand */
1005 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
1006 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
1007 | INSERTED64(not_word_1_1, 2, 2)
1008 | INSERTED64(not_word_1_1, 3, 3)
1009 | INSERTED64(not_word_1_1, 4, 4)
1010 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
1012 else if (EXTRACTED32(WORD, 1, 8) == 0
1013 && EXTRACTED32(WORD, 9, 31) != 0) {
1014 /* denormalized operand */
1015 int sign = EXTRACTED32(WORD, 0, 0);
1017 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
1018 /* normalize the operand */
1019 while (MASKED64(frac, 0, 0) == 0) {
1023 FRT = (INSERTED64(sign, 0, 0)
1024 | INSERTED64(exp + 1023, 1, 11)
1025 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
1027 else if (EXTRACTED32(WORD, 1, 8) == 255
1028 || EXTRACTED32(WORD, 1, 31) == 0) {
1029 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
1030 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
1031 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
1032 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
1033 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
1036 error("DOUBLE - unknown case\n");
1041 # Convert 64bit single to 32bit double
1042 unsigned32::function::SINGLE:unsigned64 FRS
1044 if (EXTRACTED64(FRS, 1, 11) > 896
1045 || EXTRACTED64(FRS, 1, 63) == 0) {
1046 /* no denormalization required (includes Zero/Infinity/NaN) */
1047 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
1048 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
1050 else if (874 <= EXTRACTED64(FRS, 1, 11)
1051 && EXTRACTED64(FRS, 1, 11) <= 896) {
1052 /* denormalization required */
1053 int sign = EXTRACTED64(FRS, 0, 0);
1054 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
1055 unsigned64 frac = (BIT64(0)
1056 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
1057 /* denormalize the operand */
1058 while (exp < -126) {
1059 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1062 WORD = (INSERTED32(sign, 0, 0)
1063 | INSERTED32(0x00, 1, 8)
1064 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
1067 WORD = 0x0; /* ??? */
1072 # round 64bit double to 64bit but single
1073 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
1074 /* comparisons ignore u bits */
1077 int lsb = EXTRACTED64(*frac_grx, 23, 23);
1078 int gbit = EXTRACTED64(*frac_grx, 24, 24);
1079 int rbit = EXTRACTED64(*frac_grx, 25, 25);
1080 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
1081 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
1082 if (lsb == 1 && gbit == 1) inc = 1;
1083 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1084 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1086 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
1087 if (sign == 0 && gbit == 1) inc = 1;
1088 if (sign == 0 && rbit == 1) inc = 1;
1089 if (sign == 0 && xbit == 1) inc = 1;
1091 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
1092 if (sign == 1 && gbit == 1) inc = 1;
1093 if (sign == 1 && rbit == 1) inc = 1;
1094 if (sign == 1 && xbit == 1) inc = 1;
1096 /* work out addition in low 25 bits of out */
1097 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
1098 *frac_grx = INSERTED64(out, 0, 23);
1099 if (out & BIT64(64 - 23 - 1 - 1)) {
1100 *frac_grx = (BIT64(0) |
1101 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
1104 /* frac_grx[24:52] = 0 already */
1106 FPSCR_SET_FI(gbit || rbit || xbit);
1110 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
1112 if (round_mode == fpscr_rn_round_to_nearest) {
1113 if (*frac64 == 1 && gbit == 1) inc = 1;
1114 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
1115 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
1117 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1118 if (sign == 0 && gbit == 1) inc = 1;
1119 if (sign == 0 && rbit == 1) inc = 1;
1120 if (sign == 0 && xbit == 1) inc = 1;
1122 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1123 if (sign == 1 && gbit == 1) inc = 1;
1124 if (sign == 1 && rbit == 1) inc = 1;
1125 if (sign == 1 && xbit == 1) inc = 1;
1127 /* frac[0:64] = frac[0:64} + inc */
1128 *frac += (*frac64 && inc ? 1 : 0);
1129 *frac64 = (*frac64 + inc) & 0x1;
1131 FPSCR_SET_FI(gbit | rbit | xbit);
1134 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
1137 int lsb = EXTRACTED64(*frac, 52, 52);
1138 int gbit = EXTRACTED64(*frac, 53, 53);
1139 int rbit = EXTRACTED64(*frac, 54, 54);
1140 int xbit = EXTRACTED64(*frac, 55, 55);
1141 if (round_mode == fpscr_rn_round_to_nearest) {
1142 if (lsb == 1 && gbit == 1) inc = 1;
1143 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1144 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1146 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1147 if (sign == 0 && gbit == 1) inc = 1;
1148 if (sign == 0 && rbit == 1) inc = 1;
1149 if (sign == 0 && xbit == 1) inc = 1;
1151 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1152 if (sign == 1 && gbit == 1) inc = 1;
1153 if (sign == 1 && rbit == 1) inc = 1;
1154 if (sign == 1 && xbit == 1) inc = 1;
1156 /* frac//carry_out = frac + inc */
1157 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
1158 carry_out = EXTRACTED64(*frac, 0, 0);
1160 if (carry_out == 1) *exp = *exp + 1;
1162 FPSCR_SET_FI(gbit | rbit | xbit);
1163 FPSCR_SET_XX(FPSCR & fpscr_fi);
1166 # conversion of FP to integer
1167 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
1170 unsigned64 frac = 0;
1175 int sign = EXTRACTED64(frb, 0, 0);
1177 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
1178 GOTO(Infinity_Operand);
1179 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
1181 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1183 if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
1184 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
1185 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
1186 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
1187 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1190 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1191 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1194 gbit = 0, rbit = 0, xbit = 0;
1195 for (i = 1; i <= 63 - exp; i++) {
1199 frac64 = EXTRACTED64(frac, 63, 63);
1200 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1202 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1203 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1206 frac += (frac64 ? 1 : 0);
1207 frac64 = (frac64 + 1) & 0x1;
1209 if (tgt_precision == 32 /* can ignore frac64 in compare */
1210 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1211 GOTO(Large_Operand);
1212 if (tgt_precision == 64 /* can ignore frac64 in compare */
1213 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1214 GOTO(Large_Operand);
1215 if (tgt_precision == 32 /* can ignore frac64 in compare */
1216 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1217 GOTO(Large_Operand);
1218 if (tgt_precision == 64 /* can ignore frac64 in compare */
1219 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1220 GOTO(Large_Operand);
1221 FPSCR_SET_XX(FPSCR & fpscr_fi);
1222 if (tgt_precision == 32)
1223 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1224 if (tgt_precision == 64)
1225 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1226 /*FPSCR[fprf] = undefined */
1229 LABEL(Infinity_Operand):
1232 FPSCR_OR_VX(fpscr_vxcvi);
1233 if ((FPSCR & fpscr_ve) == 0) {
1234 if (tgt_precision == 32) {
1235 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1236 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1239 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1240 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1242 /* FPSCR[FPRF] = undefined */
1246 LABEL(SNaN_Operand):
1249 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1250 if ((FPSCR & fpscr_ve) == 0) {
1251 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1252 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1253 /* FPSCR[fprf] = undefined */
1257 LABEL(QNaN_Operand):
1260 FPSCR_OR_VX(fpscr_vxcvi);
1261 if ((FPSCR & fpscr_ve) == 0) {
1262 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1263 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1264 /* FPSCR[fprf] = undefined */
1268 LABEL(Large_Operand):
1271 FPSCR_OR_VX(fpscr_vxcvi);
1272 if ((FPSCR & fpscr_ve) == 0) {
1273 if (tgt_precision == 32) {
1274 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1275 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1278 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1279 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1281 /* FPSCR[fprf] = undefined */
1287 # extract out raw fields of a FP number
1288 int::function::sign:unsigned64 FRS
1289 return (MASKED64(FRS, 0, 0)
1292 int::function::biased_exp:unsigned64 frs, int single
1294 return EXTRACTED64(frs, 1, 8);
1296 return EXTRACTED64(frs, 1, 11);
1297 unsigned64::function::fraction:unsigned64 frs, int single
1299 return EXTRACTED64(frs, 9, 31);
1301 return EXTRACTED64(frs, 12, 63);
1303 # a number?, each of the below return +1 or -1 (based on sign bit)
1305 int::function::is_nor:unsigned64 frs, int single
1306 int exp = biased_exp(frs, single);
1308 && exp <= (single ? 254 : 2046));
1309 int::function::is_zero:unsigned64 FRS
1310 return (MASKED64(FRS, 1, 63) == 0
1313 int::function::is_den:unsigned64 frs, int single
1314 int exp = biased_exp(frs, single);
1315 unsigned64 frac = fraction(frs, single);
1316 return (exp == 0 && frac != 0
1319 int::function::is_inf:unsigned64 frs, int single
1320 int exp = biased_exp(frs, single);
1321 unsigned64 frac = fraction(frs, single);
1322 return (exp == (single ? 255 : 2047) && frac == 0
1325 int::function::is_NaN:unsigned64 frs, int single
1326 int exp = biased_exp(frs, single);
1327 unsigned64 frac = fraction(frs, single);
1328 return (exp == (single ? 255 : 2047) && frac != 0
1331 int::function::is_SNaN:unsigned64 frs, int single
1332 return (is_NaN(frs, single)
1333 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1336 int::function::is_QNaN:unsigned64 frs, int single
1337 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1338 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1339 return *(double*)fra < *(double*)frb;
1340 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1341 return *(double*)fra > *(double*)frb;
1342 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1343 return *(double*)fra == *(double*)frb;
1346 # which quiet nan should become the result
1347 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1349 if (is_NaN(fra, single))
1351 else if (is_NaN(frb, single))
1352 if (instruction_is_frsp)
1353 frt = MASKED64(frb, 0, 34);
1356 else if (is_NaN(frc, single))
1358 else if (generate_qnan)
1359 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1361 error("select_qnan - default reached\n");
1365 # detect invalid operation
1366 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1368 if ((check & fpscr_vxsnan)
1369 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1370 FPSCR_OR_VX(fpscr_vxsnan);
1373 if ((check & fpscr_vxisi)
1374 && (is_inf(fra, single) && is_inf(frb, single))
1375 && ((negate && sign(fra) != sign(frb))
1376 || (!negate && sign(fra) == sign(frb)))) {
1377 /*FIXME: don't handle inf-inf VS inf+-inf */
1378 FPSCR_OR_VX(fpscr_vxisi);
1381 if ((check & fpscr_vxidi)
1382 && (is_inf(fra, single) && is_inf(frb, single))) {
1383 FPSCR_OR_VX(fpscr_vxidi);
1386 if ((check & fpscr_vxzdz)
1387 && (is_zero(fra) && is_zero(frb))) {
1388 FPSCR_OR_VX(fpscr_vxzdz);
1391 if ((check & fpscr_vximz)
1392 && (is_zero(fra) && is_inf(frb, single))) {
1393 FPSCR_OR_VX(fpscr_vximz);
1396 if ((check & fpscr_vxvc)
1397 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1398 FPSCR_OR_VX(fpscr_vxvc);
1401 if ((check & fpscr_vxsoft)) {
1402 FPSCR_OR_VX(fpscr_vxsoft);
1405 if ((check & fpscr_vxsqrt)
1407 FPSCR_OR_VX(fpscr_vxsqrt);
1410 /* if ((check && fpscr_vxcvi) {
1411 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1412 FPSCR_OR_VX(fpscr_vxcvi);
1422 # handle case of invalid operation
1423 void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int instruction_is_convert_to_64bit, int instruction_is_convert_to_32bit, int single
1424 if (FPSCR & fpscr_ve) {
1425 /* invalid operation exception enabled */
1429 /* fpscr_FPRF unchanged */
1432 /* invalid operation exception disabled */
1433 if (instruction_is_convert_to_64bit) {
1436 else if (instruction_is_convert_to_32bit) {
1439 else { /* arrith, frsp */
1440 *frt = select_qnan(fra, frb, frc,
1441 instruction_is_frsp, 1/*generate*/, single);
1444 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1451 # detect divide by zero
1452 int::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single
1454 if (is_zero (frb)) {
1463 # handle case of invalid operation
1464 void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, int single
1465 if (FPSCR & fpscr_ze) {
1466 /* zero-divide exception enabled */
1470 /* fpscr_FPRF unchanged */
1473 /* zero-divide exception disabled */
1476 if ((sign (fra) < 0 && sign (frb) < 0)
1477 || (sign (fra) > 0 && sign (frb) > 0)) {
1478 *frt = MASK64 (1, 11); /* 0 : 2047 : 0..0 */
1479 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
1482 *frt = MASK64 (0, 11); /* 1 : 2047 : 0..0 */
1483 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
1492 # 0.0.0.0 Illegal instruction used for kernel mode emulation
1494 0.0,6./,11./,16./,21./,31.1:X:::instruction_call
1495 if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1496 program_interrupt(processor, cia,
1497 illegal_instruction_program_interrupt);
1500 # I.2.4.1 Branch Instructions
1502 0.18,6.LI,30.AA,31.LK:I:::Branch
1503 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1504 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1505 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1506 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1508 No problem here because this branch is predicted taken (unconditional). */
1509 if (AA) NIA = IEA(EXTS(LI_0b00));
1510 else NIA = IEA(CIA + EXTS(LI_0b00));
1511 if (LK) LR = (spreg)CIA+4;
1512 if (CURRENT_MODEL_ISSUE > 0)
1513 model_branches(cpu_model(processor), 1, -1);
1515 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1516 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1517 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1518 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1519 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1520 int M, ctr_ok, cond_ok, succeed;
1521 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1522 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1523 if (is_64bit_implementation && is_64bit_mode) M = 0;
1525 if (!BO{2}) CTR = CTR - 1;
1526 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1527 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1528 if (ctr_ok && cond_ok) {
1529 if (AA) NIA = IEA(EXTS(BD_0b00));
1530 else NIA = IEA(CIA + EXTS(BD_0b00));
1535 if (LK) LR = (spreg)IEA(CIA + 4);
1536 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1537 /* This branch is predicted as "normal".
1538 If this is a forward branch and it is near the end of a page,
1539 we've detected a problematic branch. */
1540 if (succeed && NIA > CIA) {
1541 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1542 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1545 if (CURRENT_MODEL_ISSUE > 0)
1546 model_branches(cpu_model(processor), succeed, BO);
1549 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1550 reverse = EXTS(BD_0b00) < 0;
1551 } else { /* branch prediction bit not set */
1552 reverse = EXTS(BD_0b00) >= 0;
1554 if (CURRENT_MODEL_ISSUE > 0)
1555 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1558 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1559 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1560 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1561 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1562 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1563 int M, ctr_ok, cond_ok, succeed;
1564 if (is_64bit_implementation && is_64bit_mode) M = 0;
1566 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1567 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1568 if (!BO{2}) CTR = CTR - 1;
1569 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1570 cond_ok = BO{0} || (CR{BI} == BO{1});
1571 if (ctr_ok && cond_ok) {
1577 if (LK) LR = (spreg)IEA(CIA + 4);
1578 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1579 /* This branch is predicted as not-taken.
1580 If this is a forward branch and it is near the end of a page,
1581 we've detected a problematic branch. */
1582 if (succeed && NIA > CIA) {
1583 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1584 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1587 if (CURRENT_MODEL_ISSUE > 0) {
1588 model_branches(cpu_model(processor), succeed, BO);
1590 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1593 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1594 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1595 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1596 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1597 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1598 int cond_ok, succeed;
1599 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1600 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1601 cond_ok = BO{0} || (CR{BI} == BO{1});
1603 NIA = IEA(CTR_0b00);
1608 if (LK) LR = (spreg)IEA(CIA + 4);
1609 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1610 /* This branch is predicted as not-taken.
1611 If this is a forward branch and it is near the end of a page,
1612 we've detected a problematic branch. */
1613 if (succeed && NIA > CIA) {
1614 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1615 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1618 if (CURRENT_MODEL_ISSUE > 0) {
1619 model_branches(cpu_model(processor), succeed, BO);
1621 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1625 # I.2.4.2 System Call Instruction
1627 0.17,6./,11./,16./,30.1,31./:SC:::System Call
1628 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1629 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1630 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1631 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1632 if (CURRENT_MODEL_ISSUE > 0)
1633 model_serialize(MY_INDEX, cpu_model(processor));
1634 system_call_interrupt(processor, cia);
1637 # I.2.4.3 Condition Register Logical Instructions
1639 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1640 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1641 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1642 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1643 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1644 BLIT32(CR, BT, CR{BA} && CR{BB});
1645 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1647 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1648 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1649 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1650 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1651 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1652 BLIT32(CR, BT, CR{BA} || CR{BB});
1653 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1655 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1656 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1657 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1658 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1659 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1660 BLIT32(CR, BT, CR{BA} != CR{BB});
1661 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1663 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1664 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1665 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1666 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1667 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1668 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1669 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1671 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1672 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1673 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1674 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1675 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1676 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1677 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1679 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1680 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1681 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1682 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1683 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1684 BLIT32(CR, BT, CR{BA} == CR{BB});
1685 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1687 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1688 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1689 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1690 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1691 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1692 BLIT32(CR, BT, CR{BA} && !CR{BB});
1693 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1695 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1696 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1697 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1698 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1699 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1700 BLIT32(CR, BT, CR{BA} || !CR{BB});
1701 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1704 # I.2.4.4 Condition Register Field Instruction
1706 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1707 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1708 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1709 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1710 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1711 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1712 PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1716 # I.3.3.2 Fixed-Point Load Instructions
1719 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1720 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1721 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1722 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1723 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1729 *rT = MEM(unsigned, EA, 1);
1730 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1733 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1734 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1735 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1736 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1737 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1743 *rT = MEM(unsigned, EA, 1);
1744 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1746 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1747 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1748 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1749 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1750 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1752 if (RA_is_0 || RA == RT)
1753 program_interrupt(processor, cia,
1754 illegal_instruction_program_interrupt);
1756 *rT = MEM(unsigned, EA, 1);
1758 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1760 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1761 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1762 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1763 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1764 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1766 if (RA_is_0 || RA == RT)
1767 program_interrupt(processor, cia,
1768 illegal_instruction_program_interrupt);
1770 *rT = MEM(unsigned, EA, 1);
1772 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1774 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1775 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1776 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1777 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1778 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1784 *rT = MEM(unsigned, EA, 2);
1785 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1787 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1788 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1789 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1790 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1791 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1797 *rT = MEM(unsigned, EA, 2);
1798 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1800 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1801 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1802 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1803 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1804 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1806 if (RA_is_0 || RA == RT)
1807 program_interrupt(processor, cia,
1808 illegal_instruction_program_interrupt);
1810 *rT = MEM(unsigned, EA, 2);
1812 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1814 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1815 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1816 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1817 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1818 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1820 if (RA_is_0 || RA == RT)
1821 program_interrupt(processor, cia,
1822 illegal_instruction_program_interrupt);
1824 *rT = MEM(unsigned, EA, 2);
1826 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1828 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1829 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1830 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1831 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1832 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1838 *rT = MEM(signed, EA, 2);
1839 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1841 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1842 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1843 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1844 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1845 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1851 *rT = MEM(signed, EA, 2);
1852 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1854 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1855 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1856 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1857 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1858 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1860 if (RA_is_0 || RA == RT)
1861 program_interrupt(processor, cia,
1862 illegal_instruction_program_interrupt);
1864 *rT = MEM(signed, EA, 2);
1866 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1868 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1869 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1870 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1871 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1872 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1874 if (RA_is_0 || RA == RT)
1875 program_interrupt(processor, cia,
1876 illegal_instruction_program_interrupt);
1878 *rT = MEM(signed, EA, 2);
1880 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1882 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1883 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1884 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1885 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1886 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1892 *rT = MEM(unsigned, EA, 4);
1893 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1895 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1896 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1897 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1898 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1899 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1905 *rT = MEM(unsigned, EA, 4);
1906 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1908 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1909 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1910 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1911 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1912 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1914 if (RA_is_0 || RA == RT)
1915 program_interrupt(processor, cia,
1916 illegal_instruction_program_interrupt);
1918 *rT = MEM(unsigned, EA, 4);
1920 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1922 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1923 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1924 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1925 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1926 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1928 if (RA_is_0 || RA == RT)
1929 program_interrupt(processor, cia,
1930 illegal_instruction_program_interrupt);
1932 *rT = MEM(unsigned, EA, 4);
1934 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1936 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1939 # if (RA_is_0) b = 0;
1941 # EA = b + EXTS(DS_0b00);
1942 # *rT = MEM(signed, EA, 4);
1944 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1947 # if (RA_is_0) b = 0;
1950 # *rT = MEM(signed, EA, 4);
1952 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1954 # if (RA_is_0 || RA == RT)
1955 # program_interrupt(processor, cia
1956 # illegal_instruction_program_interrupt);
1958 # *rT = MEM(signed, EA, 4);
1961 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1964 # if (RA_is_0) b = 0;
1966 # EA = b + EXTS(DS_0b00);
1967 # *rT = MEM(unsigned, EA, 8);
1969 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1972 # if (RA_is_0) b = 0;
1975 # *rT = MEM(unsigned, EA, 8);
1977 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1979 # if (RA_is_0 || RA == RT)
1980 # program_interrupt(processor, cia
1981 # illegal_instruction_program_interrupt);
1982 # EA = *rA + EXTS(DS_0b00);
1983 # *rT = MEM(unsigned, EA, 8);
1986 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1988 # if (RA_is_0 || RA == RT)
1989 # program_interrupt(processor, cia
1990 # illegal_instruction_program_interrupt);
1992 # *rT = MEM(unsigned, EA, 8);
1998 # I.3.3.3 Fixed-Point Store Instructions
2001 0.38,6.RS,11.RA,16.D:D:::Store Byte
2002 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2003 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2004 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2005 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2012 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2014 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
2015 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2016 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2017 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2018 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2025 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2027 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
2028 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2029 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2030 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2031 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2034 program_interrupt(processor, cia,
2035 illegal_instruction_program_interrupt);
2039 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2041 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
2042 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2043 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2044 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2045 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2048 program_interrupt(processor, cia,
2049 illegal_instruction_program_interrupt);
2053 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2055 0.44,6.RS,11.RA,16.D:D:::Store Half Word
2056 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2057 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2058 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2059 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2066 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2068 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
2069 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2070 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2071 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2072 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2079 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2081 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
2082 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2083 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2084 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2085 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2088 program_interrupt(processor, cia,
2089 illegal_instruction_program_interrupt);
2093 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2095 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
2096 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2097 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2098 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2099 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2102 program_interrupt(processor, cia,
2103 illegal_instruction_program_interrupt);
2107 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2109 0.36,6.RS,11.RA,16.D:D:::Store Word
2110 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2111 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2112 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2113 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2120 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2122 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
2123 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2124 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2125 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2126 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2133 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2135 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
2136 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2137 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2138 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2139 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2142 program_interrupt(processor, cia,
2143 illegal_instruction_program_interrupt);
2147 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2149 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
2150 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2151 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2152 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2153 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2156 program_interrupt(processor, cia,
2157 illegal_instruction_program_interrupt);
2161 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2163 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2166 # if (RA_is_0) b = 0;
2168 # EA = b + EXTS(DS_0b00);
2169 # STORE(EA, 8, *rS);
2170 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2173 # if (RA_is_0) b = 0;
2176 # STORE(EA, 8, *rS);
2177 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2180 # program_interrupt(processor, cia
2181 # illegal_instruction_program_interrupt);
2182 # EA = *rA + EXTS(DS_0b00);
2183 # STORE(EA, 8, *rS);
2185 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2188 # program_interrupt(processor, cia
2189 # illegal_instruction_program_interrupt);
2191 # STORE(EA, 8, *rS);
2196 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2199 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2200 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2201 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2202 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2203 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2209 *rT = SWAP_2(MEM(unsigned, EA, 2));
2210 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2212 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2213 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2214 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2215 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2216 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2222 *rT = SWAP_4(MEM(unsigned, EA, 4));
2223 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2225 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2226 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2227 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2228 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2229 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2235 STORE(EA, 2, SWAP_2(*rS));
2236 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2238 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2239 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2240 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2241 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2242 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2248 STORE(EA, 4, SWAP_4(*rS));
2249 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2253 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2256 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2265 program_interrupt(processor, cia,
2266 illegal_instruction_program_interrupt);
2267 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
2268 alignment_interrupt(processor, cia, EA);
2270 GPR(r) = MEM(unsigned, EA, 4);
2275 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2282 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
2284 alignment_interrupt(processor, cia, EA);
2287 STORE(EA, 4, GPR(r));
2294 # I.3.3.6 Fixed-Point Move Assist Instructions
2297 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2303 if (RA_is_0) EA = 0;
2305 if (NB == 0) n = 32;
2311 ? (RA >= RT || RA < (RT + nr) % 32)
2312 : (RA >= RT && RA < RT + nr))
2313 program_interrupt(processor, cia,
2314 illegal_instruction_program_interrupt);
2315 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2316 alignment_interrupt(processor, cia, EA);
2322 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2324 if (i == 64) i = 32;
2329 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2339 n = EXTRACTED32(XER, 25, 31);
2343 if (((RT + nr >= 32)
2344 ? ((RA >= RT || RA < (RT + nr) % 32)
2345 || (RB >= RT || RB < (RT + nr) % 32))
2346 : ((RA >= RT && RA < RT + nr)
2347 || (RB >= RT && RB < RT + nr)))
2348 || (RT == RA || RT == RB))
2349 program_interrupt(processor, cia,
2350 illegal_instruction_program_interrupt);
2351 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2352 alignment_interrupt(processor, cia, EA);
2358 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2360 if (i == 64) i = 32;
2365 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2370 if (RA_is_0) EA = 0;
2372 if (NB == 0) n = 32;
2376 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2377 alignment_interrupt(processor, cia, EA);
2379 if (i == 32) r = (r + 1) % 32;
2380 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2382 if (i == 64) i = 32;
2387 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2396 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2397 alignment_interrupt(processor, cia, EA);
2398 n = EXTRACTED32(XER, 25, 31);
2402 if (i == 32) r = (r + 1) % 32;
2403 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2405 if (i == 64) i = 32;
2412 # I.3.3.7 Storage Synchronization Instructions
2414 # HACK: Rather than monitor addresses looking for a reason
2415 # to cancel a reservation. This code instead keeps
2416 # a copy of the data read from memory. Before performing
2417 # a store, the memory area is checked to see if it has
2419 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2420 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2421 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2422 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2423 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2430 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2431 RESERVE_DATA = MEM(unsigned, EA, 4);
2433 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2435 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2442 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2443 RESERVE_DATA = MEM(unsigned, EA, 8);
2445 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2447 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2448 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2449 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2450 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2451 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2458 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2459 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2461 CR_SET_XER_SO(0, cr_i_zero);
2464 /* ment to randomly to store, we never do! */
2465 CR_SET_XER_SO(0, 0);
2470 CR_SET_XER_SO(0, 0);
2472 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2474 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2481 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2482 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2484 CR_SET_XER_SO(0, cr_i_zero);
2487 /* ment to randomly to store, we never do */
2488 CR_SET_XER_SO(0, 0);
2493 CR_SET_XER_SO(0, 0);
2495 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2497 0.31,6./,9.L,11./,16./,21.598,31./:X::sync:Synchronize
2498 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2499 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2500 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2501 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2506 # I.3.3.9 Fixed-Point Arithmetic Instructions
2509 0.14,6.RT,11.RA,16.SI:D:::Add Immediate
2510 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2511 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2512 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2513 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2514 if (RA_is_0) *rT = EXTS(SI);
2515 else *rT = *rA + EXTS(SI);
2516 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2517 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2519 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2520 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2521 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2522 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2523 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2524 if (RA_is_0) *rT = EXTS(SI) << 16;
2525 else *rT = *rA + (EXTS(SI) << 16);
2526 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2527 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2529 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2530 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2531 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2532 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2533 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2536 ALU_END(*rT, 0/*CA*/, OE, Rc);
2537 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2539 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2540 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2541 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2542 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2543 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2548 ALU_END(*rT, 0/*CA*/, OE, Rc);
2549 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2551 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2552 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2553 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2554 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2555 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2558 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2559 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2561 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2562 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2563 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2564 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2565 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2568 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2569 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2571 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2572 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2573 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2574 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2575 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2580 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2581 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2583 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2584 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2585 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2586 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2587 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2590 ALU_END(*rT, 1/*CA*/, OE, Rc);
2591 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2593 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2594 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2595 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2596 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2597 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2598 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2603 ALU_END(*rT, 1/*CA*/, OE, Rc);
2604 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2606 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2607 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2608 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2609 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2610 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2614 ALU_END(*rT, 1/*CA*/, OE, Rc);
2615 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2617 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2618 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2619 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2620 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2621 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2626 ALU_END(*rT, 1/*CA*/, OE, Rc);
2627 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2629 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2631 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2632 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2633 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2637 ALU_END(*rT, 1/*CA*/, OE, Rc);
2638 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2640 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2641 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2642 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2643 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2644 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2649 ALU_END(*rT, 1/*CA*/, OE, Rc);
2650 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2652 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2653 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2654 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2655 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2656 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2659 ALU_END(*rT, 1/*CA*/, OE, Rc);
2660 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2662 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2663 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2664 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2665 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2666 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2670 ALU_END(*rT, 1/*CA*/, OE, Rc);
2671 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2673 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2674 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2675 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2676 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2677 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2681 ALU_END(*rT,0/*CA*/,OE,Rc);
2682 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2684 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2685 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2686 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2687 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2688 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2689 signed_word prod = *rA * EXTS(SI);
2691 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2693 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2695 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2696 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2697 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2698 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2699 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2700 signed64 a = (signed32)(*rA);
2701 signed64 b = (signed32)(*rB);
2702 signed64 prod = a * b;
2703 signed_word t = prod;
2705 if (t != prod && OE)
2706 XER |= (xer_overflow | xer_summary_overflow);
2707 CR0_COMPARE(t, 0, Rc);
2708 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2710 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2712 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2713 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2714 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2715 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2716 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2717 signed64 a = (signed32)(*rA);
2718 signed64 b = (signed32)(*rB);
2719 signed64 prod = a * b;
2720 signed_word t = EXTRACTED64(prod, 0, 31);
2722 CR0_COMPARE(t, 0, Rc);
2723 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2725 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2727 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::mulhwu:Multiply High Word Unsigned
2728 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2729 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2730 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2731 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2732 unsigned64 a = (unsigned32)(*rA);
2733 unsigned64 b = (unsigned32)(*rB);
2734 unsigned64 prod = a * b;
2735 signed_word t = EXTRACTED64(prod, 0, 31);
2737 CR0_COMPARE(t, 0, Rc);
2738 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2740 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2742 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2743 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2744 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2745 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2746 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2747 signed64 dividend = (signed32)(*rA);
2748 signed64 divisor = (signed32)(*rB);
2749 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2750 || (dividend == 0x80000000 && divisor == -1)) {
2752 XER |= (xer_overflow | xer_summary_overflow);
2753 CR0_COMPARE(0, 0, Rc);
2756 signed64 quotent = dividend / divisor;
2758 CR0_COMPARE((signed_word)quotent, 0, Rc);
2760 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2762 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2764 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2765 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2766 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2767 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2768 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2769 unsigned64 dividend = (unsigned32)(*rA);
2770 unsigned64 divisor = (unsigned32)(*rB);
2773 XER |= (xer_overflow | xer_summary_overflow);
2774 CR0_COMPARE(0, 0, Rc);
2777 unsigned64 quotent = dividend / divisor;
2779 CR0_COMPARE((signed_word)quotent, 0, Rc);
2781 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2785 # I.3.3.10 Fixed-Point Compare Instructions
2788 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2789 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2790 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2791 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2792 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2793 if (!is_64bit_mode && L)
2794 program_interrupt(processor, cia,
2795 illegal_instruction_program_interrupt);
2798 signed_word b = EXTS(SI);
2803 CR_COMPARE(BF, a, b);
2805 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2807 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2808 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2809 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2810 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2811 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2812 if (!is_64bit_mode && L)
2813 program_interrupt(processor, cia,
2814 illegal_instruction_program_interrupt);
2826 CR_COMPARE(BF, a, b);
2828 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2830 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2831 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2832 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2833 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2834 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2835 if (!is_64bit_mode && L)
2836 program_interrupt(processor, cia,
2837 illegal_instruction_program_interrupt);
2840 unsigned_word b = UI;
2842 a = MASKED(*rA, 32, 63);
2845 CR_COMPARE(BF, a, b);
2847 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2849 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2850 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2851 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2852 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2853 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2854 if (!is_64bit_mode && L)
2855 program_interrupt(processor, cia,
2856 illegal_instruction_program_interrupt);
2861 a = MASKED(*rA, 32, 63);
2862 b = MASKED(*rB, 32, 63);
2868 CR_COMPARE(BF, a, b);
2870 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2874 # I.3.3.11 Fixed-Point Trap Instructions
2877 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2879 program_interrupt(processor, cia,
2880 illegal_instruction_program_interrupt);
2882 signed_word a = *rA;
2883 signed_word b = EXTS(SI);
2884 if ((a < b && TO{0})
2886 || (a == b && TO{2})
2887 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2888 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2890 program_interrupt(processor, cia,
2891 trap_program_interrupt);
2894 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2895 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2896 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2897 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2898 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2899 signed_word a = EXTENDED(*rA);
2900 signed_word b = EXTS(SI);
2901 if ((a < b && TO{0})
2903 || (a == b && TO{2})
2904 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2905 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2907 program_interrupt(processor, cia,
2908 trap_program_interrupt);
2910 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2912 program_interrupt(processor, cia,
2913 illegal_instruction_program_interrupt);
2915 signed_word a = *rA;
2916 signed_word b = *rB;
2917 if ((a < b && TO{0})
2919 || (a == b && TO{2})
2920 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2921 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2923 program_interrupt(processor, cia,
2924 trap_program_interrupt);
2927 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2928 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2929 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2930 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2931 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2932 signed_word a = EXTENDED(*rA);
2933 signed_word b = EXTENDED(*rB);
2934 if (TO == 12 && rA == rB) {
2935 ITRACE(trace_breakpoint, ("breakpoint\n"));
2936 cpu_halt(processor, cia, was_trap, 0);
2938 else if ((a < b && TO{0})
2940 || (a == b && TO{2})
2941 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2942 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2944 program_interrupt(processor, cia,
2945 trap_program_interrupt);
2948 # I.3.3.12 Fixed-Point Logical Instructions
2951 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2952 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2953 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2954 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2955 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2957 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2958 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2959 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2961 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2962 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2963 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2964 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2965 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2966 *rA = *rS & (UI << 16);
2967 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2968 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2969 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2971 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2972 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2973 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2974 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2975 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2977 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2978 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2980 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2981 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2982 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2983 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2984 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2985 *rA = *rS | (UI << 16);
2986 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2987 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2989 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2990 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2991 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2992 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2993 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2995 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2996 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2998 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2999 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3000 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3001 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3002 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3003 *rA = *rS ^ (UI << 16);
3004 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3005 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
3007 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
3008 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3009 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3010 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3011 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3013 CR0_COMPARE(*rA, 0, Rc);
3014 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3015 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3017 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
3018 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3019 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3020 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3021 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3023 CR0_COMPARE(*rA, 0, Rc);
3024 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3025 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3027 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
3028 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3029 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3030 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3031 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3033 CR0_COMPARE(*rA, 0, Rc);
3034 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3035 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3037 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
3038 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3039 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3040 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3041 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3043 CR0_COMPARE(*rA, 0, Rc);
3044 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3045 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3047 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
3048 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3049 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3050 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3051 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3053 CR0_COMPARE(*rA, 0, Rc);
3054 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3055 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3057 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
3058 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3059 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3060 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3061 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3062 *rA = ~(*rS ^ *rB); /* A === B */
3063 CR0_COMPARE(*rA, 0, Rc);
3064 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3065 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3067 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
3068 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3069 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3070 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3071 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3073 CR0_COMPARE(*rA, 0, Rc);
3074 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3075 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3077 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
3078 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3079 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3080 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3081 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3083 CR0_COMPARE(*rA, 0, Rc);
3084 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3085 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3087 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
3088 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3089 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3090 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3091 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3092 *rA = (signed_word)(signed8)*rS;
3093 CR0_COMPARE(*rA, 0, Rc);
3094 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3095 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3097 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
3098 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3099 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3100 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3101 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3102 *rA = (signed_word)(signed16)*rS;
3103 CR0_COMPARE(*rA, 0, Rc);
3104 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3105 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3107 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
3108 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3109 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3110 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3111 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3112 # *rA = (signed_word)(signed32)*rS;
3113 # CR0_COMPARE(*rA, 0, Rc);
3115 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
3117 # unsigned64 mask = BIT64(0);
3118 # unsigned64 source = *rS;
3119 # while (!(source & mask) && mask != 0) {
3124 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3126 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
3127 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3128 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3129 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3130 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3132 unsigned32 mask = BIT32(0);
3133 unsigned32 source = *rS;
3134 while (!(source & mask) && mask != 0) {
3139 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3140 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3144 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
3147 0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.0,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear Left
3148 # long n = (sh_5 << 4) | sh_0_4;
3149 # unsigned_word r = ROTL64(*rS, n);
3150 # long b = (mb_5 << 4) | mb_0_4;
3151 # unsigned_word m = MASK(b, 63);
3152 # signed_word result = r & m;
3154 # ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3155 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3157 0.30,6.RS,11.RA,16.sh_0_4,21.me,27.1,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear Right
3158 # long n = (sh_5 << 4) | sh_0_4;
3159 # unsigned_word r = ROTL64(*rS, n);
3160 # long e = (me_5 << 4) | me_0_4;
3161 # unsigned_word m = MASK(0, e);
3162 # signed_word result = r & m;
3164 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3166 0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.2,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear
3167 # long n = (sh_5 << 4) | sh_0_4;
3168 # unsigned_word r = ROTL64(*rS, n);
3169 # long b = (mb_5 << 4) | mb_0_4;
3170 # unsigned_word m = MASK(0, (64-n));
3171 # signed_word result = r & m;
3173 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3175 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
3176 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3177 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3178 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3179 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3182 unsigned32 r = ROTL32(s, n);
3183 unsigned32 m = MASK(MB+32, ME+32);
3184 signed_word result = r & m;
3186 CR0_COMPARE(result, 0, Rc);
3188 ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
3189 n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
3190 (unsigned long)result, (unsigned long)CR));
3191 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3193 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
3194 # long n = MASKED(*rB, 58, 63);
3195 # unsigned_word r = ROTL64(*rS, n);
3196 # long b = (mb_5 << 4) | mb_0_4;
3197 # unsigned_word m = MASK(b, 63);
3198 # signed_word result = r & m;
3200 # CR0_COMPARE(result, 0, Rc);
3202 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
3203 # long n = MASKED(*rB, 58, 63);
3204 # unsigned_word r = ROTL64(*rS, n);
3205 # long e = (me_5 << 4) | me_0_4;
3206 # unsigned_word m = MASK(0, e);
3207 # signed_word result = r & m;
3209 # CR0_COMPARE(result, 0, Rc);
3211 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
3212 long n = MASKED(*rB, 59, 63);
3213 unsigned32 r = ROTL32(*rS, n);
3214 unsigned32 m = MASK(MB+32, ME+32);
3215 signed_word result = r & m;
3217 CR0_COMPARE(result, 0, Rc);
3219 0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert
3220 # long n = (sh_5 << 4) | sh_0_4;
3221 # unsigned_word r = ROTL64(*rS, n);
3222 # long b = (mb_5 << 4) | mb_0_4;
3223 # unsigned_word m = MASK(b, (64-n));
3224 # signed_word result = (r & m) | (*rA & ~m)
3226 # CR0_COMPARE(result, 0, Rc);
3228 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
3229 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3230 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3231 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3232 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3234 unsigned32 r = ROTL32(*rS, n);
3235 unsigned32 m = MASK(MB+32, ME+32);
3236 signed_word result = (r & m) | (*rA & ~m);
3238 ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
3239 n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
3240 (unsigned long)result));
3241 CR0_COMPARE(result, 0, Rc);
3242 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3245 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
3247 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
3248 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3249 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3250 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3251 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3252 int n = MASKED(*rB, 58, 63);
3253 unsigned32 source = *rS;
3254 signed_word shifted;
3256 shifted = (source << n);
3260 CR0_COMPARE(shifted, 0, Rc);
3262 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3263 n, (unsigned long)source, (unsigned long)shifted));
3264 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3266 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3268 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3269 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3270 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3271 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3272 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3273 int n = MASKED(*rB, 58, 63);
3274 unsigned32 source = *rS;
3275 signed_word shifted;
3277 shifted = (source >> n);
3281 CR0_COMPARE(shifted, 0, Rc);
3283 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3284 n, (unsigned long)source, (unsigned long)shifted));
3285 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3287 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3289 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3290 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3291 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3292 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3293 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3295 signed_word r = ROTL32(*rS, /*64*/32-n);
3296 signed_word m = MASK(n+32, 63);
3297 int S = MASKED(*rS, 32, 32);
3298 signed_word shifted = (r & m) | (S ? ~m : 0);
3300 if (S && ((r & ~m) & MASK(32, 63)) != 0)
3304 CR0_COMPARE(shifted, 0, Rc);
3305 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3306 (long)*rA, (long)*rA, (long)XER));
3307 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3309 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3311 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3312 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3313 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3314 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3315 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3317 int n = MASKED(*rB, 59, 63);
3318 signed32 source = (signed32)*rS; /* signed to keep sign bit */
3319 signed32 shifted = source >> n;
3320 int S = (MASKED(*rS,32,32) != 0);
3321 signed64 r = ((unsigned64) source);
3322 r = ((unsigned64) source) << 32 | (unsigned32) source;
3324 if (MASKED(*rB,58,58) == 0)
3325 mask = (unsigned64) MASK64(n+32,63);
3327 mask = (unsigned64) 0;
3328 *rA = (signed_word) (r & mask | ((signed64) -1*S) & ~mask); /* if 64bit will sign extend */
3329 if (S && (MASKED(r & ~mask,32,63)!=0))
3333 CR0_COMPARE(*rA, 0, Rc);
3334 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3335 (long)*rA, (long)*rA, (long)XER));
3336 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3339 # I.3.3.14 Move to/from System Register Instructions
3342 0.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3343 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3344 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3345 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3346 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3347 int n = (SPR{5:9} << 5) | SPR{0:4};
3348 if (SPR{0} && IS_PROBLEM_STATE(processor))
3349 program_interrupt(processor, cia,
3350 privileged_instruction_program_interrupt);
3351 else if (!spr_is_valid(n)
3352 || spr_is_readonly(n))
3353 program_interrupt(processor, cia,
3354 illegal_instruction_program_interrupt);
3356 spreg new_val = (spr_length(n) == 64
3358 : MASKED(*rS, 32, 63));
3359 /* HACK - time base registers need to be updated immediatly */
3360 if (WITH_TIME_BASE) {
3363 cpu_set_time_base(processor,
3364 (MASKED64(cpu_get_time_base(processor), 32, 63)
3365 | INSERTED64(new_val, 0, 31)));
3368 cpu_set_time_base(processor,
3369 (MASKED64(cpu_get_time_base(processor), 0, 31)
3370 | INSERTED64(new_val, 32, 63)));
3373 cpu_set_decrementer(processor, new_val);
3384 PPC_INSN_TO_SPR(RS_BITMASK, n);
3386 0.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3387 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3388 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3389 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3390 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3391 int n = (SPR{5:9} << 5) | SPR{0:4};
3392 if (SPR{0} && IS_PROBLEM_STATE(processor))
3393 program_interrupt(processor, cia,
3394 privileged_instruction_program_interrupt);
3395 else if (!spr_is_valid(n))
3396 program_interrupt(processor, cia,
3397 illegal_instruction_program_interrupt);
3399 /* HACK - time base registers need to be calculated */
3400 if (WITH_TIME_BASE) {
3403 *rT = cpu_get_decrementer(processor);
3406 if (is_64bit_implementation) *rT = TB;
3407 else *rT = EXTRACTED64(TB, 32, 63);
3410 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
3411 else *rT = EXTRACTED64(TB, 0, 31);
3415 /* NOTE - these SPR's are not readable. Use mftb[ul] */
3425 PPC_INSN_FROM_SPR(RT_BITMASK, n);
3427 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3428 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3429 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3430 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3431 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3436 unsigned_word mask = 0;
3438 for (f = 0; f < 8; f++) {
3439 if (FXM & (0x80 >> f))
3440 mask |= (0xf << 4*(7-f));
3442 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3444 PPC_INSN_MTCR(RS_BITMASK, FXM);
3446 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3447 # CR_SET(BF, EXTRACTED32(XER, 0, 3));
3448 # MBLIT32(XER, 0, 3, 0);
3450 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3451 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3452 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3453 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3454 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3455 *rT = (unsigned32)CR;
3456 PPC_INSN_MFCR(RT_BITMASK);
3459 # I.4.6.2 Floating-Point Load Instructions
3462 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3463 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3464 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3465 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3466 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3472 *frT = DOUBLE(MEM(unsigned, EA, 4));
3473 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3475 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3476 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3477 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3478 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3479 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3485 *frT = DOUBLE(MEM(unsigned, EA, 4));
3486 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3488 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3489 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3490 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3491 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3492 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3495 program_interrupt(processor, cia,
3496 illegal_instruction_program_interrupt);
3498 *frT = DOUBLE(MEM(unsigned, EA, 4));
3500 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3502 0.31,6.FRT,11.RA,16.RB,21.567,31./:X:f::Load Floating-Point Single with Update Indexed
3503 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3504 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3505 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3506 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3509 program_interrupt(processor, cia,
3510 illegal_instruction_program_interrupt);
3512 *frT = DOUBLE(MEM(unsigned, EA, 4));
3514 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3516 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3517 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3518 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3519 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3520 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3526 *frT = MEM(unsigned, EA, 8);
3527 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3529 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3530 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3531 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3532 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3533 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3539 *frT = MEM(unsigned, EA, 8);
3540 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3542 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3543 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3544 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3545 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3546 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3549 program_interrupt(processor, cia,
3550 illegal_instruction_program_interrupt);
3552 *frT = MEM(unsigned, EA, 8);
3554 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3556 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3557 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3558 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3559 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3560 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3563 program_interrupt(processor, cia,
3564 illegal_instruction_program_interrupt);
3566 *frT = MEM(unsigned, EA, 8);
3568 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3572 # I.4.6.3 Floating-Point Store Instructions
3575 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3576 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3577 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3578 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3579 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3585 STORE(EA, 4, SINGLE(*frS));
3586 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3588 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3589 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3590 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3591 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3592 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3598 STORE(EA, 4, SINGLE(*frS));
3599 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3601 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3602 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3603 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3604 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3605 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3608 program_interrupt(processor, cia,
3609 illegal_instruction_program_interrupt);
3611 STORE(EA, 4, SINGLE(*frS));
3613 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3615 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3616 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3617 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3618 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3619 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3622 program_interrupt(processor, cia,
3623 illegal_instruction_program_interrupt);
3625 STORE(EA, 4, SINGLE(*frS));
3627 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3629 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3631 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3632 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3633 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3640 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3642 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3643 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3644 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3645 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3646 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3653 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3655 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point Integer Word Indexed
3656 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3657 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3658 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3665 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3667 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3668 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3669 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3670 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3671 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3674 program_interrupt(processor, cia,
3675 illegal_instruction_program_interrupt);
3679 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3681 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3682 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3683 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3684 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3685 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3688 program_interrupt(processor, cia,
3689 illegal_instruction_program_interrupt);
3693 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3697 # I.4.6.4 Floating-Point Move Instructions
3700 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3701 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3702 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3703 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3704 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3707 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3709 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3710 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3711 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3712 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3713 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3714 *frT = *frB ^ BIT64(0);
3716 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3718 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3719 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3720 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3721 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3722 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3723 *frT = *frB & ~BIT64(0);
3725 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3727 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3728 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3729 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3730 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3731 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3732 *frT = *frB | BIT64(0);
3734 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3738 # I.4.6.5 Floating-Point Arithmetic Instructions
3741 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3742 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3743 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3744 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3745 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3747 if (is_invalid_operation(processor, cia,
3749 fpscr_vxsnan | fpscr_vxisi,
3752 invalid_arithemetic_operation(processor, cia,
3754 0, /*instruction_is_frsp*/
3755 0, /*instruction_is_convert_to_64bit*/
3756 0, /*instruction_is_convert_to_32bit*/
3757 0); /*single-precision*/
3761 double s = *(double*)frA + *(double*)frB;
3765 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3767 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3768 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3769 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3770 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3771 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3773 if (is_invalid_operation(processor, cia,
3775 fpscr_vxsnan | fpscr_vxisi,
3778 invalid_arithemetic_operation(processor, cia,
3780 0, /*instruction_is_frsp*/
3781 0, /*instruction_is_convert_to_64bit*/
3782 0, /*instruction_is_convert_to_32bit*/
3783 1); /*single-precision*/
3787 float s = *(double*)frA + *(double*)frB;
3791 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3793 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3794 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3795 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3796 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3797 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3799 if (is_invalid_operation(processor, cia,
3801 fpscr_vxsnan | fpscr_vxisi,
3804 invalid_arithemetic_operation(processor, cia,
3806 0, /*instruction_is_frsp*/
3807 0, /*instruction_is_convert_to_64bit*/
3808 0, /*instruction_is_convert_to_32bit*/
3809 0); /*single-precision*/
3813 double s = *(double*)frA - *(double*)frB;
3817 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3819 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3820 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3821 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3822 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3823 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3825 if (is_invalid_operation(processor, cia,
3827 fpscr_vxsnan | fpscr_vxisi,
3830 invalid_arithemetic_operation(processor, cia,
3832 0, /*instruction_is_frsp*/
3833 0, /*instruction_is_convert_to_64bit*/
3834 0, /*instruction_is_convert_to_32bit*/
3835 1); /*single-precision*/
3839 float s = *(double*)frA - *(double*)frB;
3843 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3845 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3846 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3847 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3848 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3849 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3851 if (is_invalid_operation(processor, cia,
3853 fpscr_vxsnan | fpscr_vximz,
3856 invalid_arithemetic_operation(processor, cia,
3858 0, /*instruction_is_frsp*/
3859 0, /*instruction_is_convert_to_64bit*/
3860 0, /*instruction_is_convert_to_32bit*/
3861 0); /*single-precision*/
3865 double s = *(double*)frA * *(double*)frC;
3869 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3871 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3872 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3873 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3874 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3875 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3877 if (is_invalid_operation(processor, cia,
3879 fpscr_vxsnan | fpscr_vximz,
3882 invalid_arithemetic_operation(processor, cia,
3884 0, /*instruction_is_frsp*/
3885 0, /*instruction_is_convert_to_64bit*/
3886 0, /*instruction_is_convert_to_32bit*/
3887 1); /*single-precision*/
3891 float s = *(double*)frA * *(double*)frC;
3895 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3897 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3898 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3899 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3900 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3901 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3903 if (is_invalid_operation(processor, cia,
3905 fpscr_vxsnan | fpscr_vxzdz,
3908 invalid_arithemetic_operation(processor, cia,
3910 0, /*instruction_is_frsp*/
3911 0, /*instruction_is_convert_to_64bit*/
3912 0, /*instruction_is_convert_to_32bit*/
3913 0); /*single-precision*/
3915 else if (is_invalid_zero_divide (processor, cia,
3918 invalid_zero_divide_operation (processor, cia,
3924 double s = *(double*)frA / *(double*)frB;
3928 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3930 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3931 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3932 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3933 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3934 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3936 if (is_invalid_operation(processor, cia,
3938 fpscr_vxsnan | fpscr_vxzdz,
3941 invalid_arithemetic_operation(processor, cia,
3943 0, /*instruction_is_frsp*/
3944 0, /*instruction_is_convert_to_64bit*/
3945 0, /*instruction_is_convert_to_32bit*/
3946 1); /*single-precision*/
3948 else if (is_invalid_zero_divide (processor, cia,
3951 invalid_zero_divide_operation (processor, cia,
3957 float s = *(double*)frA / *(double*)frB;
3961 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3963 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3964 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3965 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3966 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3967 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3969 double product; /*HACK! - incorrectly loosing precision ... */
3970 /* compute the multiply */
3971 if (is_invalid_operation(processor, cia,
3973 fpscr_vxsnan | fpscr_vximz,
3976 union { double d; unsigned64 u; } tmp;
3977 invalid_arithemetic_operation(processor, cia,
3978 &tmp.u, *frA, 0, *frC,
3979 0, /*instruction_is_frsp*/
3980 0, /*instruction_is_convert_to_64bit*/
3981 0, /*instruction_is_convert_to_32bit*/
3982 0); /*single-precision*/
3987 product = *(double*)frA * *(double*)frC;
3989 /* compute the add */
3990 if (is_invalid_operation(processor, cia,
3992 fpscr_vxsnan | fpscr_vxisi,
3995 invalid_arithemetic_operation(processor, cia,
3996 frT, product, *frB, 0,
3997 0, /*instruction_is_frsp*/
3998 0, /*instruction_is_convert_to_64bit*/
3999 0, /*instruction_is_convert_to_32bit*/
4000 0); /*single-precision*/
4004 double s = product + *(double*)frB;
4008 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4010 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
4011 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4012 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4013 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4014 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4016 float product; /*HACK! - incorrectly loosing precision ... */
4017 /* compute the multiply */
4018 if (is_invalid_operation(processor, cia,
4020 fpscr_vxsnan | fpscr_vximz,
4023 union { double d; unsigned64 u; } tmp;
4024 invalid_arithemetic_operation(processor, cia,
4025 &tmp.u, *frA, 0, *frC,
4026 0, /*instruction_is_frsp*/
4027 0, /*instruction_is_convert_to_64bit*/
4028 0, /*instruction_is_convert_to_32bit*/
4029 0); /*single-precision*/
4034 product = *(double*)frA * *(double*)frC;
4036 /* compute the add */
4037 if (is_invalid_operation(processor, cia,
4039 fpscr_vxsnan | fpscr_vxisi,
4042 invalid_arithemetic_operation(processor, cia,
4043 frT, product, *frB, 0,
4044 0, /*instruction_is_frsp*/
4045 0, /*instruction_is_convert_to_64bit*/
4046 0, /*instruction_is_convert_to_32bit*/
4047 0); /*single-precision*/
4051 float s = product + *(double*)frB;
4052 *(double*)frT = (double)s;
4055 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4057 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
4058 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4059 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4060 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4061 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4063 double product; /*HACK! - incorrectly loosing precision ... */
4064 /* compute the multiply */
4065 if (is_invalid_operation(processor, cia,
4067 fpscr_vxsnan | fpscr_vximz,
4070 union { double d; unsigned64 u; } tmp;
4071 invalid_arithemetic_operation(processor, cia,
4072 &tmp.u, *frA, 0, *frC,
4073 0, /*instruction_is_frsp*/
4074 0, /*instruction_is_convert_to_64bit*/
4075 0, /*instruction_is_convert_to_32bit*/
4076 0); /*single-precision*/
4081 product = *(double*)frA * *(double*)frC;
4083 /* compute the subtract */
4084 if (is_invalid_operation(processor, cia,
4086 fpscr_vxsnan | fpscr_vxisi,
4089 invalid_arithemetic_operation(processor, cia,
4090 frT, product, *frB, 0,
4091 0, /*instruction_is_frsp*/
4092 0, /*instruction_is_convert_to_64bit*/
4093 0, /*instruction_is_convert_to_32bit*/
4094 0); /*single-precision*/
4098 double s = product - *(double*)frB;
4102 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4104 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
4105 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4106 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4107 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4108 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4110 float product; /*HACK! - incorrectly loosing precision ... */
4111 /* compute the multiply */
4112 if (is_invalid_operation(processor, cia,
4114 fpscr_vxsnan | fpscr_vximz,
4117 union { double d; unsigned64 u; } tmp;
4118 invalid_arithemetic_operation(processor, cia,
4119 &tmp.u, *frA, 0, *frC,
4120 0, /*instruction_is_frsp*/
4121 0, /*instruction_is_convert_to_64bit*/
4122 0, /*instruction_is_convert_to_32bit*/
4123 0); /*single-precision*/
4128 product = *(double*)frA * *(double*)frC;
4130 /* compute the subtract */
4131 if (is_invalid_operation(processor, cia,
4133 fpscr_vxsnan | fpscr_vxisi,
4136 invalid_arithemetic_operation(processor, cia,
4137 frT, product, *frB, 0,
4138 0, /*instruction_is_frsp*/
4139 0, /*instruction_is_convert_to_64bit*/
4140 0, /*instruction_is_convert_to_32bit*/
4141 0); /*single-precision*/
4145 float s = product - *(double*)frB;
4146 *(double*)frT = (double)s;
4149 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4151 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
4152 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4153 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4154 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4155 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4157 double product; /*HACK! - incorrectly loosing precision ... */
4158 /* compute the multiply */
4159 if (is_invalid_operation(processor, cia,
4161 fpscr_vxsnan | fpscr_vximz,
4164 union { double d; unsigned64 u; } tmp;
4165 invalid_arithemetic_operation(processor, cia,
4166 &tmp.u, *frA, 0, *frC,
4167 0, /*instruction_is_frsp*/
4168 0, /*instruction_is_convert_to_64bit*/
4169 0, /*instruction_is_convert_to_32bit*/
4170 0); /*single-precision*/
4175 product = *(double*)frA * *(double*)frC;
4177 /* compute the add */
4178 if (is_invalid_operation(processor, cia,
4180 fpscr_vxsnan | fpscr_vxisi,
4183 invalid_arithemetic_operation(processor, cia,
4184 frT, product, *frB, 0,
4185 0, /*instruction_is_frsp*/
4186 0, /*instruction_is_convert_to_64bit*/
4187 0, /*instruction_is_convert_to_32bit*/
4188 0); /*single-precision*/
4192 double s = -(product + *(double*)frB);
4196 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4198 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4199 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4200 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4201 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4202 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4204 float product; /*HACK! - incorrectly loosing precision ... */
4205 /* compute the multiply */
4206 if (is_invalid_operation(processor, cia,
4208 fpscr_vxsnan | fpscr_vximz,
4211 union { double d; unsigned64 u; } tmp;
4212 invalid_arithemetic_operation(processor, cia,
4213 &tmp.u, *frA, 0, *frC,
4214 0, /*instruction_is_frsp*/
4215 0, /*instruction_is_convert_to_64bit*/
4216 0, /*instruction_is_convert_to_32bit*/
4217 0); /*single-precision*/
4222 product = *(double*)frA * *(double*)frC;
4224 /* compute the add */
4225 if (is_invalid_operation(processor, cia,
4227 fpscr_vxsnan | fpscr_vxisi,
4230 invalid_arithemetic_operation(processor, cia,
4231 frT, product, *frB, 0,
4232 0, /*instruction_is_frsp*/
4233 0, /*instruction_is_convert_to_64bit*/
4234 0, /*instruction_is_convert_to_32bit*/
4235 0); /*single-precision*/
4239 float s = -(product + *(double*)frB);
4240 *(double*)frT = (double)s;
4243 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4245 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4246 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4247 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4248 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4249 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4251 double product; /*HACK! - incorrectly loosing precision ... */
4252 /* compute the multiply */
4253 if (is_invalid_operation(processor, cia,
4255 fpscr_vxsnan | fpscr_vximz,
4258 union { double d; unsigned64 u; } tmp;
4259 invalid_arithemetic_operation(processor, cia,
4260 &tmp.u, *frA, 0, *frC,
4261 0, /*instruction_is_frsp*/
4262 0, /*instruction_is_convert_to_64bit*/
4263 0, /*instruction_is_convert_to_32bit*/
4264 0); /*single-precision*/
4269 product = *(double*)frA * *(double*)frC;
4271 /* compute the subtract */
4272 if (is_invalid_operation(processor, cia,
4274 fpscr_vxsnan | fpscr_vxisi,
4277 invalid_arithemetic_operation(processor, cia,
4278 frT, product, *frB, 0,
4279 0, /*instruction_is_frsp*/
4280 0, /*instruction_is_convert_to_64bit*/
4281 0, /*instruction_is_convert_to_32bit*/
4282 0); /*single-precision*/
4286 double s = -(product - *(double*)frB);
4290 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4292 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4293 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4294 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4295 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4296 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4298 float product; /*HACK! - incorrectly loosing precision ... */
4299 /* compute the multiply */
4300 if (is_invalid_operation(processor, cia,
4302 fpscr_vxsnan | fpscr_vximz,
4305 union { double d; unsigned64 u; } tmp;
4306 invalid_arithemetic_operation(processor, cia,
4307 &tmp.u, *frA, 0, *frC,
4308 0, /*instruction_is_frsp*/
4309 0, /*instruction_is_convert_to_64bit*/
4310 0, /*instruction_is_convert_to_32bit*/
4311 0); /*single-precision*/
4316 product = *(double*)frA * *(double*)frC;
4318 /* compute the subtract */
4319 if (is_invalid_operation(processor, cia,
4321 fpscr_vxsnan | fpscr_vxisi,
4324 invalid_arithemetic_operation(processor, cia,
4325 frT, product, *frB, 0,
4326 0, /*instruction_is_frsp*/
4327 0, /*instruction_is_convert_to_64bit*/
4328 0, /*instruction_is_convert_to_32bit*/
4329 0); /*single-precision*/
4333 float s = -(product - *(double*)frB);
4334 *(double*)frT = (double)s;
4337 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4341 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
4344 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4345 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4346 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4347 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4348 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4351 unsigned64 frac_grx;
4353 /* split off cases for what to do */
4354 if (EXTRACTED64(*frB, 1, 11) < 897
4355 && EXTRACTED64(*frB, 1, 63) > 0) {
4356 if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4357 if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4359 if (EXTRACTED64(*frB, 1, 11) > 1150
4360 && EXTRACTED64(*frB, 1, 11) < 2047) {
4361 if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4362 if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4364 if (EXTRACTED64(*frB, 1, 11) > 896
4365 && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4366 if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4367 if (EXTRACTED64(*frB, 1, 11) == 2047) {
4368 if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4369 if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4370 if (EXTRACTED64(*frB, 12, 12) == 0
4371 && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4374 LABEL(Disabled_Exponent_Underflow):
4375 sign = EXTRACTED64(*frB, 0, 0);
4376 if (EXTRACTED64(*frB, 1, 11) == 0) {
4378 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4380 if (EXTRACTED64(*frB, 1, 11) > 0) {
4381 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4382 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4384 /* G|R|X == zero from above */
4385 while (exp < -126) {
4387 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4388 | MASKED64(frac_grx, 55, 55));
4390 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4391 Round_Single(processor, sign, &exp, &frac_grx);
4392 FPSCR_SET_XX(FPSCR & fpscr_fi);
4393 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4394 *frT = INSERTED64(sign, 0, 0);
4395 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4396 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4398 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4399 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4400 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4401 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4403 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4404 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4405 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4407 /*Normalize_Operand:*/
4408 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4410 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4412 *frT = (INSERTED64(sign, 0, 0)
4413 | INSERTED64(exp + 1023, 1, 11)
4414 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4418 LABEL(Enabled_Exponent_Underflow):
4420 sign = EXTRACTED64(*frB, 0, 0);
4421 if (EXTRACTED64(*frB, 1, 11) == 0) {
4423 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4425 if (EXTRACTED64(*frB, 1, 11) > 0) {
4426 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4427 frac_grx = (BIT64(0) |
4428 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4430 /*Normalize_Operand:*/
4431 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4433 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4435 Round_Single(processor, sign, &exp, &frac_grx);
4436 FPSCR_SET_XX(FPSCR & fpscr_fi);
4438 *frT = (INSERTED64(sign, 0, 0)
4439 | INSERTED64(exp + 1023, 1, 11)
4440 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4441 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4442 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4445 LABEL(Disabled_Exponent_Overflow):
4447 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4448 if (EXTRACTED64(*frB, 0, 0) == 0) {
4449 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4450 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4452 if (EXTRACTED64(*frB, 0, 0) == 1) {
4453 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4454 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4457 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4458 if (EXTRACTED64(*frB, 0, 0) == 0) {
4459 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4460 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4462 if (EXTRACTED64(*frB, 0, 0) == 1) {
4463 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4464 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4467 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4468 if (EXTRACTED64(*frB, 0, 0) == 0) {
4469 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4470 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4472 if (EXTRACTED64(*frB, 0, 0) == 1) {
4473 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4474 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4477 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4478 if (EXTRACTED64(*frB, 0, 0) == 0) {
4479 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4480 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4482 if (EXTRACTED64(*frB, 0, 0) == 1) {
4483 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4484 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4487 /* FPSCR[FR] <- undefined */
4492 LABEL(Enabled_Exponent_Overflow):
4493 sign = EXTRACTED64(*frB, 0, 0);
4494 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4495 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4496 Round_Single(processor, sign, &exp, &frac_grx);
4497 FPSCR_SET_XX(FPSCR & fpscr_fi);
4499 LABEL(Enabled_Overflow):
4502 *frT = (INSERTED64(sign, 0, 0)
4503 | INSERTED64(exp + 1023, 1, 11)
4504 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4505 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4506 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4509 LABEL(Zero_Operand):
4511 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4512 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4517 LABEL(Infinity_Operand):
4519 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4520 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4525 LABEL(QNaN_Operand):
4526 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4527 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4532 LABEL(SNaN_Operand):
4533 FPSCR_OR_VX(fpscr_vxsnan);
4534 if ((FPSCR & fpscr_ve) == 0) {
4535 *frT = (MASKED64(*frB, 0, 11)
4537 | MASKED64(*frB, 13, 34));
4538 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4544 LABEL(Normal_Operand):
4545 sign = EXTRACTED64(*frB, 0, 0);
4546 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4547 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4548 Round_Single(processor, sign, &exp, &frac_grx);
4549 FPSCR_SET_XX(FPSCR & fpscr_fi);
4550 if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4551 if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4552 *frT = (INSERTED64(sign, 0, 0)
4553 | INSERTED64(exp + 1023, 1, 11)
4554 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4555 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4556 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4560 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4563 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4564 floating_point_assist_interrupt(processor, cia);
4566 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4567 floating_point_assist_interrupt(processor, cia);
4569 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4570 floating_point_assist_interrupt(processor, cia);
4572 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4573 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4574 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4575 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4576 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4578 convert_to_integer(processor, cia,
4580 fpscr_rn_round_towards_zero, 32);
4582 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4584 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4585 int sign = EXTRACTED64(*frB, 0, 0);
4587 unsigned64 frac = *frB;
4589 if (frac == 0) GOTO(Zero_Operand);
4590 if (sign == 1) frac = ~frac + 1;
4591 while (EXTRACTED64(frac, 0, 0) == 0) {
4592 /*??? do the loop 0 times if (FRB) = max negative integer */
4593 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4596 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4597 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4598 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4599 *frT = (INSERTED64(sign, 0, 0)
4600 | INSERTED64(exp + 1023, 1, 11)
4601 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4604 LABEL(Zero_Operand):
4607 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4612 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4616 # I.4.6.7 Floating-Point Compare Instructions
4619 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4620 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4621 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4622 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4623 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4626 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4627 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4628 else if (is_less_than(frA, frB))
4629 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4630 else if (is_greater_than(frA, frB))
4631 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4633 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4635 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4636 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4637 FPSCR_OR_VX(fpscr_vxsnan);
4639 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4641 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4642 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4643 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4644 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4645 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4648 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4649 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4650 else if (is_less_than(frA, frB))
4651 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4652 else if (is_greater_than(frA, frB))
4653 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4655 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4657 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4658 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4659 FPSCR_OR_VX(fpscr_vxsnan);
4660 if ((FPSCR & fpscr_ve) == 0)
4661 FPSCR_OR_VX(fpscr_vxvc);
4663 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4664 FPSCR_OR_VX(fpscr_vxvc);
4667 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4671 # I.4.6.8 Floating-Point Status and Control Register Instructions
4674 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4679 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4681 unsigned field = FPSCR_FIELD(BFA);
4683 FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
4686 0.63,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4691 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4694 for (i = 0; i < 8; i++) {
4695 if ((FLM & BIT8(i))) {
4696 FPSCR &= ~MASK32(i*4, i*4+3);
4697 FPSCR |= MASKED32(*frB, i*4, i*4+3);
4702 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4704 unsigned32 bit = BIT32(BT);
4708 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4710 unsigned32 bit = BIT32(BT);
4713 if ((bit & fpscr_vx_bits))
4715 /* note - omit vx bit */
4716 if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
4722 # I.A.1.2 Floating-Point Arithmetic Instructions
4725 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4726 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4728 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4729 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4731 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4732 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4734 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4735 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4738 # I.A.1.3 Floating-Point Select Instruction
4741 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4742 *601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
4743 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4744 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4745 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4746 if (CURRENT_MODEL == MODEL_ppc601) {
4747 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4749 unsigned64 zero = 0;
4751 if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4754 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4758 # II.3.2 Cache Management Instructions
4761 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4762 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4763 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4764 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4765 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4766 /* blindly flush all instruction cache entries */
4767 #if WITH_IDECODE_CACHE_SIZE
4768 cpu_flush_icache(processor);
4770 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4772 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4773 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4774 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4775 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4776 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4777 cpu_synchronize_context(processor, cia);
4778 PPC_INSN_INT(0, 0, 0);
4782 # II.3.2.2 Data Cache Instructions
4785 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4786 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4787 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4788 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4789 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4790 TRACE(trace_tbd,("Data Cache Block Touch\n"));
4791 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4793 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4794 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4795 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4796 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4797 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4798 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4799 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4801 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4802 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4803 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4804 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4805 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4806 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4807 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4809 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4810 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4811 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4812 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4813 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4814 TRACE(trace_tbd,("Data Cache Block Store\n"));
4815 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4817 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4818 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4819 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4820 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4821 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4822 TRACE(trace_tbd,("Data Cache Block Flush\n"));
4823 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4826 # II.3.3 Enforce In-order Execution of I/O Instruction
4829 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4830 /* Since this model has no instruction overlap
4831 this instruction need do nothing */
4834 # II.4.1 Time Base Instructions
4837 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4838 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4839 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4840 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4841 int n = (tbr{5:9} << 5) | tbr{0:4};
4843 if (is_64bit_implementation) *rT = TB;
4844 else *rT = EXTRACTED64(TB, 32, 63);
4846 else if (n == 269) {
4847 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4848 else *rT = EXTRACTED64(TB, 0, 31);
4851 program_interrupt(processor, cia,
4852 illegal_instruction_program_interrupt);
4856 # III.2.3.1 System Linkage Instructions
4859 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4860 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4861 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4862 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4863 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4864 if (IS_PROBLEM_STATE(processor)) {
4865 program_interrupt(processor, cia,
4866 privileged_instruction_program_interrupt);
4869 MSR = (MASKED(SRR1, 0, 32)
4870 | MASKED(SRR1, 37, 41)
4871 | MASKED(SRR1, 48, 63));
4872 NIA = MASKED(SRR0, 0, 61);
4873 cpu_synchronize_context(processor, cia);
4874 check_masked_interrupts(processor);
4878 # III.3.4.1 Move to/from System Register Instructions
4881 #0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4882 #0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
4883 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4884 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4885 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4886 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4887 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4888 if (IS_PROBLEM_STATE(processor))
4889 program_interrupt(processor, cia,
4890 privileged_instruction_program_interrupt);
4893 check_masked_interrupts(processor);
4896 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4897 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4898 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4899 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4900 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4901 if (IS_PROBLEM_STATE(processor))
4902 program_interrupt(processor, cia,
4903 privileged_instruction_program_interrupt);
4906 check_masked_interrupts(processor);
4911 # III.4.11.1 Cache Management Instructions
4914 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4915 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4916 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4917 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4918 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4919 if (IS_PROBLEM_STATE(processor))
4920 program_interrupt(processor, cia,
4921 privileged_instruction_program_interrupt);
4923 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4926 # III.4.11.2 Segment Register Manipulation Instructions
4929 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4930 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4931 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4932 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4933 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4934 if (IS_PROBLEM_STATE(processor))
4935 program_interrupt(processor, cia,
4936 privileged_instruction_program_interrupt);
4940 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4941 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4942 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4943 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4944 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4945 if (IS_PROBLEM_STATE(processor))
4946 program_interrupt(processor, cia,
4947 privileged_instruction_program_interrupt);
4949 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4951 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4952 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4953 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4954 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4955 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4956 if (IS_PROBLEM_STATE(processor))
4957 program_interrupt(processor, cia,
4958 privileged_instruction_program_interrupt);
4962 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4963 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4964 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4965 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4966 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4967 if (IS_PROBLEM_STATE(processor))
4968 program_interrupt(processor, cia,
4969 privileged_instruction_program_interrupt);
4971 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4975 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4978 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4980 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4982 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4983 if (IS_PROBLEM_STATE(processor))
4984 program_interrupt(processor, cia,
4985 privileged_instruction_program_interrupt);
4990 proc = psim_cpu(cpu_system(processor), nr);
4991 if (proc == NULL) break;
4992 cpu_page_tlb_invalidate_entry(proc, *rB);
4997 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4998 if (IS_PROBLEM_STATE(processor))
4999 program_interrupt(processor, cia,
5000 privileged_instruction_program_interrupt);
5005 proc = psim_cpu(cpu_system(processor), nr);
5006 if (proc == NULL) break;
5007 cpu_page_tlb_invalidate_all(proc);
5012 0.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
5013 /* nothing happens here - always in sync */
5016 # III.A.1.2 External Access Instructions
5019 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
5021 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
5023 :include:::altivec.igen
5024 :include:::e500.igen