X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=sim%2Fppc%2Fppc-instructions;h=9f9773477f772e72577ce3527ee3a6a4c1ee46e1;hb=84f9f8c33021593afd79fc89cc419db44f7bc112;hp=6ebe0812e7a4003405246f6842cf2b7ac0d217f0;hpb=1996fae84682e8ddd146215dd2959ad1ec924c09;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions index 6ebe0812e7..9f9773477f 100644 --- a/sim/ppc/ppc-instructions +++ b/sim/ppc/ppc-instructions @@ -1,7 +1,7 @@ # # This file is part of the program psim. # -# Copyright (C) 1994-1997, Andrew Cagney +# Copyright 1994, 1995, 1996, 1997, 2003, 2004 Andrew Cagney # # -- # @@ -21,7 +21,7 @@ # # 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 +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, @@ -30,9 +30,55 @@ # 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. +# along with this program; if not, see . # + +:cache::::RA:RA: +:cache:::signed_word *:rA:RA:(cpu_registers(processor)->gpr + RA) +:cache:::unsigned32:RA_BITMASK:RA:(1 << RA) +:compute:::int:RA_is_0:RA:(RA == 0) +:cache::::RT:RT: +:cache:::signed_word *:rT:RT:(cpu_registers(processor)->gpr + RT) +:cache:::unsigned32:RT_BITMASK:RT:(1 << RT) +:cache::::RS:RS: +:cache:::signed_word *:rS:RS:(cpu_registers(processor)->gpr + RS) +:cache:::unsigned32:RS_BITMASK:RS:(1 << RS) +:cache::::RB:RB: +:cache:::signed_word *:rB:RB:(cpu_registers(processor)->gpr + RB) +:cache:::unsigned32:RB_BITMASK:RB:(1 << RB) +:scratch::::FRA:FRA: +:cache:::unsigned64 *:frA:FRA:(cpu_registers(processor)->fpr + FRA) +:cache:::unsigned32:FRA_BITMASK:FRA:(1 << FRA) +:scratch::::FRB:FRB: +:cache:::unsigned64 *:frB:FRB:(cpu_registers(processor)->fpr + FRB) +:cache:::unsigned32:FRB_BITMASK:FRB:(1 << FRB) +:scratch::::FRC:FRC: +:cache:::unsigned64 *:frC:FRC:(cpu_registers(processor)->fpr + FRC) +:cache:::unsigned32:FRC_BITMASK:FRC:(1 << FRC) +:scratch::::FRS:FRS: +:cache:::unsigned64 *:frS:FRS:(cpu_registers(processor)->fpr + FRS) +:cache:::unsigned32:FRS_BITMASK:FRS:(1 << FRS) +:scratch::::FRT:FRT: +:cache:::unsigned64 *:frT:FRT:(cpu_registers(processor)->fpr + FRT) +:cache:::unsigned32:FRT_BITMASK:FRT:(1 << FRT) +:cache:::unsigned_word:EXTS_SI:SI:((signed_word)(signed16)instruction) +:scratch::::BI:BI: +:cache::::BIT32_BI:BI:BIT32(BI) +:cache::::BF:BF: +:cache:::unsigned32:BF_BITMASK:BF:(1 << BF) +:scratch::::BA:BA: +:cache::::BIT32_BA:BA:BIT32(BA) +:cache:::unsigned32:BA_BITMASK:BA:(1 << BA) +:scratch::::BB:BB: +:cache::::BIT32_BB:BB:BIT32(BB) +:cache:::unsigned32:BB_BITMASK:BB:(1 << BB) +:cache::::BT:BT: +:cache:::unsigned32:BT_BITMASK:BT:(1 << BT) +:cache:::unsigned_word:EXTS_BD_0b00:BD:(((signed_word)(signed16)instruction) & ~3) +:cache:::unsigned_word:EXTS_LI_0b00:LI:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3) +:cache:::unsigned_word:EXTS_D:D:((signed_word)(signed16)(instruction)) +:cache:::unsigned_word:EXTS_DS_0b00:DS:(((signed_word)(signed16)instruction) & ~0x3) +#:compute:::int:SPR_is_256:SPR:(SPR == 256) # PowerPC models ::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0 @@ -151,6 +197,8 @@ unsigned32 fp_busy; /* floating point registers that are busy */ unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */ signed16 spr_busy; /* SPR register that is busy or PPC_NO_SPR */ + unsigned32 vr_busy; /* AltiVec registers that are busy */ + signed16 vscr_busy; /* AltiVec status register busy */ signed16 issue; /* # of cycles until unit can accept another insn */ signed16 done; /* # of cycles until insn is done */ signed16 nr_writebacks; /* # of registers this unit writes back */ @@ -181,6 +229,8 @@ unsigned32 fp_busy; /* floating point registers that are busy */ unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */ unsigned8 spr_busy[nr_of_sprs]; /* SPR registers that are busy */ + unsigned32 vr_busy; /* AltiVec registers that are busy */ + unsigned8 vscr_busy; /* AltiVec SC register busy */ unsigned8 busy[nr_ppc_function_units]; /* whether a function is busy or not */ }; @@ -273,6 +323,15 @@ void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy } if (busy->spr_busy != PPC_NO_SPR) TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy))); + if (busy->vr_busy) { + for(i = 0; i < 32; i++) { + if (((1 << i) & busy->vr_busy) != 0) { + TRACE(trace_model, ("Register v%d is now available.\n", i)); + } + } + } + if (busy->vscr_busy) + TRACE(trace_model, ("VSCR Register is now available.\n", spr_name(busy->spr_busy))); # Trace making registers busy void::model-static::model_trace_make_busy:model_data *model_ptr, unsigned32 int_mask, unsigned32 fp_mask, unsigned32 cr_mask @@ -351,6 +410,8 @@ void::model-internal::model_new_cycle:model_data *model_ptr model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy; if (cur_busy->spr_busy != PPC_NO_SPR) model_ptr->spr_busy[cur_busy->spr_busy] = 0; + model_ptr->vr_busy &= ~cur_busy->vr_busy; + model_ptr->vscr_busy = ~cur_busy->vscr_busy; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_release(model_ptr, cur_busy); @@ -407,6 +468,8 @@ model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_functio busy->fp_busy = 0; busy->cr_fpscr_busy = 0; busy->nr_writebacks = 0; + busy->vr_busy = 0; + busy->vscr_busy = 0; } busy->unit = unit; @@ -671,7 +734,7 @@ void::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, busy_ptr->nr_writebacks = 1; TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR))); -# Schedule a MFCR instruction that moves the CR into an integer regsiter +# Schedule a MFCR instruction that moves the CR into an integer register void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, unsigned32 int_mask const unsigned32 cr_mask = 0xff; model_busy *busy_ptr; @@ -845,7 +908,7 @@ model_print *::model-function::model_mon_info:model_data *model_ptr tail->suffix_singular = ""; } - for (j = 0; j < (sizeof(ppc_branch_conditional_name) / sizeof(ppc_branch_conditional_name[0])) ; j++) { + for (j = 0; j < ARRAY_SIZE (ppc_branch_conditional_name); j++) { if (model_ptr->nr_branch_conditional[j]) { tail->next = ZALLOC(model_print); tail = tail->next; @@ -1217,7 +1280,7 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 /* FPSCR[fprf] = undefined */ } /**/ - LABEL(Done): + LABEL(Done):; # extract out raw fields of a FP number @@ -1440,7 +1503,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, *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 - /* WITH_OPTION_MPC860C0 + /* option_mpc860c0: No problem here because this branch is predicted taken (unconditional). */ if (AA) NIA = IEA(EXTS(LI_0b00)); else NIA = IEA(CIA + EXTS(LI_0b00)); @@ -1469,9 +1532,8 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); - #ifdef WITH_OPTION_MPC860C0 - if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) { - /* This branch is predicted as not-taken. + if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) { + /* This branch is predicted as "normal". If this is a forward branch and it is near the end of a page, we've detected a problematic branch. */ if (succeed && NIA > CIA) { @@ -1479,7 +1541,6 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt); } } - #endif // WITH_OPTION_MPC860C0 if (CURRENT_MODEL_ISSUE > 0) model_branches(cpu_model(processor), succeed, BO); if (! BO{0}) { @@ -1513,8 +1574,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); - #ifdef WITH_OPTION_MPC860C0 - if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) { + if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) { /* This branch is predicted as not-taken. If this is a forward branch and it is near the end of a page, we've detected a problematic branch. */ @@ -1523,7 +1583,6 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt); } } - #endif // WITH_OPTION_MPC860C0 if (CURRENT_MODEL_ISSUE > 0) { model_branches(cpu_model(processor), succeed, BO); if (! BO{0}) @@ -1546,8 +1605,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, else succeed = 0; if (LK) LR = (spreg)IEA(CIA + 4); - #ifdef WITH_OPTION_MPC860C0 - if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) { + if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) { /* This branch is predicted as not-taken. If this is a forward branch and it is near the end of a page, we've detected a problematic branch. */ @@ -1556,7 +1614,6 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt); } } - #endif // WITH_OPTION_MPC860C0 if (CURRENT_MODEL_ISSUE > 0) { model_branches(cpu_model(processor), succeed, BO); if (! BO{0}) @@ -2262,6 +2319,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, GPR(r) = 0; } GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7); + i = i + 8; if (i == 64) i = 32; EA = EA + 1; n = n - 1; @@ -2281,11 +2339,11 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, r = RT - 1; i = 32; nr = (n + 3) / 4; - if (((RT + n >= 32) - ? ((RA >= RT || RA < (RT + n) % 32) - || (RB >= RT || RB < (RT + n) % 32)) - : ((RA >= RT && RA < RT + n) - || (RB >= RT && RB < RT + n))) + if (((RT + nr >= 32) + ? ((RA >= RT || RA < (RT + nr) % 32) + || (RB >= RT || RB < (RT + nr) % 32)) + : ((RA >= RT && RA < RT + nr) + || (RB >= RT && RB < RT + nr))) || (RT == RA || RT == RB)) program_interrupt(processor, cia, illegal_instruction_program_interrupt); @@ -2294,7 +2352,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, while (n > 0) { if (i == 32) { r = (r + 1) % 32; - GPR(i) = 0; + GPR(r) = 0; } GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7); i = i + 8; @@ -2435,7 +2493,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, } PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/); -0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize +0.31,6./,9.L,11./,16./,21.598,31./:X::sync:Synchronize *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 @@ -3297,7 +3355,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, spreg new_val = (spr_length(n) == 64 ? *rS : MASKED(*rS, 32, 63)); - /* HACK - time base registers need to be updated immediatly */ + /* HACK - time base registers need to be updated immediately */ if (WITH_TIME_BASE) { switch (n) { case spr_tbu: @@ -3343,6 +3401,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, case spr_dec: *rT = cpu_get_decrementer(processor); break; + case spr_tbrl: + if (is_64bit_implementation) *rT = TB; + else *rT = EXTRACTED64(TB, 32, 63); + break; + case spr_tbru: + if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31); + else *rT = EXTRACTED64(TB, 0, 31); + break; case spr_tbu: case spr_tbl: /* NOTE - these SPR's are not readable. Use mftb[ul] */ @@ -3432,7 +3498,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, *rA = EA; PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0); -0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed +0.31,6.FRT,11.RA,16.RB,21.567,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 @@ -3585,6 +3651,18 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, STORE(EA, 8, *frS); PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK); +0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point Integer Word Indexed +*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_is_0) b = 0; + else b = *rA; + EA = b + *rB; + STORE(EA, 4, *frS); + PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK); + 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 @@ -3894,12 +3972,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -3939,12 +4019,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 1, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -3984,12 +4066,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4029,12 +4113,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 1, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4074,12 +4160,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4119,12 +4207,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 1, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4164,12 +4254,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 0, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4209,12 +4301,14 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, fpscr_vxsnan | fpscr_vximz, 1, /*single?*/ 0) /*negate?*/) { + union { double d; unsigned64 u; } tmp; invalid_arithemetic_operation(processor, cia, - (unsigned64*)&product, *frA, 0, *frC, + &tmp.u, *frA, 0, *frC, 0, /*instruction_is_frsp*/ 0, /*instruction_is_convert_to_64bit*/ 0, /*instruction_is_convert_to_32bit*/ 0); /*single-precision*/ + product = tmp.d; } else { /*HACK!*/ @@ -4288,7 +4382,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, } /* G|R|X == zero from above */ while (exp < -126) { - exp = exp - 1; + exp = exp + 1; frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55) | MASKED64(frac_grx, 55, 55)); } @@ -4588,7 +4682,7 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */ FPSCR_END(0); -0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate +0.63,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate FPSCR_BEGIN; FPSCR_SET(BF, U); FPSCR_END(Rc); @@ -4623,13 +4717,6 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, FPSCR |= bit; FPSCR_END(Rc); - -# -# I.A.1.1 Floating-Point Store Instruction -# -0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed - program_interrupt(processor, cia, optional_instruction_program_interrupt); - # # I.A.1.2 Floating-Point Arithmetic Instructions # @@ -4931,3 +5018,6 @@ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, 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 + +:include:::altivec.igen +:include:::e500.igen