# # This file is part of the program psim. # # Copyright (C) 1994-1995, Andrew Cagney # # -- # # The pseudo-code that appears below, translated into C, was copied # by Andrew Cagney of Moss Vale, Australia. # # This pseudo-code is copied by permission from the publication # "The PowerPC Architecture: A Specification for A New Family of # RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by # International Business Machines Corporation. # # THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER # EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # -- # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # -- # # # Fields: # # 1 Instruction format as a `start-bit,content' pairs. # the content is one of a digit, field name or `/' (aka.0) # # 2 Format specifier # # 3 Flags: 64 - 64bit only # f - floating point enabled required # # 4 short name # # 5 Description # # # For flags marked 'model', the fields are interpreted as follows: # # 1 Not used # # 2 Not used # # 3 "macro" # # 4 String name for model # # 5 Specific CPU model, must be an identifier # # 6 Comma separated list of functional units # PowerPC models ::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0 ::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0 ::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0 ::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0 # Flags for model.h ::model-data::: typedef enum _ppc_function_unit { PPC_UNIT_BAD, /* unknown function unit */ PPC_UNIT_IU, /* integer unit (601/603 style) */ PPC_UNIT_SRU, /* system register unit (601/603 style) */ PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */ PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */ PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */ PPC_UNIT_FPU, /* floating point unit */ PPC_UNIT_LSU, /* load/store unit */ PPC_UNIT_BPU, /* branch unit */ nr_ppc_function_units } ppc_function_unit; /* Structure to hold timing information on a per instruction basis */ struct _model_time { ppc_function_unit first_unit; /* first functional unit this insn could use */ ppc_function_unit last_unit; /* last functional unit this insn could use */ unsigned16 issue; /* # cycles before function unit can process other insns */ unsigned16 done; /* # cycles before insn is done */ unsigned32 flags; /* flag bits */ }; /* Flags */ #define PPC_LOAD 0x00000001 /* insn is a load */ #define PPC_STORE 0x00000002 /* insn is a store */ #define PPC_SERIALIZE 0x00000004 /* insn forces serialization */ /* Structure to hold the current state information for the simulated CPU model */ struct _model_data { const char *name; /* model name */ const model_time *timing; /* timing information */ unsigned nr_branches; /* # branches */ unsigned nr_branches_fallthrough; /* # conditional branches that fell through */ unsigned nr_branch_predict_trues; /* # branches predicted correctly */ unsigned nr_branch_predict_falses; /* # branches predicted incorrectly */ unsigned nr_units[nr_ppc_function_units]; /* function unit counts */ unsigned16 busy[nr_ppc_function_units]; /* how long until free */ }; STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = { "unknown functional unit instruction", "integer functional unit instruction", "system register functional unit instruction", "1st single cycle integer functional unit instruction", "2nd single cycle integer functional unit instruction", "multiple cycle integer functional unit instruction", "floating point functional unit instruction", "load/store functional unit instruction", "branch functional unit instruction", }; model_data *::model-function::model_create:cpu *processor if (CURRENT_MODEL == MODEL_NONE) { error("Must define a CPU model"); return (model_data *)0; } else { model_data *model_ptr = ZALLOC(model_data); model_ptr->name = model_name[CURRENT_MODEL]; model_ptr->timing = model_time_mapping[CURRENT_MODEL]; return model_ptr; } void::model-function::model_init:cpu *processor, model_data *model_ptr void::model-function::model_halt:cpu *processor, model_data *model_ptr void::model-function::model_issue:itable_index index, cpu *processor, model_data *model_ptr, unsigned_word cia model_ptr->nr_units[ (int)model_ptr->timing[ (int)index ].first_unit ]++; /* Assume that any instruction we don't know about is illegal for this cpu model */ if (model_ptr->timing[(int)index].first_unit == PPC_UNIT_BAD) program_interrupt(processor, cia, illegal_instruction_program_interrupt); model_print *::model-function::model_mon_info:model_data *model_ptr model_print *head; model_print *tail; ppc_function_unit i; head = tail = ZALLOC(model_print); tail->count = model_ptr->nr_branches; tail->name = "branch"; tail->suffix_plural = "es"; tail->suffix_singular = ""; if (model_ptr->nr_branches_fallthrough) { tail->next = ZALLOC(model_print); tail = tail->next; tail->count = model_ptr->nr_branches_fallthrough; tail->name = "conditional branch"; tail->suffix_plural = "es fell through"; tail->suffix_singular = " fell through"; } if (model_ptr->nr_branch_predict_trues) { tail->next = ZALLOC(model_print); tail = tail->next; tail->count = model_ptr->nr_branch_predict_trues; tail->name = "successful branch prediction"; tail->suffix_plural = "s"; tail->suffix_singular = ""; } if (model_ptr->nr_branch_predict_falses) { tail->next = ZALLOC(model_print); tail = tail->next; tail->count = model_ptr->nr_branch_predict_falses; tail->name = "unsuccessful branch prediction"; tail->suffix_plural = "s"; tail->suffix_singular = ""; } for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) { if (model_ptr->nr_units[i]) { tail->next = ZALLOC(model_print); tail = tail->next; tail->count = model_ptr->nr_units[i]; tail->name = ppc_function_unit_name[i]; tail->suffix_plural = "s"; tail->suffix_singular = ""; } } tail->next = (model_print *)0; return head; void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr model_print *next; while (ptr) { next = ptr->next; free((void *)ptr); ptr = next; } void::model-function::model_branches:model_data *model_ptr, int failed if (failed) model_ptr->nr_branches_fallthrough++; else model_ptr->nr_branches++; void::model-function::model_branch_predict:model_data *model_ptr, int success if (success) model_ptr->nr_branch_predict_trues++; else model_ptr->nr_branch_predict_falses++; # The following (illegal) instruction is `known' by gen and is # called when ever an illegal instruction is encountered ::internal::illegal program_interrupt(processor, cia, illegal_instruction_program_interrupt); return 0; # The following (floating point unavailable) instruction is `known' by gen # and is called when ever an a floating point instruction is to be # executed but floating point is make unavailable by the MSR ::internal::floating_point_unavailable floating_point_unavailable_interrupt(processor, cia); return 0; # # Floating point support functions # # Convert 32bit single to 64bit double unsigned64::function::DOUBLE:unsigned32 WORD unsigned64 FRT; if (EXTRACTED32(WORD, 1, 8) > 0 && EXTRACTED32(WORD, 1, 8) < 255) { /* normalized operand */ int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/ FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1) | INSERTED64(not_word_1_1, 2, 2) | INSERTED64(not_word_1_1, 3, 3) | INSERTED64(not_word_1_1, 4, 4) | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29))); } else if (EXTRACTED32(WORD, 1, 8) == 0 && EXTRACTED32(WORD, 9, 31) != 0) { /* denormalized operand */ int sign = EXTRACTED32(WORD, 0, 0); int exp = -126; unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29)); /* normalize the operand */ while (MASKED64(frac, 0, 0) == 0) { frac <<= 1; exp -= 1; } FRT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63)); } else if (EXTRACTED32(WORD, 1, 8) == 255 || EXTRACTED32(WORD, 1, 31) == 0) { FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1) | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2) | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3) | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4) | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29))); } else { error("DOUBLE - unknown case\n"); FRT = 0; } return FRT; # Convert 64bit single to 32bit double unsigned32::function::SINGLE:unsigned64 FRS unsigned32 WORD; if (EXTRACTED64(FRS, 1, 11) > 896 || EXTRACTED64(FRS, 1, 63) == 0) { /* no denormalization required (includes Zero/Infinity/NaN) */ WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1) | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31)); } else if (874 <= EXTRACTED64(FRS, 1, 11) && EXTRACTED64(FRS, 1, 11) <= 896) { /* denormalization required */ int sign = EXTRACTED64(FRS, 0, 0); int exp = EXTRACTED64(FRS, 1, 11) - 1023; unsigned64 frac = (BIT64(0) | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52)); /* denormalize the operand */ while (exp < -126) { frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63); exp += 1; } WORD = (INSERTED32(sign, 0, 0) | INSERTED32(0x00, 1, 8) | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31)); } else { WORD = 0x0; /* ??? */ } return WORD; # round 64bit double to 64bit but single void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx /* comparisons ignore u bits */ unsigned64 out; int inc = 0; int lsb = EXTRACTED64(*frac_grx, 23, 23); int gbit = EXTRACTED64(*frac_grx, 24, 24); int rbit = EXTRACTED64(*frac_grx, 25, 25); int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0; if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) { if (lsb == 1 && gbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1; } if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) { if (sign == 0 && gbit == 1) inc = 1; if (sign == 0 && rbit == 1) inc = 1; if (sign == 0 && xbit == 1) inc = 1; } if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) { if (sign == 1 && gbit == 1) inc = 1; if (sign == 1 && rbit == 1) inc = 1; if (sign == 1 && xbit == 1) inc = 1; } /* work out addition in low 25 bits of out */ out = EXTRACTED64(*frac_grx, 0, 23) + inc; *frac_grx = INSERTED64(out, 0, 23); if (out & BIT64(64 - 23 - 1 - 1)) { *frac_grx = (BIT64(0) | INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23)); *exp = *exp + 1; } /* frac_grx[24:52] = 0 already */ FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit || rbit || xbit); # void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode int inc = 0; if (round_mode == fpscr_rn_round_to_nearest) { if (*frac64 == 1 && gbit == 1) inc = 1; if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1; if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_pos_infinity) { if (sign == 0 && gbit == 1) inc = 1; if (sign == 0 && rbit == 1) inc = 1; if (sign == 0 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_neg_infinity) { if (sign == 1 && gbit == 1) inc = 1; if (sign == 1 && rbit == 1) inc = 1; if (sign == 1 && xbit == 1) inc = 1; } /* frac[0:64] = frac[0:64} + inc */ *frac += (*frac64 && inc ? 1 : 0); *frac64 = (*frac64 + inc) & 0x1; FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit | rbit | xbit); void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode int carry_out; int inc = 0; int lsb = EXTRACTED64(*frac, 52, 52); int gbit = EXTRACTED64(*frac, 53, 53); int rbit = EXTRACTED64(*frac, 54, 54); int xbit = EXTRACTED64(*frac, 55, 55); if (round_mode == fpscr_rn_round_to_nearest) { if (lsb == 1 && gbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_pos_infinity) { if (sign == 0 && gbit == 1) inc = 1; if (sign == 0 && rbit == 1) inc = 1; if (sign == 0 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_neg_infinity) { if (sign == 1 && gbit == 1) inc = 1; if (sign == 1 && rbit == 1) inc = 1; if (sign == 1 && xbit == 1) inc = 1; } /* frac//carry_out = frac + inc */ *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1); carry_out = EXTRACTED64(*frac, 0, 0); *frac <<= 1; if (carry_out == 1) *exp = *exp + 1; FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit | rbit | xbit); FPSCR_SET_XX(FPSCR & fpscr_fi); # conversion of FP to integer void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision int i; int exp = 0; unsigned64 frac = 0; int frac64 = 0; int gbit = 0; int rbit = 0; int xbit = 0; int sign = EXTRACTED64(frb, 0, 0); if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0) goto Infinity_Operand; if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0) goto SNaN_Operand; if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1) goto QNaN_Operand; if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand; if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023; if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022; if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */ frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53); frac64 = 0; } if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */ frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53); frac64 = 0; } gbit = 0, rbit = 0, xbit = 0; for (i = 1; i <= 63 - exp; i++) { xbit = rbit | xbit; rbit = gbit; gbit = frac64; frac64 = EXTRACTED64(frac, 63, 63); frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63); } Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode); if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */ frac = ~frac; frac64 ^= 1; frac += (frac64 ? 1 : 0); frac64 = (frac64 + 1) & 0x1; } if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/) goto Large_Operand; if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/) goto Large_Operand; if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/) goto Large_Operand; if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/) goto Large_Operand; FPSCR_SET_XX(FPSCR & fpscr_fi); if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64; if (tgt_precision == 64) *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64; /*FPSCR[fprf] = undefined */ goto Done; /**/ Infinity_Operand: FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) { if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF; if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000; } else { if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/ if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ } /* FPSCR[FPRF] = undefined */ } goto Done; /**/ SNaN_Operand: FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000; if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } goto Done; /**/ QNaN_Operand: FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000; if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } goto Done; /**/ Large_Operand: FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) { if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff; if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000; } else { if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/ if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ } /* FPSCR[fprf] = undefined */ } /**/ Done: # extract out raw fields of a FP number int::function::sign:unsigned64 FRS return (MASKED64(FRS, 0, 0) ? -1 : 1); int::function::biased_exp:unsigned64 frs, int single if (single) return EXTRACTED64(frs, 1, 8); else return EXTRACTED64(frs, 1, 11); unsigned64::function::fraction:unsigned64 frs, int single if (single) return EXTRACTED64(frs, 9, 31); else return EXTRACTED64(frs, 12, 63); # a number?, each of the below return +1 or -1 (based on sign bit) # if true. int::function::is_nor:unsigned64 frs, int single int exp = biased_exp(frs, single); return (exp >= 1 && exp <= (single ? 254 : 2046)); int::function::is_zero:unsigned64 FRS return (MASKED64(FRS, 1, 63) == 0 ? sign(FRS) : 0); int::function::is_den:unsigned64 frs, int single int exp = biased_exp(frs, single); unsigned64 frac = fraction(frs, single); return (exp == 0 && frac != 0 ? sign(frs) : 0); int::function::is_inf:unsigned64 frs, int single int exp = biased_exp(frs, single); int frac = fraction(frs, single); return (exp == (single ? 255 : 2047) && frac == 0 ? sign(frs) : 0); int::function::is_NaN:unsigned64 frs, int single int exp = biased_exp(frs, single); int frac = fraction(frs, single); return (exp == (single ? 255 : 2047) && frac != 0 ? sign(frs) : 0); int::function::is_SNaN:unsigned64 frs, int single return (is_NaN(frs, single) && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12))) ? sign(frs) : 0); int::function::is_QNaN:unsigned64 frs, int single return (is_NaN(frs, single) && !is_SNaN(frs, single)); int::function::is_less_than:unsigned64 *fra, unsigned64 *frb return *(double*)fra < *(double*)frb; int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb return *(double*)fra > *(double*)frb; int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb return *(double*)fra == *(double*)frb; # which quiet nan should become the result unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single unsigned64 frt = 0; if (is_NaN(fra, single)) frt = fra; else if (is_NaN(frb, single)) if (instruction_is_frsp) frt = MASKED64(frb, 0, 34); else frt = frb; else if (is_NaN(frc, single)) frt = frc; else if (generate_qnan) frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */ else error("select_qnan - default reached\n"); return frt; # detect invalid operation int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate int fail = 0; if ((check & fpscr_vxsnan) && (is_SNaN(fra, single) || is_SNaN(frb, single))) { FPSCR_OR_VX(fpscr_vxsnan); fail = 1; } if ((check & fpscr_vxisi) && (is_inf(fra, single) && is_inf(frb, single)) && ((negate && sign(fra) != sign(frb)) || (!negate && sign(fra) == sign(frb)))) { /*FIXME: don't handle inf-inf VS inf+-inf */ FPSCR_OR_VX(fpscr_vxisi); fail = 1; } if ((check & fpscr_vxidi) && (is_inf(fra, single) && is_inf(frb, single))) { FPSCR_OR_VX(fpscr_vxidi); fail = 1; } if ((check & fpscr_vxzdz) && (is_zero(fra) && is_zero(frb))) { FPSCR_OR_VX(fpscr_vxzdz); fail = 1; } if ((check & fpscr_vximz) && (is_zero(fra) && is_inf(frb, single))) { FPSCR_OR_VX(fpscr_vximz); fail = 1; } if ((check & fpscr_vxvc) && (is_NaN(fra, single) || is_NaN(frb, single))) { FPSCR_OR_VX(fpscr_vxvc); fail = 1; } if ((check & fpscr_vxsoft)) { FPSCR_OR_VX(fpscr_vxsoft); fail = 1; } if ((check & fpscr_vxsqrt) && sign(fra) < 0) { FPSCR_OR_VX(fpscr_vxsqrt); fail = 1; } /* if ((check && fpscr_vxcvi) { && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single))) FPSCR_OR_VX(fpscr_vxcvi); fail = 1; } */ return fail; # handle case of invalid operation 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 if (FPSCR & fpscr_ve) { /* invalid operation exception enabled */ /* FRT unchaged */ FPSCR_SET_FR(0); FPSCR_SET_FI(0); /* fpscr_FPRF unchanged */ } else { /* invalid operation exception disabled */ if (instruction_is_convert_to_64bit) { error("oopsi"); } else if (instruction_is_convert_to_32bit) { error("oopsi"); } else { /* arrith, frsp */ *frt = select_qnan(fra, frb, frc, instruction_is_frsp, 0/*generate*/, single); FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_SET_FPRF(fpscr_rf_quiet_nan); } } # # I.2.4.1 Branch Instructions # 0.18,6.LI,30.AA,31.LK:I:t::Branch *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 if (AA) NIA = IEA(EXTS(LI_0b00)); else NIA = IEA(CIA + EXTS(LI_0b00)); if (LK) LR = (spreg)CIA+4; model_branches(cpu_model(processor), 1); 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 int M, ctr_ok, cond_ok, succeed; if (is_64bit_implementation && is_64bit_mode) M = 0; else M = 32; if (!BO{2}) CTR = CTR - 1; ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3})); cond_ok = BO{0} || ((CR{BI}) == (BO{1})); if (ctr_ok && cond_ok) { if (AA) NIA = IEA(EXTS(BD_0b00)); else NIA = IEA(CIA + EXTS(BD_0b00)); succeed = 1; } else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); model_branches(cpu_model(processor), succeed); if (! BO{0}) { int reverse; if (BO{4}) { /* branch prediction bit set, reverse sense of test */ reverse = EXTS(BD_0b00) < 0; } else { /* branch prediction bit not set */ reverse = EXTS(BD_0b00) >= 0; } model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed); } 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 int M, ctr_ok, cond_ok, succeed; if (is_64bit_implementation && is_64bit_mode) M = 0; else M = 32; if (!BO{2}) CTR = CTR - 1; ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3}); cond_ok = BO{0} || (CR{BI} == BO{1}); if (ctr_ok && cond_ok) { NIA = IEA(LR_0b00); succeed = 1; } else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); model_branches(cpu_model(processor), succeed); if (! BO{0}) model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed); 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 int cond_ok, succeed; cond_ok = BO{0} || (CR{BI} == BO{1}); if (cond_ok) { NIA = IEA(CTR_0b00); succeed = 1; } else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); model_branches(cpu_model(processor), succeed); if (! BO{0}) model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed); # # I.2.4.2 System Call Instruction # 0.17,6./,11./,16./,30.1,31./:SC:t::System Call *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, PPC_SERIALIZE system_call_interrupt(processor, cia); # # I.2.4.3 Condition Register Logical Instructions # 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} && CR{BB}); 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} || CR{BB}); 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} != CR{BB}); 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, !(CR{BA} && CR{BB})); 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, !(CR{BA} || CR{BB})); 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} == CR{BB}); 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} && !CR{BB}); 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} || !CR{BB}); # # I.2.4.4 Condition Register Field Instruction # 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3)); # # I.3.3.2 Fixed-Point Load Instructions # 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *rT = MEM(unsigned, EA, 1); 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = MEM(unsigned, EA, 1); 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *rT = MEM(unsigned, EA, 1); *rA = EA; 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *rT = MEM(unsigned, EA, 1); *rA = EA; 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *rT = MEM(unsigned, EA, 2); 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = MEM(unsigned, EA, 2); 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *rT = MEM(unsigned, EA, 2); *rA = EA; 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *rT = MEM(unsigned, EA, 2); *rA = EA; 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *rT = MEM(signed, EA, 2); 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = MEM(signed, EA, 2); 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *rT = MEM(signed, EA, 2); 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *rT = MEM(signed, EA, 2); *rA = EA; 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *rT = MEM(unsigned, EA, 4); 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = MEM(unsigned, EA, 4); 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *rT = MEM(unsigned, EA, 4); *rA = EA; 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 unsigned_word EA; if (RA == 0 || RA == RT) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *rT = MEM(unsigned, EA, 4); *rA = EA; 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + EXTS(DS_0b00); # *rT = MEM(signed, EA, 4); 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + *rB;; # *rT = MEM(signed, EA, 4); 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed # unsigned_word EA; # if (RA == 0 || RA == RT) # program_interrupt(processor, cia # illegal_instruction_program_interrupt); # EA = *rA + *rB; # *rT = MEM(signed, EA, 4); # *rA = EA; 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + EXTS(DS_0b00); # *rT = MEM(unsigned, EA, 8); 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + *rB; # *rT = MEM(unsigned, EA, 8); 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update # unsigned_word EA; # if (RA == 0 || RA == RT) # program_interrupt(processor, cia # illegal_instruction_program_interrupt); # EA = *rA + EXTS(DS_0b00); # *rT = MEM(unsigned, EA, 8); # *rA = EA; 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed # unsigned_word EA; # if (RA == 0 || RA == RT) # program_interrupt(processor, cia # illegal_instruction_program_interrupt); # EA = *rA + *rB; # *rT = MEM(unsigned, EA, 8); # *rA = EA; # # I.3.3.3 Fixed-Point Store Instructions # 0.38,6.RS,11.RA,16.D:D:::Store Byte *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); STORE(EA, 1, *rS); 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 1, *rS); 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); STORE(EA, 1, *rS); *rA = EA; 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; STORE(EA, 1, *rS); *rA = EA; 0.44,6.RS,11.RA,16.D:D:::Store Half Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); STORE(EA, 2, *rS); 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 2, *rS); 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); STORE(EA, 2, *rS); *rA = EA; 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; STORE(EA, 2, *rS); *rA = EA; 0.36,6.RS,11.RA,16.D:D:::Store Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); STORE(EA, 4, *rS); 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 4, *rS); 0.37,6.RS,11.RA,16.D:D:::Store Word with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); STORE(EA, 4, *rS); *rA = EA; 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; STORE(EA, 4, *rS); *rA = EA; 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + EXTS(DS_0b00); # STORE(EA, 8, *rS); 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed # unsigned_word b; # unsigned_word EA; # if (RA == 0) b = 0; # else b = *rA; # EA = b + *rB; # STORE(EA, 8, *rS); 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update # unsigned_word EA; # if (RA == 0) # program_interrupt(processor, cia # illegal_instruction_program_interrupt); # EA = *rA + EXTS(DS_0b00); # STORE(EA, 8, *rS); # *rA = EA; 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed # unsigned_word EA; # if (RA == 0) # program_interrupt(processor, cia # illegal_instruction_program_interrupt); # EA = *rA + *rB; # STORE(EA, 8, *rS); # *rA = EA; # # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions # 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = SWAP_2(MEM(unsigned, EA, 2)); 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *rT = SWAP_4(MEM(unsigned, EA, 4)); 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 2, SWAP_2(*rS)); 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 4, SWAP_4(*rS)); # # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions # 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word # # I.3.3.6 Fixed-Point Move Assist Instructions # 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed # # I.3.3.7 Storage Synchronization Instructions # # HACK: Rather than monitor addresses looking for a reason # to cancel a reservation. This code instead keeps # a copy of the data read from memory. Before performing # a store, the memory area is checked to see if it has # been changed. 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; RESERVE = 1; RESERVE_ADDR = real_addr(EA, 1/*is-read?*/); RESERVE_DATA = MEM(unsigned, EA, 4); *rT = RESERVE_DATA; 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; RESERVE = 1; RESERVE_ADDR = real_addr(EA, 1/*is-read?*/); RESERVE_DATA = MEM(unsigned, EA, 8); *rT = RESERVE_DATA; 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; if (RESERVE) { if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/) && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) { STORE(EA, 4, *rS); CR_SET_XER_SO(0, cr_i_zero); } else { /* ment to randomly to store, we never do! */ CR_SET_XER_SO(0, 0); } RESERVE = 0; } else { CR_SET_XER_SO(0, 0); } 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; if (RESERVE) { if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/) && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) { STORE(EA, 8, *rS); CR_SET_XER_SO(0, cr_i_zero); } else { /* ment to randomly to store, we never do */ CR_SET_XER_SO(0, 0); } RESERVE = 0; } else { CR_SET_XER_SO(0, 0); } 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0 /* do nothing */ # # I.3.3.9 Fixed-Point Arithmetic Instructions # 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (RA_is_0) *rT = EXTS(SI); else *rT = *rA + EXTS(SI); 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (RA_is_0) *rT = EXTS(SI) << 16; else *rT = *rA + (EXTS(SI) << 16); 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD(*rB); ALU_END(*rT, 0/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_NOT; ALU_ADD(*rB); ALU_ADD(1); ALU_END(*rT, 0/*CA*/, OE, Rc); 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD(EXTS(SI)); ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/); 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD(EXTS(SI)); ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/); 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_NOT; ALU_ADD(EXTS(SI)); ALU_ADD(1); ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/); 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD(*rB); ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 /* RT <- ~RA + RB + 1 === RT <- RB - RA */ ALU_BEGIN(*rA); ALU_NOT; ALU_ADD(*rB); ALU_ADD(1); ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD(*rB); ALU_ADD_CA; ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_NOT; ALU_ADD(*rB); ALU_ADD_CA; ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 # ALU_BEGIN(*rA); # ALU_ADD_CA; # ALU_SUB(1); # ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 # ALU_BEGIN(*rA); # ALU_NOT; # ALU_ADD_CA; # ALU_SUB(1); # ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_ADD_CA; ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_NOT; ALU_ADD_CA; ALU_END(*rT, 1/*CA*/, OE, Rc); 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 ALU_BEGIN(*rA); ALU_NOT; ALU_ADD(1); ALU_END(*rT,0/*CA*/,OE,Rc); 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0 signed_word prod = *rA * EXTS(SI); *rT = prod; 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0 signed64 a = (signed32)(*rA); signed64 b = (signed32)(*rB); signed64 prod = a * b; signed_word t = prod; *rT = *rA * *rB; if (t != prod && OE) XER |= (xer_overflow | xer_summary_overflow); CR0_COMPARE(t, 0, Rc); 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0 signed64 a = (signed32)(*rA); signed64 b = (signed32)(*rB); signed64 prod = a * b; signed_word t = EXTRACTED64(prod, 0, 31); *rT = t; CR0_COMPARE(t, 0, Rc); 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0 unsigned64 a = (unsigned32)(*rA); unsigned64 b = (unsigned32)(*rB); unsigned64 prod = a * b; signed_word t = EXTRACTED64(prod, 0, 31); *rT = t; CR0_COMPARE(t, 0, Rc); 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0 signed64 dividend = (signed32)(*rA); signed64 divisor = (signed32)(*rB); if (divisor == 0 /* nb 0x8000..0 is sign extended */ || (dividend == 0x80000000 && divisor == -1)) { if (OE) XER |= (xer_overflow | xer_summary_overflow); CR0_COMPARE(0, 0, Rc); } else { signed64 quotent = dividend / divisor; *rT = quotent; CR0_COMPARE((signed_word)quotent, 0, Rc); } 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0 unsigned64 dividend = (unsigned32)(*rA); unsigned64 divisor = (unsigned32)(*rB); if (divisor == 0) { if (OE) XER |= (xer_overflow | xer_summary_overflow); CR0_COMPARE(0, 0, Rc); } else { unsigned64 quotent = dividend / divisor; *rT = quotent; CR0_COMPARE((signed_word)quotent, 0, Rc); } # # I.3.3.10 Fixed-Point Compare Instructions # 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (!is_64bit_mode && L) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { signed_word a; signed_word b = EXTS(SI); if (L == 0) a = EXTENDED(*rA); else a = *rA; CR_COMPARE(BF, a, b); } 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (!is_64bit_mode && L) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { signed_word a; signed_word b; if (L == 0) { a = EXTENDED(*rA); b = EXTENDED(*rB); } else { a = *rA; b = *rB; } CR_COMPARE(BF, a, b); } 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (!is_64bit_mode && L) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { unsigned_word a; unsigned_word b = UI; if (L == 0) a = MASKED(*rA, 32, 63); else a = *rA; CR_COMPARE(BF, a, b); } 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 if (!is_64bit_mode && L) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { unsigned_word a; unsigned_word b; if (L == 0) { a = MASKED(*rA, 32, 63); b = MASKED(*rB, 32, 63); } else { a = *rA; b = *rB; } CR_COMPARE(BF, a, b); } # # I.3.3.11 Fixed-Point Trap Instructions # 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate if (!is_64bit_mode) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { signed_word a = *rA; signed_word b = EXTS(SI); if ((a < b && TO{0}) || (a > b && TO{1}) || (a == b && TO{2}) || ((unsigned_word)a < (unsigned_word)b && TO{3}) || ((unsigned_word)a > (unsigned_word)b && TO{4}) ) program_interrupt(processor, cia, trap_program_interrupt); } 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 signed_word a = EXTENDED(*rA); signed_word b = EXTS(SI); if ((a < b && TO{0}) || (a > b && TO{1}) || (a == b && TO{2}) || ((unsigned_word)a < (unsigned_word)b && TO{3}) || ((unsigned_word)a > (unsigned_word)b && TO{4}) ) program_interrupt(processor, cia, trap_program_interrupt); 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword if (!is_64bit_mode) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { signed_word a = *rA; signed_word b = *rB; if ((a < b && TO{0}) || (a > b && TO{1}) || (a == b && TO{2}) || ((unsigned_word)a < (unsigned_word)b && TO{3}) || ((unsigned_word)a > (unsigned_word)b && TO{4}) ) program_interrupt(processor, cia, trap_program_interrupt); } 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 signed_word a = EXTENDED(*rA); signed_word b = EXTENDED(*rB); if (TO == 12 && rA == rB) { ITRACE(trace_breakpoint, ("breakpoint\n")); cpu_halt(processor, cia, was_trap, 0); } else if ((a < b && TO{0}) || (a > b && TO{1}) || (a == b && TO{2}) || ((unsigned_word)a < (unsigned_word)b && TO{3}) || ((unsigned_word)a > (unsigned_word)b && TO{4}) ) program_interrupt(processor, cia, trap_program_interrupt); # # I.3.3.12 Fixed-Point Logical Instructions # 0.28,6.RS,11.RA,16.UI:D:::AND Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS & UI; CR0_COMPARE(*rA, 0, 1/*Rc*/); 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS & (UI << 16); CR0_COMPARE(*rA, 0, 1/*Rc*/); 0.24,6.RS,11.RA,16.UI:D:::OR Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS | UI; 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS | (UI << 16); 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS ^ UI; 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS ^ (UI << 16); 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS & *rB; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS | *rB; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS ^ *rB; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = ~(*rS & *rB); CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = ~(*rS | *rB); CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 # *rA = ~(*rS ^ *rB); /* A === B */ # CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS & ~*rB; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = *rS | ~*rB; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = (signed_word)(signed8)*rS; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 *rA = (signed_word)(signed16)*rS; CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 # *rA = (signed_word)(signed32)*rS; # CR0_COMPARE(*rA, 0, Rc); 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword # int count = 0; # unsigned64 mask = BIT64(0); # unsigned64 source = *rS; # while (!(source & mask) && mask != 0) { # mask >>= 1; # count++; # } # *rA = count; # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */ 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 int count = 0; unsigned32 mask = BIT32(0); unsigned32 source = *rS; while (!(source & mask) && mask != 0) { mask >>= 1; count++; } *rA = count; CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */ # # I.3.3.13 Fixed-Point Rotate and Shift Instructions # 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 # long n = (sh_5 << 4) | sh_0_4; # unsigned_word r = ROTL64(*rS, n); # long b = (mb_5 << 4) | mb_0_4; # unsigned_word m = MASK(b, 63); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */ 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 # long n = (sh_5 << 4) | sh_0_4; # unsigned_word r = ROTL64(*rS, n); # long e = (me_5 << 4) | me_0_4; # unsigned_word m = MASK(0, e); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */ 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 # long n = (sh_5 << 4) | sh_0_4; # unsigned_word r = ROTL64(*rS, n); # long b = (mb_5 << 4) | mb_0_4; # unsigned_word m = MASK(0, (64-n)); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */ 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 long n = SH; unsigned32 s = *rS; unsigned32 r = ROTL32(s, n); unsigned32 m = MASK(MB+32, ME+32); signed_word result = r & m; *rA = result; CR0_COMPARE(result, 0, Rc); ITRACE(trace_alu, ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n", n, s, r, m, result, CR)); 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left # long n = MASKED(*rB, 58, 63); # unsigned_word r = ROTL64(*rS, n); # long b = (mb_5 << 4) | mb_0_4; # unsigned_word m = MASK(b, 63); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right # long n = MASKED(*rB, 58, 63); # unsigned_word r = ROTL64(*rS, n); # long e = (me_5 << 4) | me_0_4; # unsigned_word m = MASK(0, e); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask # long n = MASKED(*rB, 59, 63); # unsigned32 r = ROTL32(*rS, n); # unsigned32 m = MASK(MB+32, ME+32); # signed_word result = r & m; # *rA = result; # CR0_COMPARE(result, 0, Rc); 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 # long n = (sh_5 << 4) | sh_0_4; # unsigned_word r = ROTL64(*rS, n); # long b = (mb_5 << 4) | mb_0_4; # unsigned_word m = MASK(b, (64-n)); # signed_word result = (r & m) | (*rA & ~m) # *rA = result; # CR0_COMPARE(result, 0, Rc); 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 long n = SH; unsigned32 r = ROTL32(*rS, n); unsigned32 m = MASK(MB+32, ME+32); signed_word result = (r & m) | (*rA & ~m); *rA = result; ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n", n, *rS, r, m, result)); CR0_COMPARE(result, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 int n = MASKED(*rB, 59, 63); unsigned32 source = *rS; signed_word shifted; if (n < 32) shifted = (source << n); else shifted = 0; *rA = shifted; CR0_COMPARE(shifted, 0, Rc); ITRACE(trace_alu, ("n=%d, source=0x%x, shifted=0x%x\n", n, source, shifted)); 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 int n = MASKED(*rB, 59, 63); unsigned32 source = *rS; signed_word shifted; if (n < 32) shifted = (source >> n); else shifted = 0; *rA = shifted; CR0_COMPARE(shifted, 0, Rc); ITRACE(trace_alu, \ ("n=%d, source=0x%x, shifted=0x%x\n", n, source, shifted)); 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 int n = SH; signed_word r = ROTL32(*rS, /*64*/32-n); signed_word m = MASK(n+32, 63); int S = MASKED(*rS, 32, 32); signed_word shifted = (r & m) | (S ? ~m : 0); *rA = shifted; if (S && ((r & ~m) & MASK(32, 63)) != 0) XER |= xer_carry; else XER &= ~xer_carry; CR0_COMPARE(shifted, 0, Rc); 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 int n = MASKED(*rB, 58, 63); int shift = (n >= 31 ? 31 : n); signed32 source = (signed32)*rS; /* signed to keep sign bit */ signed32 shifted = source >> shift; unsigned32 mask = ((unsigned32)-1) >> (31-shift); *rA = (signed_word)shifted; /* if 64bit will sign extend */ if (source < 0 && (source & mask)) XER |= xer_carry; else XER &= ~xer_carry; CR0_COMPARE(shifted, 0, Rc); # # I.3.3.14 Move to/from System Register Instructions # 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0 int n = (spr{5:9} << 5) | spr{0:4}; if (spr{0} && IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else if (!spr_is_valid(n) || spr_is_readonly(n)) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { spreg new_val = (spr_length(n) == 64 ? *rS : MASKED(*rS, 32, 63)); /* HACK - time base registers need to be updated immediatly */ if (WITH_TIME_BASE) { signed64 time_base; switch (n) { case spr_tbu: cpu_set_time_base(processor, (MASKED64(cpu_get_time_base(processor), 32, 63) | INSERTED64(new_val, 0, 31))); break; case spr_tbl: cpu_set_time_base(processor, (MASKED64(cpu_get_time_base(processor), 0, 31) | INSERTED64(new_val, 32, 63))); break; case spr_dec: cpu_set_decrementer(processor, new_val); break; default: SPREG(n) = new_val; break; } } else { SPREG(n) = new_val; } } 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0 int n = (spr{5:9} << 5) | spr{0:4}; if (spr{0} && IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else if (!spr_is_valid(n)) program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { /* HACK - some SPR's need to get their value extracted specially */ *rT = SPREG(n); } # FIXME: 604 uses SCIU{1,2} if only one bit is being set 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0 if (FXM == 0xff) { CR = *rS; } else { unsigned_word mask = 0; unsigned_word f; for (f = 0; f < 8; f++) { if (FXM & (0x80 >> f)) mask |= (0xf << 4*(7-f)); } CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask); } 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0 *rT = (unsigned32)CR; # # I.4.6.2 Floating-Point Load Instructions # 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *frT = DOUBLE(MEM(unsigned, EA, 4)); 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *frT = DOUBLE(MEM(unsigned, EA, 4)); 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *frT = DOUBLE(MEM(unsigned, EA, 4)); *rA = EA; 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *frT = DOUBLE(MEM(unsigned, EA, 4)); *rA = EA; 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); *frT = MEM(unsigned, EA, 8); 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; *frT = MEM(unsigned, EA, 8); 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); *frT = MEM(unsigned, EA, 8); *rA = EA; 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; *frT = MEM(unsigned, EA, 8); *rA = EA; # # I.4.6.3 Floating-Point Store Instructions # 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); STORE(EA, 4, SINGLE(*frS)); 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 4, SINGLE(*frS)); 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); STORE(EA, 4, SINGLE(*frS)); *rA = EA; 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; STORE(EA, 4, SINGLE(*frS)); *rA = EA; 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + EXTS(D); STORE(EA, 8, *frS); 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word b; unsigned_word EA; if (RA == 0) b = 0; else b = *rA; EA = b + *rB; STORE(EA, 8, *frS); 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + EXTS(D); STORE(EA, 8, *frS); *rA = EA; 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 unsigned_word EA; if (RA == 0) program_interrupt(processor, cia, illegal_instruction_program_interrupt); EA = *rA + *rB; STORE(EA, 8, *frS); *rA = EA; # # I.4.6.4 Floating-Point Move Instructions # 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *frT = *frB; CR1_UPDATE(Rc); 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *frT = *frB ^ BIT64(0); CR1_UPDATE(Rc); 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *frT = *frB & ~BIT64(0); CR1_UPDATE(Rc); 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *frT = *frB | BIT64(0); CR1_UPDATE(Rc); # # I.4.6.5 Floating-Point Arithmetic Instructions # 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxisi, 0, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ double s = *(double*)frA + *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxisi, 1, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 1); /*single-precision*/ } else { /*HACK!*/ float s = *(double*)frA + *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxisi, 0, /*single?*/ 1) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ double s = *(double*)frA - *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxisi, 1, /*single?*/ 1) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 1); /*single-precision*/ } else { /*HACK!*/ float s = *(double*)frA - *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frC, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ double s = *(double*)frA * *(double*)frC; *(double*)frT = s; } FPSCR_END(Rc); 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frC, fpscr_vxsnan | fpscr_vximz, 1, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 1); /*single-precision*/ } else { /*HACK!*/ float s = *(double*)frA * *(double*)frC; *(double*)frT = s; } FPSCR_END(Rc); 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxzdz, 0, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ double s = *(double*)frA / *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0 FPSCR_BEGIN; if (is_invalid_operation(processor, cia, *frA, *frB, fpscr_vxsnan | fpscr_vxzdz, 1, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, *frA, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 1); /*single-precision*/ } else { /*HACK!*/ float s = *(double*)frA / *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; double product; /*HACK! - incorrectly loosing precision ... */ /* compute the multiply */ if (is_invalid_operation(processor, cia, *frA, *frC, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, (unsigned64*)&product, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ product = *(double*)frA * *(double*)frC; } /* compute the add */ if (is_invalid_operation(processor, cia, product, *frB, fpscr_vxsnan | fpscr_vxisi, 0, /*single?*/ 0) /*negate?*/) { invalid_arithemetic_operation(processor, cia, frT, product, *frB, 0, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ } else { /*HACK!*/ double s = product + *(double*)frB; *(double*)frT = s; } FPSCR_END(Rc); 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 # # I.4.6.6 Floating-Point Rounding and Conversion Instructions # 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 int sign; int exp; unsigned64 frac_grx; /* split off cases for what to do */ if (EXTRACTED64(*frB, 1, 11) < 897 && EXTRACTED64(*frB, 1, 63) > 0) { if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow; if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow; } if (EXTRACTED64(*frB, 1, 11) > 1150 && EXTRACTED64(*frB, 1, 11) < 2047) { if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow; if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow; } if (EXTRACTED64(*frB, 1, 11) > 896 && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand; if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand; if (EXTRACTED64(*frB, 1, 11) == 2047) { if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand; if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand; if (EXTRACTED64(*frB, 12, 12) == 0 && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand; } /* handle them */ Disabled_Exponent_Underflow: sign = EXTRACTED64(*frB, 0, 0); if (EXTRACTED64(*frB, 1, 11) == 0) { exp = -1022; frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); } if (EXTRACTED64(*frB, 1, 11) > 0) { exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); } Denormalize_Operand: /* G|R|X == zero from above */ while (exp < -126) { exp = exp - 1; frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55) | MASKED64(frac_grx, 55, 55)); } FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0); Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); if (EXTRACTED64(frac_grx, 0, 52) == 0) { *frT = INSERTED64(sign, 0, 0); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero); } if (EXTRACTED64(frac_grx, 0, 52) > 0) { if (EXTRACTED64(frac_grx, 0, 0) == 1) { if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); } if (EXTRACTED64(frac_grx, 0, 0) == 0) { if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number); } /*Normalize_Operand:*/ while (EXTRACTED64(frac_grx, 0, 0) == 0) { exp = exp - 1; frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51); } *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); } goto Done; Enabled_Exponent_Underflow: FPSCR_SET_UX(1); sign = EXTRACTED64(*frB, 0, 0); if (EXTRACTED64(*frB, 1, 11) == 0) { exp = -1022; frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); } if (EXTRACTED64(*frB, 1, 11) > 0) { exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = (BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52)); } /*Normalize_Operand:*/ while (EXTRACTED64(frac_grx, 0, 0) == 0) { exp = exp - 1; frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51); } Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); exp = exp + 192; *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); goto Done; Disabled_Exponent_Overflow: FPSCR_SET_OX(1); if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) { if (EXTRACTED64(*frB, 0, 0) == 0) { *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000; FPSCR_SET_FPRF(fpscr_rf_pos_infinity); } if (EXTRACTED64(*frB, 0, 0) == 1) { *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000; FPSCR_SET_FPRF(fpscr_rf_neg_infinity); } } if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) { if (EXTRACTED64(*frB, 0, 0) == 0) { *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000; FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); } if (EXTRACTED64(*frB, 0, 0) == 1) { *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000; FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); } } if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) { if (EXTRACTED64(*frB, 0, 0) == 0) { *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000; FPSCR_SET_FPRF(fpscr_rf_pos_infinity); } if (EXTRACTED64(*frB, 0, 0) == 1) { *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000; FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); } } if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) { if (EXTRACTED64(*frB, 0, 0) == 0) { *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000; FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); } if (EXTRACTED64(*frB, 0, 0) == 1) { *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000; FPSCR_SET_FPRF(fpscr_rf_neg_infinity); } } /* FPSCR[FR] <- undefined */ FPSCR_SET_FI(1); FPSCR_SET_XX(1); goto Done; Enabled_Exponent_Overflow: sign = EXTRACTED64(*frB, 0, 0); exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); Enabled_Overflow: FPSCR_SET_OX(1); exp = exp - 192; *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); goto Done; Zero_Operand: *frT = *frB; if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero); if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero); FPSCR_SET_FR(0); FPSCR_SET_FI(0); goto Done; Infinity_Operand: *frT = *frB; if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity); if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity); FPSCR_SET_FR(0); FPSCR_SET_FI(0); goto Done; QNaN_Operand: *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34); FPSCR_SET_FPRF(fpscr_rf_quiet_nan); FPSCR_SET_FR(0); FPSCR_SET_FI(0); goto Done; SNaN_Operand: FPSCR_OR_VX(fpscr_vxsnan); if ((FPSCR & fpscr_ve) == 0) { *frT = (MASKED64(*frB, 0, 11) | BIT64(12) | MASKED64(*frB, 13, 34)); FPSCR_SET_FPRF(fpscr_rf_quiet_nan); } FPSCR_SET_FR(0); FPSCR_SET_FI(0); goto Done; Normal_Operand: sign = EXTRACTED64(*frB, 0, 0); exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow; if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow; *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); goto Done; Done: 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; convert_to_integer(processor, cia, frT, *frB, fpscr_rn_round_towards_zero, 32); FPSCR_END(Rc); 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword int sign = EXTRACTED64(*frB, 0, 0); int exp = 63; unsigned64 frac = *frB; if (frac == 0) goto Zero_Operand; if (sign == 1) frac = ~frac + 1; while (EXTRACTED64(frac, 0, 0) == 0) { /*??? do the loop 0 times if (FRB) = max negative integer */ frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62); exp = exp - 1; } Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63)); goto Done; /**/ Zero_Operand: FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_SET_FPRF(fpscr_rf_pos_zero); *frT = 0; goto Done; /**/ Done: # # I.4.6.7 Floating-Point Compare Instructions # 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; unsigned c; if (is_NaN(*frA, 0) || is_NaN(*frB, 0)) c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */ else if (is_less_than(frA, frB)) c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */ else if (is_greater_than(frA, frB)) c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */ else c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */ FPSCR_SET_FPCC(c); CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */ if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) FPSCR_OR_VX(fpscr_vxsnan); FPSCR_END(0); 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 FPSCR_BEGIN; unsigned c; if (is_NaN(*frA, 0) || is_NaN(*frB, 0)) c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */ else if (is_less_than(frA, frB)) c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */ else if (is_greater_than(frA, frB)) c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */ else c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */ FPSCR_SET_FPCC(c); CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */ if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) { FPSCR_OR_VX(fpscr_vxsnan); if ((FPSCR & fpscr_ve) == 0) FPSCR_OR_VX(fpscr_vxvc); } else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) { FPSCR_OR_VX(fpscr_vxvc); } FPSCR_END(0); # # I.4.6.8 Floating-Point Status and Control Register Instructions # 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1 # # I.A.1.1 Floating-Point Store Instruction # 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed # # I.A.1.2 Floating-Point Arithmetic Instructions # 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate # # I.A.1.3 Floating-Point Select Instruction # 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select # # II.3.2 Cache Management Instructions # 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE /* blindly flush all instruction cache entries */ #if WITH_IDECODE_CACHE_SIZE cpu_flush_icache(processor); #endif 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE cpu_synchronize_context(processor); # # II.3.2.2 Data Cache Instructions # 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE TRACE(trace_tbd,("Data Cache Block Touch\n")); 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE TRACE(trace_tbd,("Data Cache Block Touch for Store\n")); 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE TRACE(trace_tbd,("Data Cache Block set to Zero\n")); 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE TRACE(trace_tbd,("Data Cache Block Store\n")); 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE TRACE(trace_tbd,("Data Cache Block Flush\n")); # # II.3.3 Enforce In-order Execution of I/O Instruction # 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O /* Since this model has no instruction overlap this instruction need do nothing */ # # II.4.1 Time Base Instructions # 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0 int n = (tbr{5:9} << 5) | tbr{0:4}; if (n == 268) { if (is_64bit_implementation) *rT = TB; else *rT = EXTRACTED64(TB, 32, 63); } else if (n == 269) { if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31); else *rT = EXTRACTED64(TB, 0, 31); } else program_interrupt(processor, cia, illegal_instruction_program_interrupt); # # III.2.3.1 System Linkage Instructions # 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) { program_interrupt(processor, cia, privileged_instruction_program_interrupt); } else { MSR = (MASKED(SRR1, 0, 32) | MASKED(SRR1, 37, 41) | MASKED(SRR1, 48, 63)); NIA = MASKED(SRR0, 0, 61); cpu_synchronize_context(processor); } # # III.3.4.1 Move to/from System Register Instructions # #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else MSR = *rS; 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else *rT = MSR; # # III.4.11.1 Cache Management Instructions # 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, PPC_SERIALIZE *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, PPC_SERIALIZE *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else TRACE(trace_tbd,("Data Cache Block Invalidate\n")); # # III.4.11.2 Segment Register Manipulation Instructions # 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else SEGREG(SR) = *rS; 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS; 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else *rT = SEGREG(SR); 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE if (IS_PROBLEM_STATE(processor)) program_interrupt(processor, cia, privileged_instruction_program_interrupt); else *rT = SEGREG(EXTRACTED32(*rB, 0, 3)); # # III.4.11.3 Lookaside Buffer Management Instructions (Optional) # 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize # # III.A.1.2 External Access Instructions # 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed