[PATCH 3 12/16] MIPS: Add GINV(+VIRT) ASE for MIPSr6/microMIPS6
Jovan Dmitrovic
jovan.dmitrovic@htecgroup.com
Thu Feb 5 16:24:13 GMT 2026
From: Faraz Shahbazker <fshahbazker@wavecomp.com>
gas/
* config/tc-mips.c (mips_ases): Add microMIPS ASE.
(mips_set_ase): Set combination VZ+GINV ASE flag.
include/
* opcode/mips.h: Add note for micromips +\ format descriptor.
(ASE_GINV_VIRT): New macro.
opcodes/
* micromips-opc.c (decode_micromips_operand) <+\>: New format.
(GINV): New macro.
(GINVVZ): New macro.
(micromips_opcodes): Add instructions from GINV ASE.
* mips-opc.c (GINVVZ): New macro.
(mips_opcodes): Add instructions from GINV+VZ ASE.
* mips-dis.c (mips_calculate_combination_ases): Handle combination
ASE for VZ & GINV.
gas/testsuite/
* gas/mips/ginv.s: Add test case.
* gas/mips/micromips@ginv.d: New test.
* gas/mips/micromips@ginv-virt.d: New test.
* gas/mips/ginv-virt.d: New test.
* gas/mips/mips.exp: Run the new tests.
(cherry picked from commit 20e4af66461818a0ae184ade12e2fede0243bbce)
---
gas/config/tc-mips.c | 11 ++++++++-
gas/testsuite/gas/mips/ginv-virt.d | 22 ++++++++++++++++++
gas/testsuite/gas/mips/ginv.s | 5 ++++
gas/testsuite/gas/mips/micromips@ginv-virt.d | 24 ++++++++++++++++++++
gas/testsuite/gas/mips/micromips@ginv.d | 20 ++++++++++++++++
gas/testsuite/gas/mips/mips.exp | 5 ++--
include/opcode/mips.h | 7 ++++++
opcodes/micromips-opc.c | 10 ++++++++
opcodes/mips-dis.c | 2 ++
opcodes/mips-opc.c | 2 ++
10 files changed, 105 insertions(+), 3 deletions(-)
create mode 100644 gas/testsuite/gas/mips/ginv-virt.d
create mode 100644 gas/testsuite/gas/mips/micromips@ginv-virt.d
create mode 100644 gas/testsuite/gas/mips/micromips@ginv.d
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 3f7323073a4..e75cbf48f63 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -2248,7 +2248,7 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
/* Clear combination ASE flags, which need to be recalculated based on
updated regular ASE settings. */
- opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT | ASE_EVA_R6);
+ opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT | ASE_EVA_R6 | ASE_GINV_VIRT);
if (enabled_p)
opts->ase |= ase->flags;
@@ -2276,6 +2276,15 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
mask |= ASE_EVA_R6;
}
+ /* The Virtualization ASE has Global INValidate (GINV) instructions
+ which are only valid when both ASEs are enabled. This sets the
+ ASE_GINV_VIRT flag when both ASEs are present. */
+ if ((opts->ase & (ASE_GINV | ASE_VIRT)) == (ASE_GINV | ASE_VIRT))
+ {
+ opts->ase |= ASE_GINV_VIRT;
+ mask |= ASE_GINV_VIRT;
+ }
+
return mask;
}
diff --git a/gas/testsuite/gas/mips/ginv-virt.d b/gas/testsuite/gas/mips/ginv-virt.d
new file mode 100644
index 00000000000..50fa6d5416d
--- /dev/null
+++ b/gas/testsuite/gas/mips/ginv-virt.d
@@ -0,0 +1,22 @@
+#objdump: -pdr --prefix-addresses --show-raw-insn
+#name: MIPS GINV Virtualization
+#as: --defsym VX= -mginv -mvirt -32
+#source: ginv.s
+
+# Test GINV+VZ instructions.
+
+.*: +file format .*mips.*
+#...
+ASEs:
+#...
+ VZ ASE
+ GINV ASE
+#...
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 7c40003d ginvi v0
+[0-9a-f]+ <[^>]*> 7c6000bd ginvt v1,0x0
+[0-9a-f]+ <[^>]*> 7c8001bd ginvt a0,0x1
+[0-9a-f]+ <[^>]*> 7c8002fd ginvgt a0,0x2
+[0-9a-f]+ <[^>]*> 7ca003fd ginvgt a1,0x3
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/ginv.s b/gas/testsuite/gas/mips/ginv.s
index 63cfb15002b..80159948655 100644
--- a/gas/testsuite/gas/mips/ginv.s
+++ b/gas/testsuite/gas/mips/ginv.s
@@ -4,6 +4,11 @@ test:
ginvt $3,0
ginvt $4,1
+ .ifdef VX
+ ginvgt $4,2
+ ginvgt $5,3
+ .endif
+
# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 2
.space 8
diff --git a/gas/testsuite/gas/mips/micromips@ginv-virt.d b/gas/testsuite/gas/mips/micromips@ginv-virt.d
new file mode 100644
index 00000000000..df1b25d1a06
--- /dev/null
+++ b/gas/testsuite/gas/mips/micromips@ginv-virt.d
@@ -0,0 +1,24 @@
+#objdump: -pdr --prefix-addresses --show-raw-insn
+#name: microMIPSr6 Global INValidate Virtualization instructions
+#as: --defsym VX= -mginv -mvirt -32
+#source: ginv.s
+
+# Check microMIPSR6 Global INValidate Virtualization instructions
+
+.*: +file format .*mips.*
+
+#...
+ASEs:
+#...
+ VZ ASE
+ MICROMIPS ASE
+ GINV ASE
+#...
+
+Disassembly of section .text:
+[0-9a-f]+ <[^>]*> 0002 617c ginvi v0
+[0-9a-f]+ <[^>]*> 0003 717c ginvt v1,0x0
+[0-9a-f]+ <[^>]*> 0004 737c ginvt a0,0x1
+[0-9a-f]+ <[^>]*> 0004 7d7c ginvgt a0,0x2
+[0-9a-f]+ <[^>]*> 0005 7f7c ginvgt a1,0x3
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/micromips@ginv.d b/gas/testsuite/gas/mips/micromips@ginv.d
new file mode 100644
index 00000000000..841f4cf1a3e
--- /dev/null
+++ b/gas/testsuite/gas/mips/micromips@ginv.d
@@ -0,0 +1,20 @@
+#objdump: -pdr --prefix-addresses --show-raw-insn
+#name: microMIPSR6 Global INValidate instructions
+#as: -mginv -32
+#source: ginv.s
+
+# Check microMIPS Global INValidate instructions
+
+.*: +file format .*mips.*
+#...
+ASEs:
+#...
+ MICROMIPS ASE
+ GINV ASE
+#...
+
+Disassembly of section .text:
+[0-9a-f]+ <[^>]*> 0002 617c ginvi v0
+[0-9a-f]+ <[^>]*> 0003 717c ginvt v1,0x0
+[0-9a-f]+ <[^>]*> 0004 737c ginvt a0,0x1
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 5c863133704..839515c674a 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -2277,8 +2277,9 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test_arches "crc64" [mips_arch_list_matching mips64r6 !micromipsr6]
run_dump_test_arches "crc64-err" [mips_arch_list_matching mips64r6 !micromipsr6]
- run_dump_test_arches "ginv" [mips_arch_list_matching mips32r6 !micromipsr6]
- run_dump_test_arches "ginv-err" [mips_arch_list_matching mips32r6 !micromipsr6]
+ run_dump_test_arches "ginv" [mips_arch_list_matching mips32r6]
+ run_dump_test_arches "ginv-err" [mips_arch_list_matching mips32r6]
+ run_dump_test_arches "ginv-virt" [mips_arch_list_matching mips32r6]
run_dump_test_arches "ur6" "-32 -mmicromips" \
[mips_arch_list_matching mips32r6 !mips64r6]
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index 35b4273fdfe..c4162ceccd7 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -1085,6 +1085,10 @@ static const unsigned int mips_isa_table[] = {
#define ASE_EVA_R6 0x02000000
/* Crypto ASE */
#define ASE_CRYPTO 0x04000000
+/* The Virtualization ASE has Global INValidate (GINV)
+ instructions which are only valid when both ASEs are enabled. */
+#define ASE_GINV_VIRT 0x08000000
+
/* MIPS ISA defines, use instead of hardcoding ISA level. */
@@ -1956,6 +1960,9 @@ extern const int bfd_mips16_num_opcodes;
"J" 3-bit MFTR and MTTR sel at bit 4.
"y" 5-bit control target register at bit 21 (RT).
+ GINV ASE usage:
+ "+\" 2 bit Global TLB invalidate type at bit 8
+
Other:
"()" Parens surrounding optional value.
"," Separates operands.
diff --git a/opcodes/micromips-opc.c b/opcodes/micromips-opc.c
index 34f54f827e9..afda685ce13 100644
--- a/opcodes/micromips-opc.c
+++ b/opcodes/micromips-opc.c
@@ -175,6 +175,7 @@ decode_micromips_operand (const char *p)
case ':': SINT (11, 0);
case '.': BIT (2, 9, 1); /* (1 .. 4) */
case ';': SPECIAL (10, 16, SAME_RS_RT);
+ case '\\': BIT (2, 9, 0); /* (00 .. 11) */
}
break;
@@ -339,6 +340,10 @@ decode_micromips_operand (const char *p)
#define XPA ASE_XPA
#define XPAVZ ASE_XPA_VIRT
+/* Global INValidate (GINV) support. */
+#define GINV ASE_GINV
+#define GINVVZ ASE_GINV_VIRT
+
const struct mips_opcode micromips_opcodes[] =
{
/* These instructions appear first so that the disassembler will find
@@ -2236,6 +2241,11 @@ const struct mips_opcode micromips_opcodes[] =
{"lsa", "d,v,t,+.", 0x0000000f, 0xfc0001ff, WR_1|RD_2|RD_3, 0, I37, MSA, 0 },
{"dlsa", "d,v,t,+~", 0x58000020, 0xfc00073f, WR_1|RD_2|RD_3, 0, 0, MSA64, I69 },
{"dlsa", "d,v,t,+.", 0x58000108, 0xfc0001ff, WR_1|RD_2|RD_3, 0, I69, MSA64, 0 },
+
+/* Global INValidate ASE */
+{"ginvi", "s", 0x0000617c, 0xffe0ffff, RD_1, 0, 0, GINV, 0 },
+{"ginvt", "s,+\\", 0x0000717c, 0xffe0f9ff, RD_1, 0, 0, GINV, 0 },
+{"ginvgt", "s,+\\", 0x0000797c, 0xffe0f9ff, RD_1, 0, 0, GINVVZ, 0 },
};
const int bfd_micromips_num_opcodes =
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index e000d762d32..1474b6a237c 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -907,6 +907,8 @@ mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
&& ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
|| (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
combination_ases |= ASE_EVA_R6;
+ if ((opcode_ases & (ASE_GINV | ASE_VIRT)) == (ASE_GINV | ASE_VIRT))
+ combination_ases |= ASE_GINV_VIRT;
return combination_ases;
}
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index 7324952a64a..ff7c6c07ed9 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -419,6 +419,7 @@ decode_mips_operand (const char *p)
/* Global INValidate (GINV) support. */
#define GINV ASE_GINV
+#define GINVVZ ASE_GINV_VIRT
/* Loongson MultiMedia extensions Instructions (MMI) support. */
#define LMMI ASE_LOONGSON_MMI
@@ -3379,6 +3380,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
/* MIPS Global INValidate (GINV) ASE. */
{"ginvi", "s", 0x7c00003d, 0xfc1fffff, RD_1, 0, 0, GINV, 0 },
{"ginvt", "s,+\\", 0x7c0000bd, 0xfc1ffcff, RD_1, 0, 0, GINV, 0 },
+{"ginvgt", "s,+\\", 0x7c0000fd, 0xfc1ffcff, RD_1, 0, 0, GINVVZ, 0 },
/* Move bc0* after mftr and mttr to avoid opcode collision. */
{"bc0f", "p", 0x41000000, 0xffff0000, RD_CC|CBD, 0, I1, 0, I4_32 },
--
2.34.1
More information about the Binutils
mailing list