Merge remote-tracking branch 'remotes/lalrae/tags/mips-20141015' into staging

* remotes/lalrae/tags/mips-20141015: (28 commits)
  target-mips: Remove unused gen_load_ACX, gen_store_ACX and cpu_ACX
  target-mips/dsp_helper.c: Add ifdef guards around various functions
  target-mips/translate.c: Add ifdef guard around check_mips64()
  target-mips/op_helper.c: Remove unused do_lbu() function
  target-mips/dsp_helper.c: Remove unused function get_DSPControl_24()
  target-mips: fix broken MIPS16 and microMIPS
  target-mips/translate.c: Update OPC_SYNCI
  target-mips: define a new generic CPU supporting MIPS64 Release 6 ISA
  mips_malta: update malta's pseudo-bootloader - replace JR with JALR
  target-mips: remove JR, BLTZAL, BGEZAL and add NAL, BAL instructions
  target-mips: do not allow Status.FR=0 mode in 64-bit FPU
  target-mips: add new Floating Point Comparison instructions
  target-mips: add new Floating Point instructions
  softfloat: add functions corresponding to IEEE-2008 min/maxNumMag
  target-mips: add AUI, LSA and PCREL instruction families
  target-mips: add compact and CP1 branches
  target-mips: add ALIGN, DALIGN, BITSWAP and DBITSWAP instructions
  target-mips: Status.UX/SX/KX enable 32-bit address wrapping
  target-mips: move CLO, DCLO, CLZ, DCLZ, SDBBP and free special2 in R6
  target-mips: redefine Integer Multiply and Divide instructions
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-10-22 12:06:47 +01:00
commit 31cc9514a5
11 changed files with 3530 additions and 1186 deletions

View File

@ -119,6 +119,8 @@ see <http://www.gnu.org/licenses/>. */
#define OP_SH_IMMEDIATE 0
#define OP_MASK_DELTA 0xffff
#define OP_SH_DELTA 0
#define OP_MASK_DELTA_R6 0x1ff
#define OP_SH_DELTA_R6 7
#define OP_MASK_FUNCT 0x3f
#define OP_SH_FUNCT 0
#define OP_MASK_SPEC 0x3f
@ -405,6 +407,12 @@ struct mips_opcode
"+3" UDI immediate bits 6-20
"+4" UDI immediate bits 6-25
R6 immediates/displacements :
(adding suffix to 'o' to avoid adding new characters)
"+o" 9 bits immediate/displacement (shift = 7)
"+o1" 18 bits immediate/displacement (shift = 0)
"+o2" 19 bits immediate/displacement (shift = 0)
Other:
"()" parens surrounding optional value
"," separates operands
@ -521,6 +529,8 @@ struct mips_opcode
#define INSN_ISA64 0x00000040
#define INSN_ISA32R2 0x00000080
#define INSN_ISA64R2 0x00000100
#define INSN_ISA32R6 0x00000200
#define INSN_ISA64R6 0x00000400
/* Masks used for MIPS-defined ASEs. */
#define INSN_ASE_MASK 0x0000f000
@ -585,6 +595,8 @@ struct mips_opcode
#define ISA_MIPS32R2 (ISA_MIPS32 | INSN_ISA32R2)
#define ISA_MIPS64R2 (ISA_MIPS64 | INSN_ISA32R2 | INSN_ISA64R2)
#define ISA_MIPS32R6 (ISA_MIPS32R2 | INSN_ISA32R6)
#define ISA_MIPS64R6 (ISA_MIPS64R2 | INSN_ISA32R6 | INSN_ISA64R6)
/* CPU defines, use instead of hardcoding processor number. Keep this
in sync with bfd/archures.c in order for machine selection to work. */
@ -1121,6 +1133,8 @@ extern const int bfd_mips16_num_opcodes;
#define I64 INSN_ISA64
#define I33 INSN_ISA32R2
#define I65 INSN_ISA64R2
#define I32R6 INSN_ISA32R6
#define I64R6 INSN_ISA64R6
/* MIPS64 MIPS-3D ASE support. */
#define I16 INSN_MIPS16
@ -1209,6 +1223,146 @@ const struct mips_opcode mips_builtin_opcodes[] =
them first. The assemblers uses a hash table based on the
instruction name anyhow. */
/* name, args, match, mask, pinfo, membership */
{"lwpc", "s,+o2", 0xec080000, 0xfc180000, WR_d, 0, I32R6},
{"lwupc", "s,+o2", 0xec100000, 0xfc180000, WR_d, 0, I64R6},
{"ldpc", "s,+o1", 0xec180000, 0xfc1c0000, WR_d, 0, I64R6},
{"addiupc", "s,+o2", 0xec000000, 0xfc180000, WR_d, 0, I32R6},
{"auipc", "s,u", 0xec1e0000, 0xfc1f0000, WR_d, 0, I32R6},
{"aluipc", "s,u", 0xec1f0000, 0xfc1f0000, WR_d, 0, I32R6},
{"daui", "s,t,u", 0x74000000, 0xfc000000, RD_s|WR_t, 0, I64R6},
{"dahi", "s,u", 0x04060000, 0xfc1f0000, RD_s, 0, I64R6},
{"dati", "s,u", 0x041e0000, 0xfc1f0000, RD_s, 0, I64R6},
{"lsa", "d,s,t", 0x00000005, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6},
{"dlsa", "d,s,t", 0x00000015, 0xfc00073f, WR_d|RD_s|RD_t, 0, I64R6},
{"clz", "U,s", 0x00000050, 0xfc1f07ff, WR_d|RD_s, 0, I32R6},
{"clo", "U,s", 0x00000051, 0xfc1f07ff, WR_d|RD_s, 0, I32R6},
{"dclz", "U,s", 0x00000052, 0xfc1f07ff, WR_d|RD_s, 0, I64R6},
{"dclo", "U,s", 0x00000053, 0xfc1f07ff, WR_d|RD_s, 0, I64R6},
{"sdbbp", "B", 0x0000000e, 0xfc00003f, TRAP, 0, I32R6},
{"mul", "d,s,t", 0x00000098, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"muh", "d,s,t", 0x000000d8, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"mulu", "d,s,t", 0x00000099, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"muhu", "d,s,t", 0x000000d9, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"div", "d,s,t", 0x0000009a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"mod", "d,s,t", 0x000000da, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"divu", "d,s,t", 0x0000009b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"modu", "d,s,t", 0x000000db, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"dmul", "d,s,t", 0x0000009c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"dmuh", "d,s,t", 0x000000dc, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"dmulu", "d,s,t", 0x0000009d, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"dmuhu", "d,s,t", 0x000000dd, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"ddiv", "d,s,t", 0x0000009e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"dmod", "d,s,t", 0x000000de, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"ddivu", "d,s,t", 0x0000009f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"dmodu", "d,s,t", 0x000000df, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6},
{"ll", "t,o(b)", 0x7c000036, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6},
{"sc", "t,o(b)", 0x7c000026, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6},
{"lld", "t,o(b)", 0x7c000037, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6},
{"scd", "t,o(b)", 0x7c000027, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6},
{"pref", "h,o(b)", 0x7c000035, 0xfc00007f, RD_b, 0, I32R6},
{"cache", "k,o(b)", 0x7c000025, 0xfc00007f, RD_b, 0, I32R6},
{"seleqz", "d,v,t", 0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"selnez", "d,v,t", 0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6},
{"maddf.s", "D,S,T", 0x46000018, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"maddf.d", "D,S,T", 0x46200018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"msubf.s", "D,S,T", 0x46000019, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"msubf.d", "D,S,T", 0x46200019, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"max.s", "D,S,T", 0x4600001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"max.d", "D,S,T", 0x4620001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"maxa.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"maxa.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"rint.s", "D,S", 0x4600001a, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6},
{"rint.d", "D,S", 0x4620001a, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6},
{"class.s", "D,S", 0x4600001b, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6},
{"class.d", "D,S", 0x4620001b, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6},
{"min.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"min.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"mina.s", "D,S,T", 0x4600001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"mina.d", "D,S,T", 0x4620001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"sel.s", "D,S,T", 0x46000010, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"sel.d", "D,S,T", 0x46200010, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"seleqz.s", "D,S,T", 0x46000014, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"seleqz.d", "D,S,T", 0x46200014, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"selnez.s", "D,S,T", 0x46000017, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"selnez.d", "D,S,T", 0x46200017, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"align", "d,v,t", 0x7c000220, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6},
{"dalign", "d,v,t", 0x7c000224, 0xfc00063f, WR_d|RD_s|RD_t, 0, I64R6},
{"bitswap", "d,w", 0x7c000020, 0xffe007ff, WR_d|RD_t, 0, I32R6},
{"dbitswap","d,w", 0x7c000024, 0xffe007ff, WR_d|RD_t, 0, I64R6},
{"balc", "+p", 0xe8000000, 0xfc000000, UBD|WR_31, 0, I32R6},
{"bc", "+p", 0xc8000000, 0xfc000000, UBD|WR_31, 0, I32R6},
{"jic", "t,o", 0xd8000000, 0xffe00000, UBD|RD_t, 0, I32R6},
{"beqzc", "s,+p", 0xd8000000, 0xfc000000, CBD|RD_s, 0, I32R6},
{"jialc", "t,o", 0xf8000000, 0xffe00000, UBD|RD_t, 0, I32R6},
{"bnezc", "s,+p", 0xf8000000, 0xfc000000, CBD|RD_s, 0, I32R6},
{"beqzalc", "s,t,p", 0x20000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bovc", "s,t,p", 0x20000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"beqc", "s,t,p", 0x20000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bnezalc", "s,t,p", 0x60000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bnvc", "s,t,p", 0x60000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bnec", "s,t,p", 0x60000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"blezc", "s,t,p", 0x58000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bgezc", "s,t,p", 0x58000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bgec", "s,t,p", 0x58000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bgtzc", "s,t,p", 0x5c000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bltzc", "s,t,p", 0x5c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bltc", "s,t,p", 0x5c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"blezalc", "s,t,p", 0x18000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bgezalc", "s,t,p", 0x18000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bgeuc", "s,t,p", 0x18000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bgtzalc", "s,t,p", 0x1c000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6},
{"bltzalc", "s,t,p", 0x1c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"bltuc", "s,t,p", 0x1c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6},
{"nal", "p", 0x04100000, 0xffff0000, WR_31, 0, I32R6},
{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, 0, I32R6},
{"bc1eqz", "T,p", 0x45200000, 0xffe00000, CBD|RD_T|FP_S|FP_D, 0, I32R6},
{"bc1nez", "T,p", 0x45a00000, 0xffe00000, CBD|RD_T|FP_S|FP_D, 0, I32R6},
{"bc2eqz", "E,p", 0x49200000, 0xffe00000, CBD|RD_C2, 0, I32R6},
{"bc2nez", "E,p", 0x49a00000, 0xffe00000, CBD|RD_C2, 0, I32R6},
{"cmp.af.s", "D,S,T", 0x46800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.un.s", "D,S,T", 0x46800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.eq.s", "D,S,T", 0x46800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.ueq.s", "D,S,T", 0x46800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.lt.s", "D,S,T", 0x46800004, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.ult.s", "D,S,T", 0x46800005, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.le.s", "D,S,T", 0x46800006, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.ule.s", "D,S,T", 0x46800007, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.saf.s", "D,S,T", 0x46800008, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sun.s", "D,S,T", 0x46800009, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.seq.s", "D,S,T", 0x4680000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sueq.s", "D,S,T", 0x4680000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.slt.s", "D,S,T", 0x4680000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sult.s", "D,S,T", 0x4680000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sle.s", "D,S,T", 0x4680000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sule.s", "D,S,T", 0x4680000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.or.s", "D,S,T", 0x46800011, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.une.s", "D,S,T", 0x46800012, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.ne.s", "D,S,T", 0x46800013, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sor.s", "D,S,T", 0x46800019, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sune.s", "D,S,T", 0x4680001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.sne.s", "D,S,T", 0x4680001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6},
{"cmp.af.d", "D,S,T", 0x46a00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.un.d", "D,S,T", 0x46a00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.eq.d", "D,S,T", 0x46a00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.ueq.d", "D,S,T", 0x46a00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.lt.d", "D,S,T", 0x46a00004, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.ult.d", "D,S,T", 0x46a00005, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.le.d", "D,S,T", 0x46a00006, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.ule.d", "D,S,T", 0x46a00007, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.saf.d", "D,S,T", 0x46a00008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sun.d", "D,S,T", 0x46a00009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.seq.d", "D,S,T", 0x46a0000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sueq.d", "D,S,T", 0x46a0000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.slt.d", "D,S,T", 0x46a0000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sult.d", "D,S,T", 0x46a0000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sle.d", "D,S,T", 0x46a0000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sule.d", "D,S,T", 0x46a0000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.or.d", "D,S,T", 0x46a00011, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.une.d", "D,S,T", 0x46a00012, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.ne.d", "D,S,T", 0x46a00013, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sor.d", "D,S,T", 0x46a00019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sune.d", "D,S,T", 0x46a0001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sne.d", "D,S,T", 0x46a0001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4|I32|G3 },
{"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t, 0, I4|I33 },
{"nop", "", 0x00000000, 0xffffffff, 0, INSN2_ALIAS, I1 }, /* sll */
@ -1753,6 +1907,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 },
{"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3 },
{"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 },
{"aui", "s,t,u", 0x3c000000, 0xfc000000, RD_s|WR_t, 0, I32R6},
{"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I5|I33|N55},
{"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 },
{"lw", "t,A(b)", 0, (int) M_LW_AB, INSN_MACRO, 0, I1 },
@ -3575,6 +3730,42 @@ print_insn_args (const char *d,
(*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
break;
case 'o':
switch (*(d+1)) {
case '1':
d++;
delta = l & ((1 << 18) - 1);
if (delta & 0x20000) {
delta |= ~0x1ffff;
}
break;
case '2':
d++;
delta = l & ((1 << 19) - 1);
if (delta & 0x40000) {
delta |= ~0x3ffff;
}
break;
default:
delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6;
if (delta & 0x8000) {
delta |= ~0xffff;
}
}
(*info->fprintf_func) (info->stream, "%d", delta);
break;
case 'p':
/* Sign extend the displacement with 26 bits. */
delta = (l >> OP_SH_DELTA) & OP_MASK_TARGET;
if (delta & 0x2000000) {
delta |= ~0x3FFFFFF;
}
info->target = (delta << 2) + pc + INSNLEN;
(*info->print_address_func) (info->target, info);
break;
case 't': /* Coprocessor 0 reg name */
(*info->fprintf_func) (info->stream, "%s",
mips_cp0_names[(l >> OP_SH_RT) &
@ -3726,7 +3917,8 @@ print_insn_args (const char *d,
case 'j': /* Same as i, but sign-extended. */
case 'o':
delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
if (delta & 0x8000)
delta |= ~0xffff;
(*info->fprintf_func) (info->stream, "%d",
@ -4052,6 +4244,23 @@ print_insn_mips (bfd_vma memaddr,
&& strcmp (op->name, "jalx"))
continue;
if (strcmp(op->name, "bovc") == 0
|| strcmp(op->name, "bnvc") == 0) {
if (((word >> OP_SH_RS) & OP_MASK_RS) <
((word >> OP_SH_RT) & OP_MASK_RT)) {
continue;
}
}
if (strcmp(op->name, "bgezc") == 0
|| strcmp(op->name, "bltzc") == 0
|| strcmp(op->name, "bgezalc") == 0
|| strcmp(op->name, "bltzalc") == 0) {
if (((word >> OP_SH_RS) & OP_MASK_RS) !=
((word >> OP_SH_RT) & OP_MASK_RT)) {
continue;
}
}
/* Figure out instruction type and branch delay information. */
if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
{

View File

@ -7240,13 +7240,17 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
* minnum() and maxnum correspond to the IEEE 754-2008 minNum()
* and maxNum() operations. min() and max() are the typical min/max
* semantics provided by many CPUs which predate that specification.
*
* minnummag() and maxnummag() functions correspond to minNumMag()
* and minNumMag() from the IEEE-754 2008.
*/
#define MINMAX(s) \
static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \
int ismin, int isieee STATUS_PARAM) \
int ismin, int isieee, \
int ismag STATUS_PARAM) \
{ \
flag aSign, bSign; \
uint ## s ## _t av, bv; \
uint ## s ## _t av, bv, aav, abv; \
a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
if (float ## s ## _is_any_nan(a) || \
@ -7266,6 +7270,17 @@ static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \
bSign = extractFloat ## s ## Sign(b); \
av = float ## s ## _val(a); \
bv = float ## s ## _val(b); \
if (ismag) { \
aav = float ## s ## _abs(av); \
abv = float ## s ## _abs(bv); \
if (aav != abv) { \
if (ismin) { \
return (aav < abv) ? a : b; \
} else { \
return (aav < abv) ? b : a; \
} \
} \
} \
if (aSign != bSign) { \
if (ismin) { \
return aSign ? a : b; \
@ -7283,22 +7298,32 @@ static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \
\
float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 1, 0 STATUS_VAR); \
return float ## s ## _minmax(a, b, 1, 0, 0 STATUS_VAR); \
} \
\
float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 0, 0 STATUS_VAR); \
return float ## s ## _minmax(a, b, 0, 0, 0 STATUS_VAR); \
} \
\
float ## s float ## s ## _minnum(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 1, 1 STATUS_VAR); \
return float ## s ## _minmax(a, b, 1, 1, 0 STATUS_VAR); \
} \
\
float ## s float ## s ## _maxnum(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 0, 1 STATUS_VAR); \
return float ## s ## _minmax(a, b, 0, 1, 0 STATUS_VAR); \
} \
\
float ## s float ## s ## _minnummag(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 1, 1, 1 STATUS_VAR); \
} \
\
float ## s float ## s ## _maxnummag(float ## s a, float ## s b STATUS_PARAM) \
{ \
return float ## s ## _minmax(a, b, 0, 1, 1 STATUS_VAR); \
}
MINMAX(32)

View File

@ -697,12 +697,12 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
/* Jump to kernel code */
stl_p(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
stl_p(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x03e00009); /* jalr ra */
stl_p(p++, 0x00000000); /* nop */
/* YAMON subroutines */
p = (uint32_t *) (base + 0x800);
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x03e00009); /* jalr ra */
stl_p(p++, 0x24020000); /* li v0,0 */
/* 808 YAMON print */
stl_p(p++, 0x03e06821); /* move t5,ra */
@ -716,7 +716,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x08000205); /* j 814 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x01a00008); /* jr t5 */
stl_p(p++, 0x01a00009); /* jalr t5 */
stl_p(p++, 0x01602021); /* move a0,t3 */
/* 0x83c YAMON print_count */
stl_p(p++, 0x03e06821); /* move t5,ra */
@ -730,7 +730,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
stl_p(p++, 0x258cffff); /* addiu t4,t4,-1 */
stl_p(p++, 0x1580fffa); /* bnez t4,84c */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x01a00008); /* jr t5 */
stl_p(p++, 0x01a00009); /* jalr t5 */
stl_p(p++, 0x01602021); /* move a0,t3 */
/* 0x870 */
stl_p(p++, 0x3c08b800); /* lui t0,0xb400 */
@ -740,7 +740,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
stl_p(p++, 0x31290040); /* andi t1,t1,0x40 */
stl_p(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x03e00009); /* jalr ra */
stl_p(p++, 0xa1040000); /* sb a0,0(t0) */
}

View File

@ -374,6 +374,8 @@ float32 float32_min(float32, float32 STATUS_PARAM);
float32 float32_max(float32, float32 STATUS_PARAM);
float32 float32_minnum(float32, float32 STATUS_PARAM);
float32 float32_maxnum(float32, float32 STATUS_PARAM);
float32 float32_minnummag(float32, float32 STATUS_PARAM);
float32 float32_maxnummag(float32, float32 STATUS_PARAM);
int float32_is_quiet_nan( float32 );
int float32_is_signaling_nan( float32 );
float32 float32_maybe_silence_nan( float32 );
@ -484,6 +486,8 @@ float64 float64_min(float64, float64 STATUS_PARAM);
float64 float64_max(float64, float64 STATUS_PARAM);
float64 float64_minnum(float64, float64 STATUS_PARAM);
float64 float64_maxnum(float64, float64 STATUS_PARAM);
float64 float64_minnummag(float64, float64 STATUS_PARAM);
float64 float64_maxnummag(float64, float64 STATUS_PARAM);
int float64_is_quiet_nan( float64 a );
int float64_is_signaling_nan( float64 );
float64 float64_maybe_silence_nan( float64 );

View File

@ -431,7 +431,7 @@ struct CPUMIPSState {
int error_code;
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
#define MIPS_HFLAG_TMASK 0xC07FF
#define MIPS_HFLAG_TMASK 0x1807FF
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
@ -450,7 +450,7 @@ struct CPUMIPSState {
and RSQRT.D. */
#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */
#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */
#define MIPS_HFLAG_UX 0x00200 /* 64-bit user mode */
#define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */
#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */
#define MIPS_HFLAG_M16_SHIFT 10
/* If translation is interrupted between the branch instruction and
@ -463,17 +463,18 @@ struct CPUMIPSState {
#define MIPS_HFLAG_BL 0x01800 /* Likely branch */
#define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */
/* Extra flags about the current pending branch. */
#define MIPS_HFLAG_BMASK_EXT 0x3C000
#define MIPS_HFLAG_BMASK_EXT 0x7C000
#define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */
#define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */
#define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */
#define MIPS_HFLAG_BX 0x20000 /* branch exchanges execution mode */
#define MIPS_HFLAG_BDS_STRICT 0x20000 /* Strict delay slot size */
#define MIPS_HFLAG_BX 0x40000 /* branch exchanges execution mode */
#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
/* MIPS DSP resources access. */
#define MIPS_HFLAG_DSP 0x40000 /* Enable access to MIPS DSP resources. */
#define MIPS_HFLAG_DSPR2 0x80000 /* Enable access to MIPS DSPR2 resources. */
#define MIPS_HFLAG_DSP 0x080000 /* Enable access to MIPS DSP resources. */
#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */
/* Extra flag about HWREna register. */
#define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */
target_ulong btarget; /* Jump / branch target */
target_ulong bcond; /* Branch condition (if needed) */
@ -725,7 +726,7 @@ static inline void compute_hflags(CPUMIPSState *env)
{
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
MIPS_HFLAG_UX | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2);
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2);
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
@ -737,8 +738,18 @@ static inline void compute_hflags(CPUMIPSState *env)
(env->CP0_Status & (1 << CP0St_UX))) {
env->hflags |= MIPS_HFLAG_64;
}
if (env->CP0_Status & (1 << CP0St_UX)) {
env->hflags |= MIPS_HFLAG_UX;
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
!(env->CP0_Status & (1 << CP0St_UX))) {
env->hflags |= MIPS_HFLAG_AWRAP;
} else if (env->insn_flags & ISA_MIPS32R6) {
/* Address wrapping for Supervisor and Kernel is specified in R6 */
if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
!(env->CP0_Status & (1 << CP0St_SX))) ||
(((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
!(env->CP0_Status & (1 << CP0St_KX)))) {
env->hflags |= MIPS_HFLAG_AWRAP;
}
}
#endif
if ((env->CP0_Status & (1 << CP0St_CU0)) ||

View File

@ -76,15 +76,6 @@ static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
env->active_tc.DSPControl |= (target_ulong)flag << 24;
}
static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
{
uint32_t filter;
filter = (0x01 << len) - 1;
return (env->active_tc.DSPControl >> 24) & filter;
}
static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
{
target_ulong dspc;
@ -283,6 +274,7 @@ static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
return result;
}
#ifdef TARGET_MIPS64
/* a[0] is LO, a[1] is HI. */
static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
int32_t ac,
@ -336,6 +328,7 @@ static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
set_DSPControl_overflow_flag(1, 16 + ac, env);
}
}
#endif
static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
CPUMIPSState *env)
@ -357,10 +350,12 @@ static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
return a * b;
}
#ifdef TARGET_MIPS64
static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
{
return a * b;
}
#endif
static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
CPUMIPSState *env)
@ -417,10 +412,12 @@ static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
return a >> mov;
}
#ifdef TARGET_MIPS64
static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
{
return a >> mov;
}
#endif
static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
{
@ -479,6 +476,7 @@ static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
return (temp >> 1) & 0x00FF;
}
#ifdef TARGET_MIPS64
static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
{
uint16_t temp;
@ -496,6 +494,7 @@ static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
return (temp >> 1) & 0x00FF;
}
#endif
/* 128 bits long. p[0] is LO, p[1] is HI. */
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
@ -511,6 +510,7 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
p[1] = (acc >> 63) & 0x01;
}
#ifdef TARGET_MIPS64
/* 128 bits long. p[0] is LO, p[1] is HI */
static inline void mipsdsp_rashift_acc(uint64_t *p,
uint32_t ac,
@ -558,6 +558,7 @@ static inline void mipsdsp_rndrashift_acc(uint64_t *p,
}
}
}
#endif
static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
CPUMIPSState *env)
@ -608,10 +609,12 @@ static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
return tempI & 0x0000FFFF;
}
#ifdef TARGET_MIPS64
static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
{
return (uint64_t)a * (uint64_t)b;
}
#endif
static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
CPUMIPSState *env)
@ -717,7 +720,7 @@ static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
return a << s;
}
#ifdef TARGET_MIPS64
static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
CPUMIPSState *env)
{
@ -734,6 +737,7 @@ static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
return a << s;
}
}
#endif
static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
CPUMIPSState *env)
@ -973,6 +977,7 @@ static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
return temp & 0x00FF;
}
#ifdef TARGET_MIPS64
static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
{
int32_t temp;
@ -997,6 +1002,7 @@ static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
return temp;
}
#endif
static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
{

View File

@ -39,6 +39,11 @@ DEF_HELPER_3(macchiu, tl, env, tl, tl)
DEF_HELPER_3(msachi, tl, env, tl, tl)
DEF_HELPER_3(msachiu, tl, env, tl, tl)
DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
#ifdef TARGET_MIPS64
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
#endif
#ifndef CONFIG_USER_ONLY
/* CP0 helpers */
DEF_HELPER_1(mfc0_mvpcontrol, tl, env)
@ -197,6 +202,25 @@ DEF_HELPER_2(float_cvtw_d, i32, env, i64)
DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64)
#define FOP_PROTO(op) \
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64)
FOP_PROTO(maddf)
FOP_PROTO(msubf)
#undef FOP_PROTO
#define FOP_PROTO(op) \
DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \
DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64)
FOP_PROTO(max)
FOP_PROTO(maxa)
FOP_PROTO(min)
FOP_PROTO(mina)
#undef FOP_PROTO
#define FOP_PROTO(op) \
DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \
DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \
@ -214,6 +238,7 @@ DEF_HELPER_2(float_ ## op ## _d, i64, env, i64)
FOP_PROTO(sqrt)
FOP_PROTO(rsqrt)
FOP_PROTO(recip)
FOP_PROTO(rint)
#undef FOP_PROTO
#define FOP_PROTO(op) \
@ -279,6 +304,33 @@ FOP_PROTO(le)
FOP_PROTO(ngt)
#undef FOP_PROTO
#define FOP_PROTO(op) \
DEF_HELPER_3(r6_cmp_d_ ## op, i64, env, i64, i64) \
DEF_HELPER_3(r6_cmp_s_ ## op, i32, env, i32, i32)
FOP_PROTO(af)
FOP_PROTO(un)
FOP_PROTO(eq)
FOP_PROTO(ueq)
FOP_PROTO(lt)
FOP_PROTO(ult)
FOP_PROTO(le)
FOP_PROTO(ule)
FOP_PROTO(saf)
FOP_PROTO(sun)
FOP_PROTO(seq)
FOP_PROTO(sueq)
FOP_PROTO(slt)
FOP_PROTO(sult)
FOP_PROTO(sle)
FOP_PROTO(sule)
FOP_PROTO(or)
FOP_PROTO(une)
FOP_PROTO(ne)
FOP_PROTO(sor)
FOP_PROTO(sune)
FOP_PROTO(sne)
#undef FOP_PROTO
/* Special functions */
#ifndef CONFIG_USER_ONLY
DEF_HELPER_1(tlbwi, void, env)

View File

@ -30,17 +30,21 @@
#define ISA_MIPS64 0x00000080
#define ISA_MIPS64R2 0x00000100
#define ISA_MIPS32R3 0x00000200
#define ISA_MIPS32R5 0x00000400
#define ISA_MIPS64R3 0x00000400
#define ISA_MIPS32R5 0x00000800
#define ISA_MIPS64R5 0x00001000
#define ISA_MIPS32R6 0x00002000
#define ISA_MIPS64R6 0x00004000
/* MIPS ASEs. */
#define ASE_MIPS16 0x00001000
#define ASE_MIPS3D 0x00002000
#define ASE_MDMX 0x00004000
#define ASE_DSP 0x00008000
#define ASE_DSPR2 0x00010000
#define ASE_MT 0x00020000
#define ASE_SMARTMIPS 0x00040000
#define ASE_MICROMIPS 0x00080000
#define ASE_MIPS16 0x00010000
#define ASE_MIPS3D 0x00020000
#define ASE_MDMX 0x00040000
#define ASE_DSP 0x00080000
#define ASE_DSPR2 0x00100000
#define ASE_MT 0x00200000
#define ASE_SMARTMIPS 0x00400000
#define ASE_MICROMIPS 0x00800000
/* Chip specific instructions. */
#define INSN_LOONGSON2E 0x20000000
@ -68,9 +72,15 @@
/* MIPS Technologies "Release 3" */
#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3)
#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3)
/* MIPS Technologies "Release 5" */
#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5)
#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5)
/* MIPS Technologies "Release 6" */
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6)
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6)
/* Strictly follow the architecture standard:
- Disallow "special" instruction handling for PMON/SPIM.

View File

@ -90,7 +90,6 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
} \
}
#endif
HELPER_LD(lbu, ldub, uint8_t)
HELPER_LD(lw, ldl, int32_t)
#ifdef TARGET_MIPS64
HELPER_LD(ld, ldq, int64_t)
@ -266,6 +265,29 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
(uint64_t)(uint32_t)arg2);
}
static inline target_ulong bitswap(target_ulong v)
{
v = ((v >> 1) & (target_ulong)0x5555555555555555) |
((v & (target_ulong)0x5555555555555555) << 1);
v = ((v >> 2) & (target_ulong)0x3333333333333333) |
((v & (target_ulong)0x3333333333333333) << 2);
v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0F) |
((v & (target_ulong)0x0F0F0F0F0F0F0F0F) << 4);
return v;
}
#ifdef TARGET_MIPS64
target_ulong helper_dbitswap(target_ulong rt)
{
return bitswap(rt);
}
#endif
target_ulong helper_bitswap(target_ulong rt)
{
return (int32_t)bitswap(rt);
}
#ifndef CONFIG_USER_ONLY
static inline hwaddr do_translate_address(CPUMIPSState *env,
@ -2786,6 +2808,110 @@ FLOAT_UNOP(abs)
FLOAT_UNOP(chs)
#undef FLOAT_UNOP
#define FLOAT_FMADDSUB(name, bits, muladd_arg) \
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
uint ## bits ## _t fs, \
uint ## bits ## _t ft, \
uint ## bits ## _t fd) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
&env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
}
FLOAT_FMADDSUB(maddf_s, 32, 0)
FLOAT_FMADDSUB(maddf_d, 64, 0)
FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
#undef FLOAT_FMADDSUB
#define FLOAT_MINMAX(name, bits, minmaxfunc) \
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
uint ## bits ## _t fs, \
uint ## bits ## _t ft) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
&env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
}
FLOAT_MINMAX(max_s, 32, maxnum)
FLOAT_MINMAX(max_d, 64, maxnum)
FLOAT_MINMAX(maxa_s, 32, maxnummag)
FLOAT_MINMAX(maxa_d, 64, maxnummag)
FLOAT_MINMAX(min_s, 32, minnum)
FLOAT_MINMAX(min_d, 64, minnum)
FLOAT_MINMAX(mina_s, 32, minnummag)
FLOAT_MINMAX(mina_d, 64, minnummag)
#undef FLOAT_MINMAX
#define FLOAT_RINT(name, bits) \
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
uint ## bits ## _t fs) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
}
FLOAT_RINT(rint_s, 32)
FLOAT_RINT(rint_d, 64)
#undef FLOAT_RINT
#define FLOAT_CLASS_SIGNALING_NAN 0x001
#define FLOAT_CLASS_QUIET_NAN 0x002
#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004
#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008
#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
#define FLOAT_CLASS_NEGATIVE_ZERO 0x020
#define FLOAT_CLASS_POSITIVE_INFINITY 0x040
#define FLOAT_CLASS_POSITIVE_NORMAL 0x080
#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
#define FLOAT_CLASS_POSITIVE_ZERO 0x200
#define FLOAT_CLASS(name, bits) \
uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \
{ \
if (float ## bits ## _is_signaling_nan(arg)) { \
return FLOAT_CLASS_SIGNALING_NAN; \
} else if (float ## bits ## _is_quiet_nan(arg)) { \
return FLOAT_CLASS_QUIET_NAN; \
} else if (float ## bits ## _is_neg(arg)) { \
if (float ## bits ## _is_infinity(arg)) { \
return FLOAT_CLASS_NEGATIVE_INFINITY; \
} else if (float ## bits ## _is_zero(arg)) { \
return FLOAT_CLASS_NEGATIVE_ZERO; \
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \
} else { \
return FLOAT_CLASS_NEGATIVE_NORMAL; \
} \
} else { \
if (float ## bits ## _is_infinity(arg)) { \
return FLOAT_CLASS_POSITIVE_INFINITY; \
} else if (float ## bits ## _is_zero(arg)) { \
return FLOAT_CLASS_POSITIVE_ZERO; \
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
return FLOAT_CLASS_POSITIVE_SUBNORMAL; \
} else { \
return FLOAT_CLASS_POSITIVE_NORMAL; \
} \
} \
}
FLOAT_CLASS(class_s, 32)
FLOAT_CLASS(class_d, 64)
#undef FLOAT_CLASS
/* MIPS specific unary operations */
uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
{
@ -3261,3 +3387,114 @@ FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status),
float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
/* R6 compare operations */
#define FOP_CONDN_D(op, cond) \
uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState * env, uint64_t fdt0, \
uint64_t fdt1) \
{ \
uint64_t c; \
c = cond; \
update_fcr31(env, GETPC()); \
if (c) { \
return -1; \
} else { \
return 0; \
} \
}
/* NOTE: the comma operator will make "cond" to eval to false,
* but float64_unordered_quiet() is still called. */
FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)))
FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
/* NOTE: the comma operator will make "cond" to eval to false,
* but float64_unordered() is still called. */
FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)))
FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
|| float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
#define FOP_CONDN_S(op, cond) \
uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState * env, uint32_t fst0, \
uint32_t fst1) \
{ \
uint64_t c; \
c = cond; \
update_fcr31(env, GETPC()); \
if (c) { \
return -1; \
} else { \
return 0; \
} \
}
/* NOTE: the comma operator will make "cond" to eval to false,
* but float32_unordered_quiet() is still called. */
FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)))
FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
/* NOTE: the comma operator will make "cond" to eval to false,
* but float32_unordered() is still called. */
FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)))
FOP_CONDN_S(seq, (float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(slt, (float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sle, (float32_le(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_le(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sor, (float32_le(fst1, fst0, &env->active_fpu.fp_status)
|| float32_le(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst0, fst1, &env->active_fpu.fp_status)))

File diff suppressed because it is too large Load Diff

View File

@ -515,6 +515,36 @@ static const mips_def_t mips_defs[] =
.insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
.mmu_type = MMU_TYPE_R4000,
},
{
/* A generic CPU supporting MIPS64 Release 6 ISA.
FIXME: It does not support all the MIPS64R6 features yet.
Eventually this should be replaced by a real CPU model. */
.name = "MIPS64R6-generic",
.CP0_PRid = 0x00010000,
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
(MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x30D8FFFF,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
(0x0 << FCR0_REV),
.SEGBITS = 42,
/* The architectural limit is 59, but we have hardcoded 36 bit
in some places...
.PABITS = 59, */ /* the architectural limit */
.PABITS = 36,
.insn_flags = CPU_MIPS64R6,
.mmu_type = MMU_TYPE_R4000,
},
{
.name = "Loongson-2E",
.CP0_PRid = 0x6302,