diff --git a/riscv64/riscv64asm/decode.go b/riscv64/riscv64asm/decode.go
index 390edfa..6cc218b 100644
--- a/riscv64/riscv64asm/decode.go
+++ b/riscv64/riscv64asm/decode.go
@@ -503,6 +503,30 @@
newargs[1] = args[0]
newargs[2] = args[1]
+ case C_NTL_P1:
+ f.op = ADD
+ newargs[0] = X0
+ newargs[1] = X0
+ newargs[2] = X2
+
+ case C_NTL_PALL:
+ f.op = ADD
+ newargs[0] = X0
+ newargs[1] = X0
+ newargs[2] = X3
+
+ case C_NTL_S1:
+ f.op = ADD
+ newargs[0] = X0
+ newargs[1] = X0
+ newargs[2] = X4
+
+ case C_NTL_ALL:
+ f.op = ADD
+ newargs[0] = X0
+ newargs[1] = X0
+ newargs[2] = X5
+
case C_SWSP:
f.op = SW
newargs[0] = args[0]
diff --git a/riscv64/riscv64asm/gnu.go b/riscv64/riscv64asm/gnu.go
index 324b365..2557999 100644
--- a/riscv64/riscv64asm/gnu.go
+++ b/riscv64/riscv64asm/gnu.go
@@ -86,7 +86,13 @@
}
case ADD:
- if inst.Args[1].(Reg) == X0 {
+ if ntl := ntlName(inst); ntl != "" {
+ op = ntl
+ if inst.Len == 2 {
+ op = "c." + op
+ }
+ args = nil
+ } else if inst.Args[1].(Reg) == X0 {
op = "mv"
args[1] = args[2]
args = args[:len(args)-1]
@@ -380,6 +386,24 @@
return op
}
+func ntlName(inst Inst) string {
+ if inst.Op != ADD || inst.Args[0].(Reg) != X0 || inst.Args[1].(Reg) != X0 {
+ return ""
+ }
+
+ switch inst.Args[2].(Reg) {
+ case X2:
+ return "ntl.p1"
+ case X3:
+ return "ntl.pall"
+ case X4:
+ return "ntl.s1"
+ case X5:
+ return "ntl.all"
+ }
+ return ""
+}
+
func gnuVectorOp(inst Inst, args []string) string {
// Instruction is either a vector load, store or an arithmetic
// operation. We can use the inst.Enc to figure out which. Whatever
diff --git a/riscv64/riscv64asm/objdump_test.go b/riscv64/riscv64asm/objdump_test.go
index ddaa28c..4f8059f 100644
--- a/riscv64/riscv64asm/objdump_test.go
+++ b/riscv64/riscv64asm/objdump_test.go
@@ -88,6 +88,30 @@
return true
}
+ // Older objdump versions print the underlying ADD/C.ADD forms instead
+ // of the Zihintntl pseudo-instruction names.
+ if allowedLegacyNtlMismatch(inst, dec.text) {
+ return true
+ }
+
+ return false
+}
+
+func allowedLegacyNtlMismatch(inst *Inst, text string) bool {
+ ntl := ntlName(*inst)
+ if ntl == "" {
+ return false
+ }
+
+ switch inst.Args[2].(Reg) {
+ case X2, X3, X4, X5:
+ reg := inst.Args[2].(Reg)
+ if inst.Len == 2 {
+ return text == "c.add x0,"+reg.String()
+ }
+ return text == "add x0,x0,"+reg.String()
+ }
+
return false
}
@@ -128,3 +152,31 @@
}
return false
}
+
+func TestAllowedMismatchObjdumpLegacyNtl(t *testing.T) {
+ tests := []struct {
+ name string
+ enc []byte
+ text string
+ want bool
+ }{
+ {name: "base ntl", enc: []byte{0x33, 0x00, 0x20, 0x00}, text: "add x0,x0,x2", want: true},
+ {name: "compressed ntl", enc: []byte{0x0a, 0x90}, text: "c.add x0,x2", want: true},
+ {name: "wrong base reg", enc: []byte{0x33, 0x00, 0x20, 0x00}, text: "add x0,x0,x6", want: false},
+ {name: "wrong compressed text", enc: []byte{0x0a, 0x90}, text: "c.mv x0,x2", want: false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ inst, err := Decode(tt.enc)
+ if err != nil {
+ t.Fatalf("Decode(%x): %v", tt.enc, err)
+ }
+
+ got := allowedMismatchObjdump("", &inst, ExtInst{text: tt.text}, "")
+ if got != tt.want {
+ t.Fatalf("allowedMismatchObjdump(%x, %q) = %v, want %v", tt.enc, tt.text, got, tt.want)
+ }
+ })
+ }
+}
diff --git a/riscv64/riscv64asm/plan9x.go b/riscv64/riscv64asm/plan9x.go
index 59f2a5b..b5e2d8b 100644
--- a/riscv64/riscv64asm/plan9x.go
+++ b/riscv64/riscv64asm/plan9x.go
@@ -75,6 +75,12 @@
args = args[:len(args)-1]
}
+ case ADD:
+ if ntl := ntlName(inst); ntl != "" {
+ op = strings.ToUpper(ntl)
+ args = nil
+ }
+
case ORI:
if inst.Args[0].(Reg) == X0 {
simm := inst.Args[2].(Simm)
diff --git a/riscv64/riscv64asm/tables.go b/riscv64/riscv64asm/tables.go
index f96c307..9dc030f 100644
--- a/riscv64/riscv64asm/tables.go
+++ b/riscv64/riscv64asm/tables.go
@@ -150,6 +150,10 @@
C_LWSP
C_MV
C_NOP
+ C_NTL_ALL
+ C_NTL_P1
+ C_NTL_PALL
+ C_NTL_S1
C_OR
C_SD
C_SDSP
@@ -1174,6 +1178,10 @@
C_LWSP: "C.LWSP",
C_MV: "C.MV",
C_NOP: "C.NOP",
+ C_NTL_ALL: "C.NTL.ALL",
+ C_NTL_P1: "C.NTL.P1",
+ C_NTL_PALL: "C.NTL.PALL",
+ C_NTL_S1: "C.NTL.S1",
C_OR: "C.OR",
C_SD: "C.SD",
C_SDSP: "C.SDSP",
@@ -2340,6 +2348,14 @@
{mask: 0x0000f003, value: 0x00008002, op: C_MV, args: argTypeList{arg_rd_n0, arg_c_rs2_n0}},
// C.NOP c_nzimm6
{mask: 0x0000ef83, value: 0x00000001, op: C_NOP, args: argTypeList{arg_c_nzimm6}},
+ // C.NTL.ALL
+ {mask: 0x0000ffff, value: 0x00009016, op: C_NTL_ALL, args: argTypeList{}},
+ // C.NTL.P1
+ {mask: 0x0000ffff, value: 0x0000900a, op: C_NTL_P1, args: argTypeList{}},
+ // C.NTL.PALL
+ {mask: 0x0000ffff, value: 0x0000900e, op: C_NTL_PALL, args: argTypeList{}},
+ // C.NTL.S1
+ {mask: 0x0000ffff, value: 0x00009012, op: C_NTL_S1, args: argTypeList{}},
// C.OR rd_rs1_p, rs2_p
{mask: 0x0000fc63, value: 0x00008c41, op: C_OR, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}},
// C.SD rs1_p, rs2_p, c_uimm8
diff --git a/riscv64/riscv64asm/testdata/gnucases.txt b/riscv64/riscv64asm/testdata/gnucases.txt
index db1fc8f..e12670e 100644
--- a/riscv64/riscv64asm/testdata/gnucases.txt
+++ b/riscv64/riscv64asm/testdata/gnucases.txt
@@ -413,6 +413,16 @@
# 10.1: "Zihintpause" Extension for Pause Hint, Version 1.0.0
0f000001| pause
+# "Zihintntl" Extension for Non-Temporal Locality Hints
+33002000| ntl.p1
+33003000| ntl.pall
+33004000| ntl.s1
+33005000| ntl.all
+0a90| c.ntl.p1
+0e90| c.ntl.pall
+1290| c.ntl.s1
+1690| c.ntl.all
+
# 12.3: "Zicond" Extension for Integer Conditional Operations, Version 1.0.0
b353530e| czero.eqz x7,x6,x5
b373530e| czero.nez x7,x6,x5
diff --git a/riscv64/riscv64asm/testdata/plan9cases.txt b/riscv64/riscv64asm/testdata/plan9cases.txt
index a361d65..884efd8 100644
--- a/riscv64/riscv64asm/testdata/plan9cases.txt
+++ b/riscv64/riscv64asm/testdata/plan9cases.txt
@@ -366,6 +366,16 @@
# 10.1: "Zihintpause" Extension for Pause Hint, Version 1.0.0
0f000001| PAUSE
+# "Zihintntl" Extension for Non-Temporal Locality Hints
+33002000| NTLP1
+33003000| NTLPALL
+33004000| NTLS1
+33005000| NTLALL
+0a90| NTLP1
+0e90| NTLPALL
+1290| NTLS1
+1690| NTLALL
+
# 12.3: "Zicond" Extension for Integer Conditional Operations, Version 1.0.0
b353530e| CZEROEQZ X5, X6, X7
b373530e| CZERONEZ X5, X6, X7
diff --git a/riscv64/riscv64spec/spec.go b/riscv64/riscv64spec/spec.go
index 887dd14..b88e922 100644
--- a/riscv64/riscv64spec/spec.go
+++ b/riscv64/riscv64spec/spec.go
@@ -26,6 +26,7 @@
"rv_a",
"rv_c",
"rv_c_d",
+ "rv_c_zihintntl",
"rv_d",
"rv_f",
"rv_i",
@@ -111,9 +112,9 @@
continue
}
- // skip $pseudo_op except rv_zbb/rv64_zbb
+ // skip $pseudo_op except rv_zbb/rv64_zbb/rv_c_zihintntl
if words[0][0] == '$' {
- if ext != "rv_zbb" && ext != "rv64_zbb" {
+ if ext != "rv_zbb" && ext != "rv64_zbb" && ext != "rv_c_zihintntl" {
continue
}
words = words[2:]