binutils-gdb/sim/mips/mips3264r2.igen
Faraz Shahbazker 06c441ccef sim: mips: Add simulator support for mips32r6/mips64r6
2022-02-01  Ali Lown  <ali.lown@imgtec.com>
	    Andrew Bennett  <andrew.bennett@imgtec.com>
	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

sim/common/ChangeLog:
	* sim-bits.h (EXTEND9, EXTEND18 ,EXTEND19, EXTEND21,
	EXTEND26): New macros.

sim/mips/ChangeLog:
	* Makefile.in (IGEN_INCLUDE): Add mips3264r6.igen.
	* configure: Regenerate.
	* configure.ac: Support mipsisa32r6 and mipsisa64r6.
	(sim_engine_run): Pick simulator model from processor specified
	in e_flags.
	* cp1.c (value_fpr): Handle fmt_dc32.
	(fp_unary, fp_binary): Zero initialize locals.
	(update_fcsr, fp_classify, fp_rint, fp_r6_cmp, inner_fmac,
	fp_fmac, fp_min, fp_max, fp_mina, fp_maxa, fp_fmadd, fp_fmsub):
	New functions.
	(sim_fpu_class_mips_mapping): New.
	* cp1.h (fcsr_ABS2008_mask, fcsr_ABS2008_shift): New define.
	* interp.c (MIPSR6_P): New.
	(load_word): Allow unaligned memory access for MIPSR6.
	* micromips.igen (sc, scd): Adapt to new do_sc* helper signature.
	* mips.igen: Add *r6 models.
	(signal_if_cti, forbiddenslot32): New helpers.
	(delayslot32): Use signal_if_cti.
	(do_sc, do_scd); Add store_ll_bit parameter.
	(sc, scd): Adapt to previous change.
	(nal, beq, bal): New definitions for *r6.
	(sll): Split nop and ssnop cases into ...
	(nop, ssnop): New definitions.
	(loadstore_ea): Use the 32-bit compatibility adressing.
	(cache): Split logic into ...
	(do_cache): New helper.
	(check_fpu): Select IEEE 754-2008 mode for R6.
	(not_word_value, unpredictable, check_mt_hilo, check_mf_hilo,
	check_multi_hilo, check_div_hilo, check_u64, do_dmfc1b, add,
	li, addu, and, andi, bgez, bgtz, blez, bltz, bne, break, dadd,
	daddiu, daddu, dror, dror32, drorv, dsll, dsll32, dsllv, dsra,
	dsra32, dsrav, dsrl, dsrl32, dsub, dsubu, j, jal, jalr,
	jalr.hb, lb, lbu, ld, lh, lhu, lui, lw, lwu, nor, or, ori, ror,
	rorv, sb, sd, sh, sll, sllv, slt, slti, sltiu, sltu, sra, srav,
	srl, srlv, sub, subu, sw, sync, syscall, teq, tge, tgeu, tlt,
	tltu, tne, xor, xori, check_fmt_p, do_load_double,
	do_store_double, abs.FMT, add.FMT, ceil.l.FMT, ceil.w.FMT,
	cfc1, ctc1, cvt.d.FMT, cvt.l.FMT, cvt.w.FMT, div.FMT, dfmc1,
	dmtc1, floor.l.FMT, floor.w.FMT, ldc1, lwc1, mfc1, mov.FMT,
	mtc1, mul.FMT, recip.FMT, round.l.FMT, round.w.FMT, rsqrt.FMT,
	sdc1, sqrt.FMT, sub.FMT, swc1, trunc.l.FMT, trunc.w.FMT, bc0f,
	bc0fl, bc0t, bc0tl, dmfc0, dmtc0, eret, mfc0, mtc0, cop, tlbp,
	tlbr, tlbwi, tlbwr): Enable on *r6 models.
	* mips3264r2.igen (dext, dextm, dextu, di, dins, dinsm, dinsu,
	dsbh, dshd, ei, ext, mfhc1, mthc1, ins, seb, seh, synci, rdhwr,
	wsbh): Likewise.
	* mips3264r6.igen: New file.
	* sim-main.h (FP_formats): Add fmt_dc32.
	(FORBIDDEN_SLOT): New macros.
	(simFORBIDDENSLOT, FP_R6CMP_*, FP_R6CLASS_*): New defines.
	(fp_r6_cmp, fp_classify, fp_rint, fp_min, fp_max, fp_mina,
	fp_maxa, fp_fmadd, fp_fmsub): New declarations.
	(R6Compare, Classify, RoundToIntegralExact, Min, Max, MinA,
	MaxA, FusedMultiplyAdd, FusedMultiplySub): New macros. Wrapping
	previous declarations.

sim/testsuite/mips/ChangeLog:
	* basic.exp: Add r6-*.s tests.
	(run_r6_removed_test): New function.
	(run_endian_tests): New function.
	* hilo-hazard-3.s: Skip for mips*r6.
	* r2-fpu.s: New test.
	* r6-64.s: New test.
	* r6-branch.s: New test.
	* r6-forbidden.s: New test.
	* r6-fpu.s: New test.
	* r6-llsc-dp.s: New test.
	* r6-llsc-wp.s: New test.
	* r6-removed.csv: New test.
	* r6-removed.s: New test.
	* r6.s: New test.
	* utils-r6.inc: New inc.
2022-02-04 19:37:26 -05:00

389 lines
7.9 KiB
C

// -*- C -*-
// Simulator definition for the MIPS 32/64 revision 2 instructions.
// Copyright (C) 2004-2022 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 { uint64_t d; uint16_t 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
{
uint64_t 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 { uint32_t w; uint16_t 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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips32r6:
*mips64r2:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips64r6:
{
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:
*mips32r6:
*mips64r2:
*mips64r6:
{
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:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_ext (SD_, RT, RS, LSB, SIZE);
}
010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1
"mfhc1 r<RT>, f<FS>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_mfhc1 (SD_, RT, FS);
}
010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1
"mthc1 r<RT>, f<FS>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
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:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_ins (SD_, RT, RS, LSB, MSB);
}
011111,00000,5.RT,5.RD,10000,100000::32::SEB
"seb r<RD>, r<RT>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_seb (SD_, RD, RT);
}
011111,00000,5.RT,5.RD,11000,100000::32::SEH
"seh r<RD>, r<RT>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_seh (SD_, RD, RT);
}
000001,5.BASE,11111,16.OFFSET::32::SYNCI
"synci <OFFSET>(r<BASE>)"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
// sync i-cache - nothing to do currently
}
011111,00000,5.RT,5.RD,00000,111011::32::RDHWR
"rdhwr r<RT>, r<RD>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_rdhwr (SD_, RT, RD);
}
011111,00000,5.RT,5.RD,00010,100000::32::WSBH
"wsbh r<RD>, r<RT>"
*mips32r2:
*mips32r6:
*mips64r2:
*mips64r6:
{
do_wsbh (SD_, RD, RT);
}