mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
8e394ffc7a
2015-09-25 Andrew Bennett <andrew.bennett@imgtec.com> Ali Lown <ali.lown@imgtec.com> sim/common/ * sim-bits.h (EXTEND6): New macro. (EXTEND12): New macro. (EXTEND25): New macro. sim/mips/ * Makefile.in (tmp-micromips): New rule. (tmp-mach-multi): Add support for micromips. * configure.ac (mips*-sde-elf* | mips*-mti-elf*): Made a multi sim that works for both mips64 and micromips64. (mipsisa32r2*-*-*): Made a multi sim that works for mips32 and micromips32. Add build support for micromips. * dsp.igen (do_ph_s_absq, do_w_s_absq, do_qb_s_absq, do_addsc, do_addwc, do_bitrev, do_extpv, do_extrv, do_extrv_s_h, do_insv, do_lxx do_modsub, do_mthlip, do_mulsaq_s_w_ph, do_ph_packrl, do_qb_pick do_ph_pick, do_qb_ph_precequ, do_qb_ph_preceu, do_w_preceq do_w_ph_precrq, do_ph_qb_precrq, do_w_ph_rs_precrq do_qb_w_raddu, do_rddsp, do_repl, do_shilov, do_ph_shl, do_qb_shl do_w_s_shllv, do_ph_shrlv, do_w_r_shrav, do_wrdsp, do_qb_shrav, do_append, do_balign, do_ph_w_mulsa, do_ph_qb_precr, do_prepend): New functions. Refactored instruction code to use these functions. * dsp2.igen: Refactored instruction code to use the new functions. * interp.c (decode_coproc): Refactored to work with any instruction encoding. (isa_mode): New variable (RSVD_INSTRUCTION): Changed to 0x00000039. * m16.igen (BREAK16): Refactored instruction to use do_break16. (JALX32): Add mips32, mips64, mips32r2 and mips64r2 models. * micromips.dc: New file. * micromips.igen: New file. * micromips16.dc: New file. * micromipsdsp.igen: New file. * micromipsrun.c: New file. * mips.igen (do_swc1): Changed to work with any instruction encoding. (do_add do_addi do_andi do_dadd do_daddi do_dsll32 do_dsra32 do_dsrl32, do_dsub, do_break, do_break16, do_clo, do_clz, do_dclo do_dclz, do_lb, do_lh, do_lwr, do_lwl, do_lwc, do_lw, do_lwu, do_lhu do_ldc, do_lbu, do_ll, do_lld, do_lui, do_madd, do_dsp_madd, do_maddu do_dsp_maddu, do_dsp_mfhi, do_dsp_mflo, do_movn, do_movz, do_msub do_dsp_msub, do_msubu, do_dsp_msubu, do_mthi, do_dsp_mthi, do_mtlo do_dsp_mtlo, do_mul, do_dsp_mult, do_dsp_multu, do_pref, do_sc, do_scd do_sub, do_sw, do_teq, do_teqi, do_tge, do_tgei, do_tgeiu, do_tgeu, do_tlt do_tlti, do_tltiu, do_tltu, do_tne, do_tnei, do_abs_fmt, do_add_fmt do_alnv_ps, do_c_cond_fmt, do_ceil_fmt, do_cfc1, do_ctc1, do_cvt_d_fmt do_cvt_l_fmt, do_cvt_ps_s, do_cvt_s_fmt, do_cvt_s_pl, do_cvt_s_pu do_cvt_w_fmt, do_div_fmt, do_dmfc1b, do_dmtc1b, do_floor_fmt, do_luxc1_32 do_luxc1_64, do_lwc1, do_lwxc1, do_madd_fmt, do_mfc1b, do_mov_fmt, do_movtf do_movtf_fmt, do_movn_fmt, do_movz_fmt, do_msub_fmt, do_mtc1b, do_mul_fmt do_neg_fmt, do_nmadd_fmt, do_nmsub_fmt, do_pll_ps, do_plu_ps, do_pul_ps do_puu_ps, do_recip_fmt, do_round_fmt, do_rsqrt_fmt, do_prefx, do_sdc1 do_suxc1_32, do_suxc1_64, do_sqrt_fmt, do_sub_fmt, do_swc1, do_swxc1 do_trunc_fmt): New functions, refactored from existing instructions. Refactored instruction code to use these functions. (RSVD): Changed to use new reserved instruction. (loadstore_ea, not_word_value, unpredictable, check_mt_hilo, check_mf_hilo, check_mult_hilo, check_div_hilo, check_u64, do_luxc1_32, do_sdc1, do_suxc1_32, check_fmt_p, check_fpu, do_load_double, do_store_double): Added micromips32 and micromips64 models. Added include for micromips.igen and micromipsdsp.igen Add micromips32 and micromips64 models. (DecodeCoproc): Updated to use new macro definition. * mips3264r2.igen (do_dsbh, do_dshd, do_dext, do_dextm, do_dextu, do_di, do_dins, do_dinsm, do_ei, do_ext, do_mfhc1, do_mthc1, do_ins, do_dinsu, do_seb, do_seh do_rdhwr, do_wsbh): New functions. Refactored instruction code to use these functions. * sim-main.h (CP0_operation): New enum. (DecodeCoproc): Updated macro. (IMEM32_MICROMIPS, IMEM16_MICROMIPS, MICROMIPS_MINOR_OPCODE, MICROMIPS_DELAYSLOT_SIZE_ANY, MICROMIPS_DELAYSLOT_SIZE_16, MICROMIPS_DELAYSLOT_SIZE_32, ISA_MODE_MIPS32 and ISA_MODE_MICROMIPS): New defines. (sim_state): Add isa_mode field. sim/testsuite/sim/mips/ * basic.exp (run_micromips_test, run_sim_tests): New functions Add support for micromips tests. * hilo-hazard-4.s: New file. * testutils.inc (_dowrite): Changed reserved instruction encoding. (writemsg): Moved the la and li instructions before the data they are assigned to, which prevents a bug where MIPS32 relocations are used instead of micromips relocations when building for micromips.
359 lines
7.6 KiB
C
359 lines
7.6 KiB
C
// -*- C -*-
|
|
|
|
// Simulator definition for the MIPS 32/64 revision 2 instructions.
|
|
// Copyright (C) 2004-2015 Free Software Foundation, Inc.
|
|
// Contributed by David Ung, of MIPS Technologies.
|
|
//
|
|
// This file is part of the MIPS sim.
|
|
//
|
|
// 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
:function:::void:do_dsbh:int rd, int rt
|
|
{
|
|
union { unsigned64 d; unsigned16 h[4]; } u;
|
|
TRACE_ALU_INPUT1 (GPR[rt]);
|
|
u.d = GPR[rt];
|
|
u.h[0] = SWAP_2 (u.h[0]);
|
|
u.h[1] = SWAP_2 (u.h[1]);
|
|
u.h[2] = SWAP_2 (u.h[2]);
|
|
u.h[3] = SWAP_2 (u.h[3]);
|
|
GPR[rd] = u.d;
|
|
TRACE_ALU_RESULT1 (GPR[rd]);
|
|
}
|
|
|
|
:function:::void:do_dshd:int rd, int rt
|
|
{
|
|
unsigned64 d;
|
|
TRACE_ALU_INPUT1 (GPR[rt]);
|
|
d = GPR[rt];
|
|
GPR[rd] = ((d >> 48)
|
|
| (d << 48)
|
|
| ((d & 0x0000ffff00000000ULL) >> 16)
|
|
| ((d & 0x00000000ffff0000ULL) << 16));
|
|
TRACE_ALU_RESULT1 (GPR[rd]);
|
|
}
|
|
|
|
:function:::void:do_dext:int rt, int rs, int lsb, int size
|
|
{
|
|
TRACE_ALU_INPUT3 (GPR[rs], lsb, size);
|
|
GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size, lsb);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_dextm:int rt, int rs, int lsb, int size
|
|
{
|
|
TRACE_ALU_INPUT3 (GPR[rs], lsb, size);
|
|
GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size + 32, lsb);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_dextu:int rt, int rs, int lsb, int size
|
|
{
|
|
TRACE_ALU_INPUT3 (GPR[rs], lsb, size);
|
|
GPR[rt] = EXTRACTED64 (GPR[rs], lsb + 32 + size, lsb + 32);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_di:int rt
|
|
{
|
|
TRACE_ALU_INPUT0 ();
|
|
GPR[rt] = EXTEND32 (SR);
|
|
SR &= ~status_IE;
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_dins:int rt, int rs, int lsb, int msb
|
|
{
|
|
TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb);
|
|
if (lsb <= msb)
|
|
GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb, lsb);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_dinsm:int rt, int rs, int lsb, int msb
|
|
{
|
|
TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb);
|
|
if (lsb <= msb + 32)
|
|
GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb + 32, lsb);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_ei:int rt
|
|
{
|
|
TRACE_ALU_INPUT0 ();
|
|
GPR[rt] = EXTEND32 (SR);
|
|
SR |= status_IE;
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_ext:int rt, int rs, int lsb, int size
|
|
{
|
|
TRACE_ALU_INPUT3 (GPR[rs], lsb, size);
|
|
GPR[rt] = EXTEND32 (EXTRACTED32 (GPR[rs], lsb + size, lsb));
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_mfhc1:int rt, int fs
|
|
{
|
|
check_fpu (SD_);
|
|
if (SizeFGR() == 64)
|
|
GPR[rt] = EXTEND32 (WORD64HI (FGR[fs]));
|
|
else if ((fs & 0x1) == 0)
|
|
GPR[rt] = EXTEND32 (FGR[fs + 1]);
|
|
else
|
|
{
|
|
if (STATE_VERBOSE_P(SD))
|
|
sim_io_eprintf (SD,
|
|
"Warning: PC 0x%lx: MFHC1 32-bit use of odd FPR number\n",
|
|
(long) CIA);
|
|
GPR[rt] = EXTEND32 (0xBADF00D);
|
|
}
|
|
TRACE_ALU_RESULT (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_mthc1:int rt, int fs
|
|
{
|
|
check_fpu (SD_);
|
|
if (SizeFGR() == 64)
|
|
StoreFPR (fs, fmt_uninterpreted_64, SET64HI (GPR[rt]) | VL4_8 (FGR[fs]));
|
|
else if ((fs & 0x1) == 0)
|
|
StoreFPR (fs + 1, fmt_uninterpreted_32, VL4_8 (GPR[rt]));
|
|
else
|
|
{
|
|
if (STATE_VERBOSE_P(SD))
|
|
sim_io_eprintf (SD,
|
|
"Warning: PC 0x%lx: MTHC1 32-bit use of odd FPR number\n",
|
|
(long) CIA);
|
|
StoreFPR (fs, fmt_uninterpreted_32, 0xDEADC0DE);
|
|
}
|
|
TRACE_FP_RESULT (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_ins:int rt, int rs, int lsb, int msb
|
|
{
|
|
TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb);
|
|
if (lsb <= msb)
|
|
GPR[rt] = EXTEND32 (GPR[rt] ^
|
|
((GPR[rt] ^ (GPR[rs] << lsb)) & MASK32 (msb, lsb)));
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_dinsu:int rt, int rs, int lsb, int msb
|
|
{
|
|
TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb);
|
|
if (lsb <= msb)
|
|
GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << (lsb + 32)))
|
|
& MASK64 (msb + 32, lsb + 32);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_seb:int rd, int rt
|
|
{
|
|
TRACE_ALU_INPUT1 (GPR[rt]);
|
|
GPR[rd] = EXTEND8 (GPR[rt]);
|
|
TRACE_ALU_RESULT1 (GPR[rd]);
|
|
}
|
|
|
|
:function:::void:do_seh:int rd, int rt
|
|
{
|
|
TRACE_ALU_INPUT1 (GPR[rt]);
|
|
GPR[rd] = EXTEND16 (GPR[rt]);
|
|
TRACE_ALU_RESULT1 (GPR[rd]);
|
|
}
|
|
|
|
:function:::void:do_rdhwr:int rt, int rd
|
|
{
|
|
// Return 0 for all hardware registers currently
|
|
GPR[rt] = EXTEND32 (0);
|
|
TRACE_ALU_RESULT1 (GPR[rt]);
|
|
}
|
|
|
|
:function:::void:do_wsbh:int rd, int rt
|
|
{
|
|
union { unsigned32 w; unsigned16 h[2]; } u;
|
|
TRACE_ALU_INPUT1 (GPR[rt]);
|
|
u.w = GPR[rt];
|
|
u.h[0] = SWAP_2 (u.h[0]);
|
|
u.h[1] = SWAP_2 (u.h[1]);
|
|
GPR[rd] = EXTEND32 (u.w);
|
|
TRACE_ALU_RESULT1 (GPR[rd]);
|
|
}
|
|
|
|
011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT
|
|
"dext r<RT>, r<RS>, <LSB>, <SIZE+1>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dext (SD_, RT, RS, LSB, SIZE);
|
|
}
|
|
|
|
011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM
|
|
"dextm r<RT>, r<RS>, <LSB>, <SIZE+33>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dextm (SD_, RT, RS, LSB, SIZE);
|
|
}
|
|
|
|
011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU
|
|
"dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dextu (SD_, RT, RS, LSB, SIZE);
|
|
}
|
|
|
|
|
|
010000,01011,5.RT,01100,00000,0,00,000::32::DI
|
|
"di":RT == 0
|
|
"di r<RT>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_di (SD_, RT);
|
|
}
|
|
|
|
|
|
011111,5.RS,5.RT,5.MSB,5.LSB,000111::64::DINS
|
|
"dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dins (SD_, RT, RS, LSB, MSB);
|
|
}
|
|
|
|
011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM
|
|
"dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dinsm (SD_, RT, RS, LSB, MSB);
|
|
}
|
|
|
|
011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU
|
|
"dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dinsu (SD_, RT, RS, LSB, MSB);
|
|
}
|
|
|
|
|
|
011111,00000,5.RT,5.RD,00010,100100::64::DSBH
|
|
"dsbh r<RD>, r<RT>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dsbh (SD_, RD, RT);
|
|
}
|
|
|
|
011111,00000,5.RT,5.RD,00101,100100::64::DSHD
|
|
"dshd r<RD>, r<RT>"
|
|
*mips64r2:
|
|
{
|
|
check_u64 (SD_, instruction_0);
|
|
do_dshd (SD_, RD, RT);
|
|
}
|
|
|
|
010000,01011,5.RT,01100,00000,1,00,000::32::EI
|
|
"ei":RT == 0
|
|
"ei r<RT>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_ei (SD_, RT);
|
|
}
|
|
|
|
|
|
011111,5.RS,5.RT,5.SIZE,5.LSB,000000::32::EXT
|
|
"ext r<RT>, r<RS>, <LSB>, <SIZE+1>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_ext (SD_, RT, RS, LSB, SIZE);
|
|
}
|
|
|
|
|
|
010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1
|
|
"mfhc1 r<RT>, f<FS>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_mfhc1 (SD_, RT, FS);
|
|
}
|
|
|
|
010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1
|
|
"mthc1 r<RT>, f<FS>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_mthc1 (SD_, RT, FS);
|
|
}
|
|
|
|
|
|
011111,5.RS,5.RT,5.MSB,5.LSB,000100::32::INS
|
|
"ins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_ins (SD_, RT, RS, LSB, MSB);
|
|
}
|
|
|
|
|
|
011111,00000,5.RT,5.RD,10000,100000::32::SEB
|
|
"seb r<RD>, r<RT>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_seb (SD_, RD, RT);
|
|
}
|
|
|
|
011111,00000,5.RT,5.RD,11000,100000::32::SEH
|
|
"seh r<RD>, r<RT>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_seh (SD_, RD, RT);
|
|
}
|
|
|
|
|
|
000001,5.BASE,11111,16.OFFSET::32::SYNCI
|
|
"synci <OFFSET>(r<BASE>)"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
// sync i-cache - nothing to do currently
|
|
}
|
|
|
|
|
|
011111,00000,5.RT,5.RD,00000,111011::32::RDHWR
|
|
"rdhwr r<RT>, r<RD>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_rdhwr (SD_, RT, RD);
|
|
}
|
|
|
|
|
|
011111,00000,5.RT,5.RD,00010,100000::32::WSBH
|
|
"wsbh r<RD>, r<RT>"
|
|
*mips32r2:
|
|
*mips64r2:
|
|
{
|
|
do_wsbh (SD_, RD, RT);
|
|
}
|
|
|
|
|
|
|