2 # This file is part of the program psim.
4 # Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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.
41 # 1 Instruction format as a `start-bit,content' pairs.
42 # the content is one of a digit, field name or `/' (aka.0)
46 # 3 Flags: 64 - 64bit only
47 # f - floating point enabled required
54 # For flags marked 'model', the fields are interpreted as follows:
62 # 4 String name for model
64 # 5 Specific CPU model, must be an identifier
66 # 6 Comma separated list of functional units
69 ::model:604:ppc604:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
70 ::model:603e:ppc603e:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
71 ::model:603:ppc603:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
75 typedef enum _ppc_function_unit {
76 PPC_FUNCTION_UNIT_UNKNOWN, /* unknown function unit */
77 PPC_FUNCTION_UNIT_IU, /* integer unit (603 style) */
78 PPC_FUNCTION_UNIT_SRU, /* system register unit (603 style) */
79 PPC_FUNCTION_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
80 PPC_FUNCTION_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
81 PPC_FUNCTION_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
82 PPC_FUNCTION_UNIT_FPU, /* floating point unit */
83 PPC_FUNCTION_UNIT_LSU, /* load/store unit */
84 PPC_FUNCTION_UNIT_BPU, /* branch unit */
88 /* Structure to hold timing information on a per instruction basis */
90 ppc_function_unit first_unit; /* first functional unit this insn could use */
91 ppc_function_unit last_unit; /* last functional unit this insn could use */
92 unsigned16 issue; /* # cycles before function unit can process other insns */
93 unsigned16 done; /* # cycles before insn is done */
94 unsigned32 flags; /* flag bits */
98 #define PPC_LOAD 0x00000001 /* insn is a load */
99 #define PPC_STORE 0x00000002 /* insn is a store */
100 #define PPC_SERIALIZE 0x00000004 /* insn forces serialization */
102 /* Structure to hold the current state information for the simulated CPU model */
104 const char *name; /* model name */
105 const model_time *timing; /* timing information */
106 unsigned_word old_program_counter; /* previous PC */
107 unsigned nr_branches; /* # branches */
108 unsigned nr_units[nr_ppc_function_units]; /* function unit counts */
109 unsigned16 busy[nr_ppc_function_units]; /* how long until free */
112 STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
113 "unknown functional unit",
114 "integer functional unit",
115 "system register functional unit",
116 "1st single cycle integer functional unit",
117 "2nd single cycle integer functional unit",
118 "multiple cycle integer functional unit",
119 "floating point functional unit",
120 "load/store functional unit",
121 "branch functional unit",
124 model_data *::model-function::model_create:cpu *processor
125 if (CURRENT_MODEL == MODEL_NONE)
126 return (model_data *)0;
128 model_data *model_ptr = ZALLOC(model_data);
129 model_ptr->name = model_name[CURRENT_MODEL];
130 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
134 void::model-function::model_init:cpu *processor, model_data *model_ptr
135 void::model-function::model_halt:cpu *processor, model_data *model_ptr
137 void::model-function::model_issue:itable_index index, model_data *model_ptr, unsigned_word cia
138 if (model_ptr->old_program_counter+4 != cia)
139 model_ptr->nr_branches++;
141 model_ptr->old_program_counter = cia;
142 model_ptr->nr_units[ (int)model_ptr->timing[ (int)index ].first_unit ]++;
144 model_print *::model-function::model_mon_info:model_data *model_ptr
149 head = tail = ZALLOC(model_print);
150 tail->count = model_ptr->nr_branches;
151 tail->name = "branch";
152 tail->suffix_plural = "es";
153 tail->suffix_singular = "";
155 for (i = PPC_FUNCTION_UNIT_UNKNOWN; i < nr_ppc_function_units; i++) {
156 if (model_ptr->nr_units[i]) {
157 tail->next = ZALLOC(model_print);
159 tail->count = model_ptr->nr_units[i];
160 tail->name = ppc_function_unit_name[i];
161 tail->suffix_plural = "s";
162 tail->suffix_singular = "";
166 tail->next = (model_print *)0;
169 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
179 # The following (illegal) instruction is `known' by gen and is
180 # called when ever an illegal instruction is encountered
182 program_interrupt(processor, cia,
183 illegal_instruction_program_interrupt);
187 # The following (floating point unavailable) instruction is `known' by gen
188 # and is called when ever an a floating point instruction is to be
189 # executed but floating point is make unavailable by the MSR
190 ::internal::floating_point_unavailable
191 floating_point_unavailable_interrupt(processor, cia);
196 # Floating point support functions
199 # Convert 32bit single to 64bit double
200 unsigned64::function::DOUBLE:unsigned32 WORD
202 if (EXTRACTED32(WORD, 1, 8) > 0
203 && EXTRACTED32(WORD, 1, 8) < 255) {
204 /* normalized operand */
205 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
206 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
207 | INSERTED64(not_word_1_1, 2, 2)
208 | INSERTED64(not_word_1_1, 3, 3)
209 | INSERTED64(not_word_1_1, 4, 4)
210 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
212 else if (EXTRACTED32(WORD, 1, 8) == 0
213 && EXTRACTED32(WORD, 9, 31) != 0) {
214 /* denormalized operand */
215 int sign = EXTRACTED32(WORD, 0, 0);
217 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
218 /* normalize the operand */
219 while (MASKED64(frac, 0, 0) == 0) {
223 FRT = (INSERTED64(sign, 0, 0)
224 | INSERTED64(exp + 1023, 1, 11)
225 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
227 else if (EXTRACTED32(WORD, 1, 8) == 255
228 || EXTRACTED32(WORD, 1, 31) == 0) {
229 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
230 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
231 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
232 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
233 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
236 error("DOUBLE - unknown case\n");
241 # Convert 64bit single to 32bit double
242 unsigned32::function::SINGLE:unsigned64 FRS
244 if (EXTRACTED64(FRS, 1, 11) > 896
245 || EXTRACTED64(FRS, 1, 63) == 0) {
246 /* no denormalization required (includes Zero/Infinity/NaN) */
247 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
248 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
250 else if (874 <= EXTRACTED64(FRS, 1, 11)
251 && EXTRACTED64(FRS, 1, 11) <= 896) {
252 /* denormalization required */
253 int sign = EXTRACTED64(FRS, 0, 0);
254 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
255 unsigned64 frac = (BIT64(0)
256 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
257 /* denormalize the operand */
259 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
262 WORD = (INSERTED32(sign, 0, 0)
263 | INSERTED32(0x00, 1, 8)
264 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
267 WORD = 0x0; /* ??? */
272 # round 64bit double to 64bit but single
273 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
274 /* comparisons ignore u bits */
277 int lsb = EXTRACTED64(*frac_grx, 23, 23);
278 int gbit = EXTRACTED64(*frac_grx, 24, 24);
279 int rbit = EXTRACTED64(*frac_grx, 25, 25);
280 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
281 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
282 if (lsb == 1 && gbit == 1) inc = 1;
283 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
284 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
286 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
287 if (sign == 0 && gbit == 1) inc = 1;
288 if (sign == 0 && rbit == 1) inc = 1;
289 if (sign == 0 && xbit == 1) inc = 1;
291 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
292 if (sign == 1 && gbit == 1) inc = 1;
293 if (sign == 1 && rbit == 1) inc = 1;
294 if (sign == 1 && xbit == 1) inc = 1;
296 /* work out addition in low 25 bits of out */
297 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
298 *frac_grx = INSERTED64(out, 0, 23);
299 if (out & BIT64(64 - 23 - 1 - 1)) {
300 *frac_grx = (BIT64(0) |
301 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
304 /* frac_grx[24:52] = 0 already */
306 FPSCR_SET_FI(gbit || rbit || xbit);
310 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
312 if (round_mode == fpscr_rn_round_to_nearest) {
313 if (*frac64 == 1 && gbit == 1) inc = 1;
314 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
315 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
317 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
318 if (sign == 0 && gbit == 1) inc = 1;
319 if (sign == 0 && rbit == 1) inc = 1;
320 if (sign == 0 && xbit == 1) inc = 1;
322 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
323 if (sign == 1 && gbit == 1) inc = 1;
324 if (sign == 1 && rbit == 1) inc = 1;
325 if (sign == 1 && xbit == 1) inc = 1;
327 /* frac[0:64] = frac[0:64} + inc */
328 *frac += (*frac64 && inc ? 1 : 0);
329 *frac64 = (*frac64 + inc) & 0x1;
331 FPSCR_SET_FI(gbit | rbit | xbit);
334 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
337 int lsb = EXTRACTED64(*frac, 52, 52);
338 int gbit = EXTRACTED64(*frac, 53, 53);
339 int rbit = EXTRACTED64(*frac, 54, 54);
340 int xbit = EXTRACTED64(*frac, 55, 55);
341 if (round_mode == fpscr_rn_round_to_nearest) {
342 if (lsb == 1 && gbit == 1) inc = 1;
343 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
344 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
346 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
347 if (sign == 0 && gbit == 1) inc = 1;
348 if (sign == 0 && rbit == 1) inc = 1;
349 if (sign == 0 && xbit == 1) inc = 1;
351 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
352 if (sign == 1 && gbit == 1) inc = 1;
353 if (sign == 1 && rbit == 1) inc = 1;
354 if (sign == 1 && xbit == 1) inc = 1;
356 /* frac//carry_out = frac + inc */
357 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
358 carry_out = EXTRACTED64(*frac, 0, 0);
360 if (carry_out == 1) *exp = *exp + 1;
362 FPSCR_SET_FI(gbit | rbit | xbit);
363 FPSCR_SET_XX(FPSCR & fpscr_fi);
366 # conversion of FP to integer
367 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
375 int sign = EXTRACTED64(frb, 0, 0);
376 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
377 goto Infinity_Operand;
378 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
380 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
382 if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
383 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
384 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
385 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
386 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
389 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
390 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
393 gbit = 0, rbit = 0, xbit = 0;
394 for (i = 1; i <= 63 - exp; i++) {
398 frac64 = EXTRACTED64(frac, 63, 63);
399 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
401 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
402 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
405 frac += (frac64 ? 1 : 0);
406 frac64 = (frac64 + 1) & 0x1;
408 if (tgt_precision == 32 /* can ignore frac64 in compare */
409 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
411 if (tgt_precision == 64 /* can ignore frac64 in compare */
412 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
414 if (tgt_precision == 32 /* can ignore frac64 in compare */
415 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
417 if (tgt_precision == 64 /* can ignore frac64 in compare */
418 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
420 FPSCR_SET_XX(FPSCR & fpscr_fi);
421 if (tgt_precision == 32)
422 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
423 if (tgt_precision == 64)
424 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
425 /*FPSCR[fprf] = undefined */
431 FPSCR_OR_VX(fpscr_vxcvi);
432 if ((FPSCR & fpscr_ve) == 0) {
433 if (tgt_precision == 32) {
434 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
435 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
438 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
439 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
441 /* FPSCR[FPRF] = undefined */
448 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
449 if ((FPSCR & fpscr_ve) == 0) {
450 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
451 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
452 /* FPSCR[fprf] = undefined */
459 FPSCR_OR_VX(fpscr_vxcvi);
460 if ((FPSCR & fpscr_ve) == 0) {
461 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
462 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
463 /* FPSCR[fprf] = undefined */
470 FPSCR_OR_VX(fpscr_vxcvi);
471 if ((FPSCR & fpscr_ve) == 0) {
472 if (tgt_precision == 32) {
473 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
474 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
477 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
478 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
480 /* FPSCR[fprf] = undefined */
486 # extract out raw fields of a FP number
487 int::function::sign:unsigned64 FRS
488 return (MASKED64(FRS, 0, 0)
491 int::function::biased_exp:unsigned64 frs, int single
493 return EXTRACTED64(frs, 1, 8);
495 return EXTRACTED64(frs, 1, 11);
496 unsigned64::function::fraction:unsigned64 frs, int single
498 return EXTRACTED64(frs, 9, 31);
500 return EXTRACTED64(frs, 12, 63);
502 # a number?, each of the below return +1 or -1 (based on sign bit)
504 int::function::is_nor:unsigned64 frs, int single
505 int exp = biased_exp(frs, single);
507 && exp <= (single ? 254 : 2046));
508 int::function::is_zero:unsigned64 FRS
509 return (MASKED64(FRS, 1, 63) == 0
512 int::function::is_den:unsigned64 frs, int single
513 int exp = biased_exp(frs, single);
514 unsigned64 frac = fraction(frs, single);
515 return (exp == 0 && frac != 0
518 int::function::is_inf:unsigned64 frs, int single
519 int exp = biased_exp(frs, single);
520 int frac = fraction(frs, single);
521 return (exp == (single ? 255 : 2047) && frac == 0
524 int::function::is_NaN:unsigned64 frs, int single
525 int exp = biased_exp(frs, single);
526 int frac = fraction(frs, single);
527 return (exp == (single ? 255 : 2047) && frac != 0
530 int::function::is_SNaN:unsigned64 frs, int single
531 return (is_NaN(frs, single)
532 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
535 int::function::is_QNaN:unsigned64 frs, int single
536 return (is_NaN(frs, single) && !is_SNaN(frs, single));
537 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
538 return *(double*)fra < *(double*)frb;
539 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
540 return *(double*)fra > *(double*)frb;
541 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
542 return *(double*)fra == *(double*)frb;
545 # which quiet nan should become the result
546 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
548 if (is_NaN(fra, single))
550 else if (is_NaN(frb, single))
551 if (instruction_is_frsp)
552 frt = MASKED64(frb, 0, 34);
555 else if (is_NaN(frc, single))
557 else if (generate_qnan)
558 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
560 error("select_qnan - default reached\n");
564 # detect invalid operation
565 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
567 if ((check & fpscr_vxsnan)
568 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
569 FPSCR_OR_VX(fpscr_vxsnan);
572 if ((check & fpscr_vxisi)
573 && (is_inf(fra, single) && is_inf(frb, single))
574 && ((negate && sign(fra) != sign(frb))
575 || (!negate && sign(fra) == sign(frb)))) {
576 /*FIXME: don't handle inf-inf VS inf+-inf */
577 FPSCR_OR_VX(fpscr_vxisi);
580 if ((check & fpscr_vxidi)
581 && (is_inf(fra, single) && is_inf(frb, single))) {
582 FPSCR_OR_VX(fpscr_vxidi);
585 if ((check & fpscr_vxzdz)
586 && (is_zero(fra) && is_zero(frb))) {
587 FPSCR_OR_VX(fpscr_vxzdz);
590 if ((check & fpscr_vximz)
591 && (is_zero(fra) && is_inf(frb, single))) {
592 FPSCR_OR_VX(fpscr_vximz);
595 if ((check & fpscr_vxvc)
596 && (is_NaN(fra, single) || is_NaN(frb, single))) {
597 FPSCR_OR_VX(fpscr_vxvc);
600 if ((check & fpscr_vxsoft)) {
601 FPSCR_OR_VX(fpscr_vxsoft);
604 if ((check & fpscr_vxsqrt)
606 FPSCR_OR_VX(fpscr_vxsqrt);
609 /* if ((check && fpscr_vxcvi) {
610 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
611 FPSCR_OR_VX(fpscr_vxcvi);
621 # handle case of invalid operation
622 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
623 if (FPSCR & fpscr_ve) {
624 /* invalid operation exception enabled */
628 /* fpscr_FPRF unchanged */
631 /* invalid operation exception disabled */
632 if (instruction_is_convert_to_64bit) {
635 else if (instruction_is_convert_to_32bit) {
638 else { /* arrith, frsp */
639 *frt = select_qnan(fra, frb, frc,
640 instruction_is_frsp, 0/*generate*/, single);
643 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
651 # I.2.4.1 Branch Instructions
653 0.18,6.LI,30.AA,31.LK:I:t::Branch
654 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
655 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
656 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
657 if (AA) NIA = IEA(EXTS(LI_0b00));
658 else NIA = IEA(CIA + EXTS(LI_0b00));
659 if (LK) LR = (spreg)CIA+4;
660 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
661 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
662 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
663 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
664 int M, ctr_ok, cond_ok;
665 if (is_64bit_implementation && is_64bit_mode) M = 0;
667 if (!BO{2}) CTR = CTR - 1;
668 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
669 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
670 if (ctr_ok && cond_ok)
671 if (AA) NIA = IEA(EXTS(BD_0b00));
672 else NIA = IEA(CIA + EXTS(BD_0b00));
673 if (LK) LR = (spreg)IEA(CIA + 4);
674 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
675 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
676 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
677 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
678 int M, ctr_ok, cond_ok;
679 if (is_64bit_implementation && is_64bit_mode) M = 0;
681 if (!BO{2}) CTR = CTR - 1;
682 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
683 cond_ok = BO{0} || (CR{BI} == BO{1});
684 if (ctr_ok && cond_ok) NIA = IEA(LR_0b00);
685 if (LK) LR = (spreg)IEA(CIA + 4);
686 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
687 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
688 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
689 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
691 cond_ok = BO{0} || (CR{BI} == BO{1});
692 if (cond_ok) NIA = IEA(CTR_0b00);
693 if (LK) LR = (spreg)IEA(CIA + 4);
696 # I.2.4.2 System Call Instruction
698 0.17,6./,11./,16./,30.1,31./:SC:t::System Call
699 system_call_interrupt(processor, cia);
702 # I.2.4.3 Condition Register Logical Instructions
704 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
705 BLIT32(CR, BT, CR{BA} && CR{BB});
706 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
707 BLIT32(CR, BT, CR{BA} || CR{BB});
708 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
709 BLIT32(CR, BT, CR{BA} != CR{BB});
710 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
711 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
712 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
713 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
714 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
715 BLIT32(CR, BT, CR{BA} == CR{BB});
716 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
717 BLIT32(CR, BT, CR{BA} && !CR{BB});
718 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
719 BLIT32(CR, BT, CR{BA} || !CR{BB});
722 # I.2.4.4 Condition Register Field Instruction
724 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
725 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
729 # I.3.3.2 Fixed-Point Load Instructions
732 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
738 *rT = MEM(unsigned, EA, 1);
739 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
745 *rT = MEM(unsigned, EA, 1);
746 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
748 if (RA == 0 || RA == RT)
749 program_interrupt(processor, cia,
750 illegal_instruction_program_interrupt);
752 *rT = MEM(unsigned, EA, 1);
754 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
756 if (RA == 0 || RA == RT)
757 program_interrupt(processor, cia,
758 illegal_instruction_program_interrupt);
760 *rT = MEM(unsigned, EA, 1);
763 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
769 *rT = MEM(unsigned, EA, 2);
770 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
776 *rT = MEM(unsigned, EA, 2);
777 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
779 if (RA == 0 || RA == RT)
780 program_interrupt(processor, cia,
781 illegal_instruction_program_interrupt);
783 *rT = MEM(unsigned, EA, 2);
785 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
787 if (RA == 0 || RA == RT)
788 program_interrupt(processor, cia,
789 illegal_instruction_program_interrupt);
791 *rT = MEM(unsigned, EA, 2);
794 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
800 *rT = MEM(signed, EA, 2);
801 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
807 *rT = MEM(signed, EA, 2);
808 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
810 if (RA == 0 || RA == RT)
811 program_interrupt(processor, cia,
812 illegal_instruction_program_interrupt);
814 *rT = MEM(signed, EA, 2);
815 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
817 if (RA == 0 || RA == RT)
818 program_interrupt(processor, cia,
819 illegal_instruction_program_interrupt);
821 *rT = MEM(signed, EA, 2);
824 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
830 *rT = MEM(unsigned, EA, 4);
831 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
837 *rT = MEM(unsigned, EA, 4);
838 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
840 if (RA == 0 || RA == RT)
841 program_interrupt(processor, cia,
842 illegal_instruction_program_interrupt);
844 *rT = MEM(unsigned, EA, 4);
846 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
848 if (RA == 0 || RA == RT)
849 program_interrupt(processor, cia,
850 illegal_instruction_program_interrupt);
852 *rT = MEM(unsigned, EA, 4);
855 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
858 # if (RA == 0) b = 0;
860 # EA = b + EXTS(DS_0b00);
861 # *rT = MEM(signed, EA, 4);
862 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
865 # if (RA == 0) b = 0;
868 # *rT = MEM(signed, EA, 4);
869 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
871 # if (RA == 0 || RA == RT)
872 # program_interrupt(processor, cia
873 # illegal_instruction_program_interrupt);
875 # *rT = MEM(signed, EA, 4);
878 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
881 # if (RA == 0) b = 0;
883 # EA = b + EXTS(DS_0b00);
884 # *rT = MEM(unsigned, EA, 8);
885 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
888 # if (RA == 0) b = 0;
891 # *rT = MEM(unsigned, EA, 8);
892 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
894 # if (RA == 0 || RA == RT)
895 # program_interrupt(processor, cia
896 # illegal_instruction_program_interrupt);
897 # EA = *rA + EXTS(DS_0b00);
898 # *rT = MEM(unsigned, EA, 8);
900 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
902 # if (RA == 0 || RA == RT)
903 # program_interrupt(processor, cia
904 # illegal_instruction_program_interrupt);
906 # *rT = MEM(unsigned, EA, 8);
912 # I.3.3.3 Fixed-Point Store Instructions
915 0.38,6.RS,11.RA,16.D:D:::Store Byte
922 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
929 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
932 program_interrupt(processor, cia,
933 illegal_instruction_program_interrupt);
937 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
940 program_interrupt(processor, cia,
941 illegal_instruction_program_interrupt);
946 0.44,6.RS,11.RA,16.D:D:::Store Half Word
953 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
960 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
963 program_interrupt(processor, cia,
964 illegal_instruction_program_interrupt);
968 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
971 program_interrupt(processor, cia,
972 illegal_instruction_program_interrupt);
977 0.36,6.RS,11.RA,16.D:D:::Store Word
984 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
991 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
994 program_interrupt(processor, cia,
995 illegal_instruction_program_interrupt);
999 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1002 program_interrupt(processor, cia,
1003 illegal_instruction_program_interrupt);
1008 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
1011 # if (RA == 0) b = 0;
1013 # EA = b + EXTS(DS_0b00);
1014 # STORE(EA, 8, *rS);
1015 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
1018 # if (RA == 0) b = 0;
1021 # STORE(EA, 8, *rS);
1022 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
1025 # program_interrupt(processor, cia
1026 # illegal_instruction_program_interrupt);
1027 # EA = *rA + EXTS(DS_0b00);
1028 # STORE(EA, 8, *rS);
1030 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
1033 # program_interrupt(processor, cia
1034 # illegal_instruction_program_interrupt);
1036 # STORE(EA, 8, *rS);
1041 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
1044 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1050 *rT = SWAP_2(MEM(unsigned, EA, 2));
1051 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1057 *rT = SWAP_4(MEM(unsigned, EA, 4));
1059 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1065 STORE(EA, 2, SWAP_2(*rS));
1066 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1072 STORE(EA, 4, SWAP_4(*rS));
1076 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
1079 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
1080 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
1084 # I.3.3.6 Fixed-Point Move Assist Instructions
1087 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
1088 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
1090 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
1091 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
1095 # I.3.3.7 Storage Synchronization Instructions
1097 # HACK: Rather than monitor addresses looking for a reason
1098 # to cancel a reservation. This code instead keeps
1099 # a copy of the data read from memory. Before performing
1100 # a store, the memory area is checked to see if it has
1102 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
1109 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1110 RESERVE_DATA = MEM(unsigned, EA, 4);
1112 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
1119 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1120 RESERVE_DATA = MEM(unsigned, EA, 8);
1123 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
1130 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
1131 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
1133 CR_SET_XER_SO(0, cr_i_zero);
1136 /* ment to randomly to store, we never do! */
1137 CR_SET_XER_SO(0, 0);
1142 CR_SET_XER_SO(0, 0);
1144 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
1151 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
1152 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
1154 CR_SET_XER_SO(0, cr_i_zero);
1157 /* ment to randomly to store, we never do */
1158 CR_SET_XER_SO(0, 0);
1163 CR_SET_XER_SO(0, 0);
1166 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
1171 # I.3.3.9 Fixed-Point Arithmetic Instructions
1174 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
1175 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1176 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1177 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1178 if (RA_is_0) *rT = EXTS(SI);
1179 else *rT = *rA + EXTS(SI);
1181 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
1182 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1183 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1184 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1185 if (RA_is_0) *rT = EXTS(SI) << 16;
1186 else *rT = *rA + (EXTS(SI) << 16);
1188 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
1189 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1190 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1191 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1194 ALU_END(*rT, 0/*CA*/, OE, Rc);
1196 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
1197 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1198 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1199 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1204 ALU_END(*rT, 0/*CA*/, OE, Rc);
1206 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
1207 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1208 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1209 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1212 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1214 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
1215 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1216 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1217 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1220 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
1222 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
1223 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1224 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1225 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1230 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1232 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
1233 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1234 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1235 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1238 ALU_END(*rT, 1/*CA*/, OE, Rc);
1240 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
1241 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1242 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1243 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1244 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
1249 ALU_END(*rT, 1/*CA*/, OE, Rc);
1251 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
1252 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1253 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1254 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1258 ALU_END(*rT, 1/*CA*/, OE, Rc);
1260 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
1261 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1262 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1263 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1268 ALU_END(*rT, 1/*CA*/, OE, Rc);
1270 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
1271 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1272 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1273 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1277 # ALU_END(*rT, 1/*CA*/, OE, Rc);
1279 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
1280 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1281 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1282 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1287 # ALU_END(*rT, 1/*CA*/, OE, Rc);
1289 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
1290 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1291 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1292 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1295 ALU_END(*rT, 1/*CA*/, OE, Rc);
1297 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
1298 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1299 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1300 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1304 ALU_END(*rT, 1/*CA*/, OE, Rc);
1306 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
1307 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1308 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1309 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1313 ALU_END(*rT,0/*CA*/,OE,Rc);
1315 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
1316 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
1317 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
1318 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 3, 3, 0
1319 signed_word prod = *rA * EXTS(SI);
1322 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
1324 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
1325 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1326 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1327 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1328 signed64 a = (signed32)(*rA);
1329 signed64 b = (signed32)(*rB);
1330 signed64 prod = a * b;
1331 signed_word t = prod;
1333 if (t != prod && OE)
1334 XER |= (xer_overflow | xer_summary_overflow);
1335 CR0_COMPARE(t, 0, Rc);
1337 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
1339 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
1340 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1341 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1342 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1343 signed64 a = (signed32)(*rA);
1344 signed64 b = (signed32)(*rB);
1345 signed64 prod = a * b;
1346 signed_word t = EXTRACTED64(prod, 0, 31);
1348 CR0_COMPARE(t, 0, Rc);
1350 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
1352 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
1353 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
1354 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
1355 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1356 unsigned64 a = (unsigned32)(*rA);
1357 unsigned64 b = (unsigned32)(*rB);
1358 unsigned64 prod = a * b;
1359 signed_word t = EXTRACTED64(prod, 0, 31);
1361 CR0_COMPARE(t, 0, Rc);
1363 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
1365 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
1366 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1367 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1368 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
1369 signed64 dividend = (signed32)(*rA);
1370 signed64 divisor = (signed32)(*rB);
1371 if (divisor == 0 /* nb 0x8000..0 is sign extended */
1372 || (dividend == 0x80000000 && divisor == -1)) {
1374 XER |= (xer_overflow | xer_summary_overflow);
1375 CR0_COMPARE(0, 0, Rc);
1378 signed64 quotent = dividend / divisor;
1380 CR0_COMPARE((signed_word)quotent, 0, Rc);
1382 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
1384 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
1385 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1386 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1387 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
1388 unsigned64 dividend = (unsigned32)(*rA);
1389 unsigned64 divisor = (unsigned32)(*rB);
1392 XER |= (xer_overflow | xer_summary_overflow);
1393 CR0_COMPARE(0, 0, Rc);
1396 unsigned64 quotent = dividend / divisor;
1398 CR0_COMPARE((signed_word)quotent, 0, Rc);
1403 # I.3.3.10 Fixed-Point Compare Instructions
1406 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
1407 if (!is_64bit_mode && L)
1408 program_interrupt(processor, cia,
1409 illegal_instruction_program_interrupt);
1412 signed_word b = EXTS(SI);
1417 CR_COMPARE(BF, a, b);
1419 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
1420 if (!is_64bit_mode && L)
1421 program_interrupt(processor, cia,
1422 illegal_instruction_program_interrupt);
1434 CR_COMPARE(BF, a, b);
1436 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
1437 if (!is_64bit_mode && L)
1438 program_interrupt(processor, cia,
1439 illegal_instruction_program_interrupt);
1442 unsigned_word b = UI;
1444 a = MASKED(*rA, 32, 63);
1447 CR_COMPARE(BF, a, b);
1449 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
1450 if (!is_64bit_mode && L)
1451 program_interrupt(processor, cia,
1452 illegal_instruction_program_interrupt);
1457 a = MASKED(*rA, 32, 63);
1458 b = MASKED(*rB, 32, 63);
1464 CR_COMPARE(BF, a, b);
1469 # I.3.3.11 Fixed-Point Trap Instructions
1472 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
1474 program_interrupt(processor, cia,
1475 illegal_instruction_program_interrupt);
1477 signed_word a = *rA;
1478 signed_word b = EXTS(SI);
1479 if ((a < b && TO{0})
1481 || (a == b && TO{2})
1482 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1483 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1485 program_interrupt(processor, cia,
1486 trap_program_interrupt);
1488 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
1489 signed_word a = EXTENDED(*rA);
1490 signed_word b = EXTS(SI);
1491 if ((a < b && TO{0})
1493 || (a == b && TO{2})
1494 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1495 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1497 program_interrupt(processor, cia,
1498 trap_program_interrupt);
1499 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
1501 program_interrupt(processor, cia,
1502 illegal_instruction_program_interrupt);
1504 signed_word a = *rA;
1505 signed_word b = *rB;
1506 if ((a < b && TO{0})
1508 || (a == b && TO{2})
1509 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1510 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1512 program_interrupt(processor, cia,
1513 trap_program_interrupt);
1515 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
1516 signed_word a = EXTENDED(*rA);
1517 signed_word b = EXTENDED(*rB);
1518 if (TO == 12 && rA == rB) {
1519 ITRACE(trace_breakpoint, ("breakpoint\n"));
1520 cpu_halt(processor, cia, was_trap, 0);
1522 else if ((a < b && TO{0})
1524 || (a == b && TO{2})
1525 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1526 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1528 program_interrupt(processor, cia,
1529 trap_program_interrupt);
1532 # I.3.3.12 Fixed-Point Logical Instructions
1535 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
1537 CR0_COMPARE(*rA, 0, 1/*Rc*/);
1538 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
1539 *rA = *rS & (UI << 16);
1540 CR0_COMPARE(*rA, 0, 1/*Rc*/);
1541 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
1543 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
1544 *rA = *rS | (UI << 16);
1545 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
1547 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
1548 *rA = *rS ^ (UI << 16);
1549 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
1551 CR0_COMPARE(*rA, 0, Rc);
1552 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
1554 CR0_COMPARE(*rA, 0, Rc);
1555 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
1557 CR0_COMPARE(*rA, 0, Rc);
1558 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
1560 CR0_COMPARE(*rA, 0, Rc);
1561 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
1563 CR0_COMPARE(*rA, 0, Rc);
1564 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
1565 # *rA = ~(*rS ^ *rB); /* A === B */
1566 # CR0_COMPARE(*rA, 0, Rc);
1567 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
1569 CR0_COMPARE(*rA, 0, Rc);
1570 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
1572 CR0_COMPARE(*rA, 0, Rc);
1573 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
1574 *rA = (signed_word)(signed8)*rS;
1575 CR0_COMPARE(*rA, 0, Rc);
1576 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
1577 *rA = (signed_word)(signed16)*rS;
1578 CR0_COMPARE(*rA, 0, Rc);
1579 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
1580 # *rA = (signed_word)(signed32)*rS;
1581 # CR0_COMPARE(*rA, 0, Rc);
1582 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
1584 # unsigned64 mask = BIT64(0);
1585 # unsigned64 source = *rS;
1586 # while (!(source & mask) && mask != 0) {
1591 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
1592 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
1594 unsigned32 mask = BIT32(0);
1595 unsigned32 source = *rS;
1596 while (!(source & mask) && mask != 0) {
1601 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
1605 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
1608 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
1609 # long n = (sh_5 << 4) | sh_0_4;
1610 # unsigned_word r = ROTL64(*rS, n);
1611 # long b = (mb_5 << 4) | mb_0_4;
1612 # unsigned_word m = MASK(b, 63);
1613 # signed_word result = r & m;
1615 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1616 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
1617 # long n = (sh_5 << 4) | sh_0_4;
1618 # unsigned_word r = ROTL64(*rS, n);
1619 # long e = (me_5 << 4) | me_0_4;
1620 # unsigned_word m = MASK(0, e);
1621 # signed_word result = r & m;
1623 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1624 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
1625 # long n = (sh_5 << 4) | sh_0_4;
1626 # unsigned_word r = ROTL64(*rS, n);
1627 # long b = (mb_5 << 4) | mb_0_4;
1628 # unsigned_word m = MASK(0, (64-n));
1629 # signed_word result = r & m;
1631 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1633 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
1636 unsigned32 r = ROTL32(s, n);
1637 unsigned32 m = MASK(MB+32, ME+32);
1638 signed_word result = r & m;
1640 CR0_COMPARE(result, 0, Rc);
1642 ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
1643 n, s, r, m, result, CR));
1645 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
1646 # long n = MASKED(*rB, 58, 63);
1647 # unsigned_word r = ROTL64(*rS, n);
1648 # long b = (mb_5 << 4) | mb_0_4;
1649 # unsigned_word m = MASK(b, 63);
1650 # signed_word result = r & m;
1652 # CR0_COMPARE(result, 0, Rc);
1653 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
1654 # long n = MASKED(*rB, 58, 63);
1655 # unsigned_word r = ROTL64(*rS, n);
1656 # long e = (me_5 << 4) | me_0_4;
1657 # unsigned_word m = MASK(0, e);
1658 # signed_word result = r & m;
1660 # CR0_COMPARE(result, 0, Rc);
1662 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
1663 # long n = MASKED(*rB, 59, 63);
1664 # unsigned32 r = ROTL32(*rS, n);
1665 # unsigned32 m = MASK(MB+32, ME+32);
1666 # signed_word result = r & m;
1668 # CR0_COMPARE(result, 0, Rc);
1669 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
1670 # long n = (sh_5 << 4) | sh_0_4;
1671 # unsigned_word r = ROTL64(*rS, n);
1672 # long b = (mb_5 << 4) | mb_0_4;
1673 # unsigned_word m = MASK(b, (64-n));
1674 # signed_word result = (r & m) | (*rA & ~m)
1676 # CR0_COMPARE(result, 0, Rc);
1677 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
1679 unsigned32 r = ROTL32(*rS, n);
1680 unsigned32 m = MASK(MB+32, ME+32);
1681 signed_word result = (r & m) | (*rA & ~m);
1683 ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
1684 n, *rS, r, m, result));
1685 CR0_COMPARE(result, 0, Rc);
1688 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
1689 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
1690 int n = MASKED(*rB, 59, 63);
1691 unsigned32 source = *rS;
1692 signed_word shifted;
1694 shifted = (source << n);
1698 CR0_COMPARE(shifted, 0, Rc);
1700 ("n=%d, source=0x%x, shifted=0x%x\n",
1701 n, source, shifted));
1702 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
1703 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
1704 int n = MASKED(*rB, 59, 63);
1705 unsigned32 source = *rS;
1706 signed_word shifted;
1708 shifted = (source >> n);
1712 CR0_COMPARE(shifted, 0, Rc);
1714 ("n=%d, source=0x%x, shifted=0x%x\n",
1715 n, source, shifted));
1717 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
1718 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
1720 signed_word r = ROTL32(*rS, /*64*/32-n);
1721 signed_word m = MASK(n+32, 63);
1722 int S = MASKED(*rS, 32, 32);
1723 signed_word shifted = (r & m) | (S ? ~m : 0);
1725 if (S && ((r & ~m) & MASK(32, 63)) != 0)
1729 CR0_COMPARE(shifted, 0, Rc);
1730 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
1731 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
1732 int n = MASKED(*rB, 58, 63);
1733 int shift = (n >= 31 ? 31 : n);
1734 signed32 source = (signed32)*rS; /* signed to keep sign bit */
1735 signed32 shifted = source >> shift;
1736 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
1737 *rA = (signed_word)shifted; /* if 64bit will sign extend */
1738 if (source < 0 && (source & mask))
1742 CR0_COMPARE(shifted, 0, Rc);
1746 # I.3.3.14 Move to/from System Register Instructions
1749 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
1750 int n = (spr{5:9} << 5) | spr{0:4};
1751 if (spr{0} && IS_PROBLEM_STATE(processor))
1752 program_interrupt(processor, cia,
1753 privileged_instruction_program_interrupt);
1754 else if (!spr_is_valid(n)
1755 || spr_is_readonly(n))
1756 program_interrupt(processor, cia,
1757 illegal_instruction_program_interrupt);
1759 spreg new_val = (spr_length(n) == 64
1761 : MASKED(*rS, 32, 63));
1762 /* HACK - time base registers need to be updated immediatly */
1763 if (WITH_TIME_BASE) {
1767 cpu_set_time_base(processor,
1768 (MASKED64(cpu_get_time_base(processor), 32, 63)
1769 | INSERTED64(new_val, 0, 31)));
1772 cpu_set_time_base(processor,
1773 (MASKED64(cpu_get_time_base(processor), 0, 31)
1774 | INSERTED64(new_val, 32, 63)));
1777 cpu_set_decrementer(processor, new_val);
1788 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
1789 int n = (spr{5:9} << 5) | spr{0:4};
1790 if (spr{0} && IS_PROBLEM_STATE(processor))
1791 program_interrupt(processor, cia,
1792 privileged_instruction_program_interrupt);
1793 else if (!spr_is_valid(n))
1794 program_interrupt(processor, cia,
1795 illegal_instruction_program_interrupt);
1797 /* HACK - some SPR's need to get their value extracted specially */
1800 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
1805 unsigned_word mask = 0;
1807 for (f = 0; f < 8; f++) {
1808 if (FXM & (0x80 >> f))
1809 mask |= (0xf << 4*(7-f));
1811 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
1813 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
1814 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
1815 *rT = (unsigned32)CR;
1818 # I.4.6.2 Floating-Point Load Instructions
1821 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
1827 *frT = DOUBLE(MEM(unsigned, EA, 4));
1828 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
1834 *frT = DOUBLE(MEM(unsigned, EA, 4));
1835 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
1838 program_interrupt(processor, cia,
1839 illegal_instruction_program_interrupt);
1841 *frT = DOUBLE(MEM(unsigned, EA, 4));
1843 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
1846 program_interrupt(processor, cia,
1847 illegal_instruction_program_interrupt);
1849 *frT = DOUBLE(MEM(unsigned, EA, 4));
1852 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
1858 *frT = MEM(unsigned, EA, 8);
1859 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
1865 *frT = MEM(unsigned, EA, 8);
1866 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
1869 program_interrupt(processor, cia,
1870 illegal_instruction_program_interrupt);
1872 *frT = MEM(unsigned, EA, 8);
1874 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
1877 program_interrupt(processor, cia,
1878 illegal_instruction_program_interrupt);
1880 *frT = MEM(unsigned, EA, 8);
1885 # I.4.6.3 Floating-Point Store Instructions
1888 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
1894 STORE(EA, 4, SINGLE(*frS));
1895 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
1901 STORE(EA, 4, SINGLE(*frS));
1902 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
1905 program_interrupt(processor, cia,
1906 illegal_instruction_program_interrupt);
1908 STORE(EA, 4, SINGLE(*frS));
1910 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
1913 program_interrupt(processor, cia,
1914 illegal_instruction_program_interrupt);
1916 STORE(EA, 4, SINGLE(*frS));
1919 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
1926 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
1933 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
1936 program_interrupt(processor, cia,
1937 illegal_instruction_program_interrupt);
1941 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
1944 program_interrupt(processor, cia,
1945 illegal_instruction_program_interrupt);
1952 # I.4.6.4 Floating-Point Move Instructions
1955 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
1958 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
1959 *frT = *frB ^ BIT64(0);
1961 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
1962 *frT = *frB & ~BIT64(0);
1964 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
1965 *frT = *frB | BIT64(0);
1971 # I.4.6.5 Floating-Point Arithmetic Instructions
1974 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
1976 if (is_invalid_operation(processor, cia,
1978 fpscr_vxsnan | fpscr_vxisi,
1981 invalid_arithemetic_operation(processor, cia,
1983 0, /*instruction_is_frsp*/
1984 0, /*instruction_is_convert_to_64bit*/
1985 0, /*instruction_is_convert_to_32bit*/
1986 0); /*single-precision*/
1990 double s = *(double*)frA + *(double*)frB;
1994 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
1996 if (is_invalid_operation(processor, cia,
1998 fpscr_vxsnan | fpscr_vxisi,
2001 invalid_arithemetic_operation(processor, cia,
2003 0, /*instruction_is_frsp*/
2004 0, /*instruction_is_convert_to_64bit*/
2005 0, /*instruction_is_convert_to_32bit*/
2006 1); /*single-precision*/
2010 float s = *(double*)frA + *(double*)frB;
2015 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
2017 if (is_invalid_operation(processor, cia,
2019 fpscr_vxsnan | fpscr_vxisi,
2022 invalid_arithemetic_operation(processor, cia,
2024 0, /*instruction_is_frsp*/
2025 0, /*instruction_is_convert_to_64bit*/
2026 0, /*instruction_is_convert_to_32bit*/
2027 0); /*single-precision*/
2031 double s = *(double*)frA - *(double*)frB;
2035 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
2037 if (is_invalid_operation(processor, cia,
2039 fpscr_vxsnan | fpscr_vxisi,
2042 invalid_arithemetic_operation(processor, cia,
2044 0, /*instruction_is_frsp*/
2045 0, /*instruction_is_convert_to_64bit*/
2046 0, /*instruction_is_convert_to_32bit*/
2047 1); /*single-precision*/
2051 float s = *(double*)frA - *(double*)frB;
2056 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
2058 if (is_invalid_operation(processor, cia,
2060 fpscr_vxsnan | fpscr_vximz,
2063 invalid_arithemetic_operation(processor, cia,
2065 0, /*instruction_is_frsp*/
2066 0, /*instruction_is_convert_to_64bit*/
2067 0, /*instruction_is_convert_to_32bit*/
2068 0); /*single-precision*/
2072 double s = *(double*)frA * *(double*)frC;
2076 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
2078 if (is_invalid_operation(processor, cia,
2080 fpscr_vxsnan | fpscr_vximz,
2083 invalid_arithemetic_operation(processor, cia,
2085 0, /*instruction_is_frsp*/
2086 0, /*instruction_is_convert_to_64bit*/
2087 0, /*instruction_is_convert_to_32bit*/
2088 1); /*single-precision*/
2092 float s = *(double*)frA * *(double*)frC;
2097 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
2099 if (is_invalid_operation(processor, cia,
2101 fpscr_vxsnan | fpscr_vxzdz,
2104 invalid_arithemetic_operation(processor, cia,
2106 0, /*instruction_is_frsp*/
2107 0, /*instruction_is_convert_to_64bit*/
2108 0, /*instruction_is_convert_to_32bit*/
2109 0); /*single-precision*/
2113 double s = *(double*)frA / *(double*)frB;
2117 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
2119 if (is_invalid_operation(processor, cia,
2121 fpscr_vxsnan | fpscr_vxzdz,
2124 invalid_arithemetic_operation(processor, cia,
2126 0, /*instruction_is_frsp*/
2127 0, /*instruction_is_convert_to_64bit*/
2128 0, /*instruction_is_convert_to_32bit*/
2129 1); /*single-precision*/
2133 float s = *(double*)frA / *(double*)frB;
2138 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
2140 double product; /*HACK! - incorrectly loosing precision ... */
2141 /* compute the multiply */
2142 if (is_invalid_operation(processor, cia,
2144 fpscr_vxsnan | fpscr_vximz,
2147 invalid_arithemetic_operation(processor, cia,
2148 (unsigned64*)&product, *frA, 0, *frC,
2149 0, /*instruction_is_frsp*/
2150 0, /*instruction_is_convert_to_64bit*/
2151 0, /*instruction_is_convert_to_32bit*/
2152 0); /*single-precision*/
2156 product = *(double*)frA * *(double*)frC;
2158 /* compute the add */
2159 if (is_invalid_operation(processor, cia,
2161 fpscr_vxsnan | fpscr_vxisi,
2164 invalid_arithemetic_operation(processor, cia,
2165 frT, product, *frB, 0,
2166 0, /*instruction_is_frsp*/
2167 0, /*instruction_is_convert_to_64bit*/
2168 0, /*instruction_is_convert_to_32bit*/
2169 0); /*single-precision*/
2173 double s = product + *(double*)frB;
2177 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
2179 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
2180 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
2182 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
2183 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
2185 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
2186 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
2190 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
2193 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
2196 unsigned64 frac_grx;
2197 /* split off cases for what to do */
2198 if (EXTRACTED64(*frB, 1, 11) < 897
2199 && EXTRACTED64(*frB, 1, 63) > 0) {
2200 if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
2201 if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
2203 if (EXTRACTED64(*frB, 1, 11) > 1150
2204 && EXTRACTED64(*frB, 1, 11) < 2047) {
2205 if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
2206 if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
2208 if (EXTRACTED64(*frB, 1, 11) > 896
2209 && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
2210 if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
2211 if (EXTRACTED64(*frB, 1, 11) == 2047) {
2212 if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
2213 if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
2214 if (EXTRACTED64(*frB, 12, 12) == 0
2215 && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
2218 Disabled_Exponent_Underflow:
2219 sign = EXTRACTED64(*frB, 0, 0);
2220 if (EXTRACTED64(*frB, 1, 11) == 0) {
2222 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2224 if (EXTRACTED64(*frB, 1, 11) > 0) {
2225 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2226 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2228 Denormalize_Operand:
2229 /* G|R|X == zero from above */
2230 while (exp < -126) {
2232 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
2233 | MASKED64(frac_grx, 55, 55));
2235 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
2236 Round_Single(processor, sign, &exp, &frac_grx);
2237 FPSCR_SET_XX(FPSCR & fpscr_fi);
2238 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
2239 *frT = INSERTED64(sign, 0, 0);
2240 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2241 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
2243 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
2244 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
2245 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2246 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2248 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
2249 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
2250 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
2252 /*Normalize_Operand:*/
2253 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
2255 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
2257 *frT = (INSERTED64(sign, 0, 0)
2258 | INSERTED64(exp + 1023, 1, 11)
2259 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2262 Enabled_Exponent_Underflow:
2264 sign = EXTRACTED64(*frB, 0, 0);
2265 if (EXTRACTED64(*frB, 1, 11) == 0) {
2267 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2269 if (EXTRACTED64(*frB, 1, 11) > 0) {
2270 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2271 frac_grx = (BIT64(0) |
2272 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
2274 /*Normalize_Operand:*/
2275 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
2277 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
2279 Round_Single(processor, sign, &exp, &frac_grx);
2280 FPSCR_SET_XX(FPSCR & fpscr_fi);
2282 *frT = (INSERTED64(sign, 0, 0)
2283 | INSERTED64(exp + 1023, 1, 11)
2284 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2285 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2286 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2288 Disabled_Exponent_Overflow:
2290 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
2291 if (EXTRACTED64(*frB, 0, 0) == 0) {
2292 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
2293 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2295 if (EXTRACTED64(*frB, 0, 0) == 1) {
2296 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
2297 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2300 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
2301 if (EXTRACTED64(*frB, 0, 0) == 0) {
2302 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
2303 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2305 if (EXTRACTED64(*frB, 0, 0) == 1) {
2306 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
2307 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2310 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
2311 if (EXTRACTED64(*frB, 0, 0) == 0) {
2312 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
2313 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2315 if (EXTRACTED64(*frB, 0, 0) == 1) {
2316 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
2317 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2320 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
2321 if (EXTRACTED64(*frB, 0, 0) == 0) {
2322 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
2323 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2325 if (EXTRACTED64(*frB, 0, 0) == 1) {
2326 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
2327 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2330 /* FPSCR[FR] <- undefined */
2334 Enabled_Exponent_Overflow:
2335 sign = EXTRACTED64(*frB, 0, 0);
2336 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2337 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2338 Round_Single(processor, sign, &exp, &frac_grx);
2339 FPSCR_SET_XX(FPSCR & fpscr_fi);
2343 *frT = (INSERTED64(sign, 0, 0)
2344 | INSERTED64(exp + 1023, 1, 11)
2345 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2346 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2347 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2351 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2352 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
2358 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2359 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2364 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
2365 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
2370 FPSCR_OR_VX(fpscr_vxsnan);
2371 if ((FPSCR & fpscr_ve) == 0) {
2372 *frT = (MASKED64(*frB, 0, 11)
2374 | MASKED64(*frB, 13, 34));
2375 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
2381 sign = EXTRACTED64(*frB, 0, 0);
2382 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2383 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2384 Round_Single(processor, sign, &exp, &frac_grx);
2385 FPSCR_SET_XX(FPSCR & fpscr_fi);
2386 if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
2387 if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
2388 *frT = (INSERTED64(sign, 0, 0)
2389 | INSERTED64(exp + 1023, 1, 11)
2390 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2391 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2392 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2395 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
2396 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
2397 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
2398 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
2400 convert_to_integer(processor, cia,
2402 fpscr_rn_round_towards_zero, 32);
2404 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
2405 int sign = EXTRACTED64(*frB, 0, 0);
2407 unsigned64 frac = *frB;
2408 if (frac == 0) goto Zero_Operand;
2409 if (sign == 1) frac = ~frac + 1;
2410 while (EXTRACTED64(frac, 0, 0) == 0) {
2411 /*??? do the loop 0 times if (FRB) = max negative integer */
2412 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
2415 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
2416 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2417 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2418 *frT = (INSERTED64(sign, 0, 0)
2419 | INSERTED64(exp + 1023, 1, 11)
2420 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
2426 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2433 # I.4.6.7 Floating-Point Compare Instructions
2436 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
2439 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
2440 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
2441 else if (is_less_than(frA, frB))
2442 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
2443 else if (is_greater_than(frA, frB))
2444 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
2446 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
2448 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
2449 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
2450 FPSCR_OR_VX(fpscr_vxsnan);
2452 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
2455 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
2456 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
2457 else if (is_less_than(frA, frB))
2458 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
2459 else if (is_greater_than(frA, frB))
2460 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
2462 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
2464 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
2465 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
2466 FPSCR_OR_VX(fpscr_vxsnan);
2467 if ((FPSCR & fpscr_ve) == 0)
2468 FPSCR_OR_VX(fpscr_vxvc);
2470 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
2471 FPSCR_OR_VX(fpscr_vxvc);
2477 # I.4.6.8 Floating-Point Status and Control Register Instructions
2480 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
2481 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
2482 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
2483 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
2484 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
2485 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
2489 # I.A.1.1 Floating-Point Store Instruction
2491 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
2494 # I.A.1.2 Floating-Point Arithmetic Instructions
2497 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
2498 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
2500 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
2501 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
2504 # I.A.1.3 Floating-Point Select Instruction
2507 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
2511 # II.3.2 Cache Management Instructions
2514 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
2515 /* blindly flush all instruction cache entries */
2516 #if WITH_IDECODE_CACHE_SIZE
2517 cpu_flush_icache(processor);
2520 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
2521 cpu_synchronize_context(processor);
2525 # II.3.2.2 Data Cache Instructions
2528 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
2531 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
2534 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
2537 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
2540 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
2544 # II.3.3 Envorce In-order Execution of I/O Instruction
2547 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
2548 /* Since this model has no instruction overlap
2549 this instruction need do nothing */
2552 # II.4.1 Time Base Instructions
2555 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
2556 int n = (tbr{5:9} << 5) | tbr{0:4};
2558 if (is_64bit_implementation) *rT = TB;
2559 else *rT = EXTRACTED64(TB, 32, 63);
2561 else if (n == 269) {
2562 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
2563 else *rT = EXTRACTED64(TB, 0, 31);
2566 program_interrupt(processor, cia,
2567 illegal_instruction_program_interrupt);
2571 # III.2.3.1 System Linkage Instructions
2574 #0.17,6./,11./,16./,30.1,31./:SC::sc:System Call
2575 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
2576 if (IS_PROBLEM_STATE(processor)) {
2577 program_interrupt(processor, cia,
2578 privileged_instruction_program_interrupt);
2581 MSR = (MASKED(SRR1, 0, 32)
2582 | MASKED(SRR1, 37, 41)
2583 | MASKED(SRR1, 48, 63));
2584 NIA = MASKED(SRR0, 0, 61);
2585 cpu_synchronize_context(processor);
2589 # III.3.4.1 Move to/from System Register Instructions
2592 #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
2593 #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
2594 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
2595 if (IS_PROBLEM_STATE(processor))
2596 program_interrupt(processor, cia,
2597 privileged_instruction_program_interrupt);
2600 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
2601 if (IS_PROBLEM_STATE(processor))
2602 program_interrupt(processor, cia,
2603 privileged_instruction_program_interrupt);
2609 # III.4.11.1 Cache Management Instructions
2612 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
2616 # III.4.11.2 Segment Register Manipulation Instructions
2619 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
2620 if (IS_PROBLEM_STATE(processor))
2621 program_interrupt(processor, cia,
2622 privileged_instruction_program_interrupt);
2625 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
2626 if (IS_PROBLEM_STATE(processor))
2627 program_interrupt(processor, cia,
2628 privileged_instruction_program_interrupt);
2630 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
2631 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
2632 if (IS_PROBLEM_STATE(processor))
2633 program_interrupt(processor, cia,
2634 privileged_instruction_program_interrupt);
2637 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
2638 if (IS_PROBLEM_STATE(processor))
2639 program_interrupt(processor, cia,
2640 privileged_instruction_program_interrupt);
2642 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
2646 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
2649 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
2650 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
2652 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
2653 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
2655 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
2659 # III.A.1.2 External Access Instructions
2662 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
2663 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed