Skip to content

Commit 0f9c8fb

Browse files
committed
cmd/asm,cmd/internal/obj/riscv: add support for riscv compressed instructions
Add support for compressed instructions in the RISC-V assembler. This implements instruction validation and encoding for all instructions in the "C" extension. It is worth noting that the validation and encoding of these instructions is far more convoluted then the typical instruction validation and encoding. While the current model has been followed for now, it would be worth revisiting this in the future and potentially switching to a table based or even per-instruction implementation. Additionally, the current instruction encoding is lacking some of the bits needed for compressed instructions - this is solved by compressedEncoding, which provides the missing information. This will also be addressed in the future, likely by changing the instruction encoding format. Updates #71105 Change-Id: I0f9359d63f93ebbdc6e708e79429b2d61eae220d Reviewed-on: https://go-review.googlesource.com/c/go/+/713020 Reviewed-by: Mark Ryan <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Reviewed-by: Cherry Mui <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Meng Zhuo <[email protected]>
1 parent a15d036 commit 0f9c8fb

File tree

4 files changed

+787
-21
lines changed

4 files changed

+787
-21
lines changed

src/cmd/asm/internal/arch/arch.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ func jumpX86(word string) bool {
9292
func jumpRISCV(word string) bool {
9393
switch word {
9494
case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ",
95-
"BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP":
95+
"BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "CBEQZ", "CBNEZ", "CJ", "CJALR", "CJR",
96+
"JAL", "JALR", "JMP":
9697
return true
9798
}
9899
return false

src/cmd/asm/internal/asm/testdata/riscv64.s

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,76 @@ start:
372372
// 21.7: Double-Precision Floating-Point Classify Instruction
373373
FCLASSD F0, X5 // d31200e2
374374

375+
//
376+
// "C" Extension for Compressed Instructions, Version 2.0
377+
//
378+
379+
// 26.3.1: Compressed Stack-Pointer-Based Loads and Stores
380+
CLWSP 20(SP), X10 // 5245
381+
CLDSP 24(SP), X10 // 6265
382+
CFLDSP 32(SP), F10 // 0235
383+
CSWSP X10, 20(SP) // 2aca
384+
CSDSP X10, 24(SP) // 2aec
385+
CFSDSP F10, 32(SP) // 2ab0
386+
387+
// 26.3.2: Compressed Register-Based Loads and Stores
388+
CLW 20(X10), X11 // 4c49
389+
CLD 24(X10), X11 // 0c6d
390+
CFLD 32(X10), F11 // 0c31
391+
CSW X11, 20(X10) // 4cc9
392+
CSD X11, 24(X10) // 0ced
393+
CFSD F11, 32(X10) // 0cb1
394+
395+
// 26.4: Compressed Control Transfer Instructions
396+
CJ 1(PC) // 09a0
397+
CJR X5 // 8282
398+
CJALR X5 // 8292
399+
CBEQZ X10, 1(PC) // 09c1
400+
CBNEZ X10, 1(PC) // 09e1
401+
402+
// 26.5.1: Compressed Integer Constant-Generation Instructions
403+
CLI $-32, X5 // 8152
404+
CLI $31, X5 // fd42
405+
CLUI $-32, X5 // 8172
406+
CLUI $31, X5 // fd62
407+
408+
// 26.5.2: Compressed Integer Register-Immediate Operations
409+
CADD $-32, X5 // 8112
410+
CADD $31, X5 // fd02
411+
CADDI $-32, X5 // 8112
412+
CADDI $31, X5 // fd02
413+
CADDW $-32, X5 // 8132
414+
CADDW $31, X5 // fd22
415+
CADDIW $-32, X5 // 8132
416+
CADDIW $31, X5 // fd22
417+
CADDI16SP $-512, SP // 0171
418+
CADDI16SP $496, SP // 7d61
419+
CADDI4SPN $4, SP, X10 // 4800
420+
CADDI4SPN $1020, SP, X10 // e81f
421+
CSLLI $63, X5 // fe12
422+
CSRLI $63, X10 // 7d91
423+
CSRAI $63, X10 // 7d95
424+
CAND $-32, X10 // 0199
425+
CAND $31, X10 // 7d89
426+
CANDI $-32, X10 // 0199
427+
CANDI $31, X10 // 7d89
428+
429+
// 26.5.3: Compressed Integer Register-Register Operations
430+
CMV X6, X5 // 9a82
431+
CADD X9, X8 // 2694
432+
CAND X9, X8 // 658c
433+
COR X9, X8 // 458c
434+
CXOR X9, X8 // 258c
435+
CSUB X9, X8 // 058c
436+
CADDW X9, X8 // 259c
437+
CSUBW X9, X8 // 059c
438+
439+
// 26.5.5: Compressed NOP Instruction
440+
CNOP // 0100
441+
442+
// 26.5.6: Compressed Breakpoint Instruction
443+
CEBREAK // 0290
444+
375445
// 28.4.1: Address Generation Instructions (Zba)
376446
ADDUW X10, X11, X12 // 3b86a508
377447
ADDUW X10, X11 // bb85a508

src/cmd/asm/internal/asm/testdata/riscv64validation.s

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,144 @@ TEXT validation(SB),$0
1515
WORD $-1 // ERROR "must be in range [0x0, 0xffffffff]"
1616
WORD $0x100000000 // ERROR "must be in range [0x0, 0xffffffff]"
1717

18+
//
19+
// "C" Extension for Compressed Instructions, Version 2.0
20+
//
21+
CLWSP 20(X5), X10 // ERROR "rs2 must be SP/X2"
22+
CLWSP 20(SP), X0 // ERROR "cannot use register X0"
23+
CLWSP 20(SP), F10 // ERROR "expected integer register in rd position"
24+
CLWSP 22(SP), X10 // ERROR "must be a multiple of 4"
25+
CLDSP 24(X5), X10 // ERROR "rs2 must be SP/X2"
26+
CLDSP 24(SP), X0 // ERROR "cannot use register X0"
27+
CLDSP 24(SP), F10 // ERROR "expected integer register in rd position"
28+
CLDSP 28(SP), X10 // ERROR "must be a multiple of 8"
29+
CFLDSP 32(X5), F10 // ERROR "rs2 must be SP/X2"
30+
CFLDSP 32(SP), X10 // ERROR "expected float register in rd position"
31+
CFLDSP 36(SP), F10 // ERROR "must be a multiple of 8"
32+
CSWSP X10, 20(X5) // ERROR "rd must be SP/X2"
33+
CSWSP F10, 20(SP) // ERROR "expected integer register in rs2 position"
34+
CSWSP X10, 22(SP) // ERROR "must be a multiple of 4"
35+
CSDSP X10, 24(X5) // ERROR "rd must be SP/X2"
36+
CSDSP F10, 24(SP) // ERROR "expected integer register in rs2 position"
37+
CSDSP X10, 28(SP) // ERROR "must be a multiple of 8"
38+
CFSDSP F10, 32(X5) // ERROR "rd must be SP/X2"
39+
CFSDSP X10, 32(SP) // ERROR "expected float register in rs2 position"
40+
CFSDSP F10, 36(SP) // ERROR "must be a multiple of 8"
41+
CLW 20(X10), F11 // ERROR "expected integer prime register in rd position"
42+
CLW 20(X5), X11 // ERROR "expected integer prime register in rs1 position"
43+
CLW 20(X10), X5 // ERROR "expected integer prime register in rd position"
44+
CLW -1(X10), X11 // ERROR "must be in range [0, 127]"
45+
CLW 22(X10), X11 // ERROR "must be a multiple of 4"
46+
CLW 128(X10), X11 // ERROR "must be in range [0, 127]"
47+
CLD 24(X10), F11 // ERROR "expected integer prime register in rd position"
48+
CLD 24(X5), X11 // ERROR "expected integer prime register in rs1 position"
49+
CLD -1(X10), X11 // ERROR "must be in range [0, 255]"
50+
CLD 30(X10), X11 // ERROR "must be a multiple of 8"
51+
CLD 256(X10), X11 // ERROR "must be in range [0, 255]"
52+
CFLD 32(X10), X11 // ERROR "expected float prime register in rd position"
53+
CFLD 32(X5), F11 // ERROR "expected integer prime register in rs1 position"
54+
CFLD -1(X10), F11 // ERROR "must be in range [0, 255]"
55+
CFLD 34(X10), F11 // ERROR "must be a multiple of 8"
56+
CFLD 256(X10), F11 // ERROR "must be in range [0, 255]"
57+
CSW F11, 20(X10) // ERROR "expected integer prime register in rs2 position"
58+
CSW X11, -1(X10) // ERROR "must be in range [0, 127]"
59+
CSW X11, 22(X10) // ERROR "must be a multiple of 4"
60+
CSW X11, 128(X10) // ERROR "must be in range [0, 127]"
61+
CSD F11, 24(X10) // ERROR "expected integer prime register in rs2 position"
62+
CSD X11, -1(X10) // ERROR "must be in range [0, 255]"
63+
CSD X11, 28(X10) // ERROR "must be a multiple of 8"
64+
CSD X11, 256(X10) // ERROR "must be in range [0, 255]"
65+
CFSD X11, 32(X10) // ERROR "expected float prime register in rs2 position"
66+
CFSD F11, -1(X10) // ERROR "must be in range [0, 255]"
67+
CFSD F11, 36(X10) // ERROR "must be a multiple of 8"
68+
CFSD F11, 256(X10) // ERROR "must be in range [0, 255]"
69+
CJR X0 // ERROR "cannot use register X0 in rs1"
70+
CJR X10, X11 // ERROR "expected no register in rs2"
71+
CJALR X0 // ERROR "cannot use register X0 in rs1"
72+
CJALR X10, X11 // ERROR "expected no register in rd"
73+
CBEQZ X5, 1(PC) // ERROR "expected integer prime register in rs1"
74+
CBNEZ X5, 1(PC) // ERROR "expected integer prime register in rs1"
75+
CLI $3, X0 // ERROR "cannot use register X0 in rd"
76+
CLI $-33, X5 // ERROR "must be in range [-32, 31]"
77+
CLI $32, X5 // ERROR "must be in range [-32, 31]"
78+
CLUI $0, X5 // ERROR "immediate cannot be zero"
79+
CLUI $3, X0 // ERROR "cannot use register X0 in rd"
80+
CLUI $3, X2 // ERROR "cannot use register SP/X2 in rd"
81+
CLUI $-33, X5 // ERROR "must be in range [-32, 31]"
82+
CLUI $32, X5 // ERROR "must be in range [-32, 31]"
83+
CADD $31, X5, X6 // ERROR "rd must be the same as rs1"
84+
CADD $-33, X5 // ERROR "must be in range [-32, 31]"
85+
CADD $32, X5 // ERROR "must be in range [-32, 31]"
86+
CADDI $0, X5 // ERROR "immediate cannot be zero"
87+
CADDI $31, X5, X6 // ERROR "rd must be the same as rs1"
88+
CADDI $-33, X5 // ERROR "must be in range [-32, 31]"
89+
CADDI $32, X5 // ERROR "must be in range [-32, 31]"
90+
CADDW $-33, X5 // ERROR "must be in range [-32, 31]"
91+
CADDW $32, X5 // ERROR "must be in range [-32, 31]"
92+
CADDIW $-33, X5 // ERROR "must be in range [-32, 31]"
93+
CADDIW $32, X5 // ERROR "must be in range [-32, 31]"
94+
CADDI16SP $0, SP // ERROR "immediate cannot be zero"
95+
CADDI16SP $16, X5 // ERROR "rd must be SP/X2"
96+
CADDI16SP $-513, SP // ERROR "must be in range [-512, 511]"
97+
CADDI16SP $20, SP // ERROR "must be a multiple of 16"
98+
CADDI16SP $512, SP // ERROR "must be in range [-512, 511]"
99+
CADDI4SPN $4, SP, X5 // ERROR "expected integer prime register in rd"
100+
CADDI4SPN $4, X5, X10 // ERROR "SP/X2 must be in rs1"
101+
CADDI4SPN $-1, SP, X10 // ERROR "must be in range [0, 1023]"
102+
CADDI4SPN $0, SP, X10 // ERROR "immediate cannot be zero"
103+
CADDI4SPN $6, SP, X10 // ERROR "must be a multiple of 4"
104+
CADDI4SPN $1024, SP, X10 // ERROR "must be in range [0, 1023]"
105+
CSLLI $63, X5, X6 // ERROR "rd must be the same as rs1"
106+
CSLLI $-1, X5 // ERROR "must be in range [0, 63]"
107+
CSLLI $0, X5 // ERROR "immediate cannot be zero"
108+
CSLLI $64, X5 // ERROR "must be in range [0, 63]"
109+
CSRLI $63, X10, X11 // ERROR "rd must be the same as rs1"
110+
CSRLI $63, X5 // ERROR "expected integer prime register in rd"
111+
CSRLI $-1, X10 // ERROR "must be in range [0, 63]"
112+
CSRLI $0, X10 // ERROR "immediate cannot be zero"
113+
CSRLI $64, X10 // ERROR "must be in range [0, 63]"
114+
CSRAI $63, X10, X11 // ERROR "rd must be the same as rs1"
115+
CSRAI $63, X5 // ERROR "expected integer prime register in rd"
116+
CSRAI $-1, X10 // ERROR "must be in range [0, 63]"
117+
CSRAI $0, X10 // ERROR "immediate cannot be zero"
118+
CSRAI $64, X10 // ERROR "must be in range [0, 63]"
119+
CAND $1, X10, X11 // ERROR "rd must be the same as rs1"
120+
CAND $1, X5 // ERROR "expected integer prime register in rd"
121+
CAND $-64, X10 // ERROR "must be in range [-32, 31]"
122+
CAND $63, X10 // ERROR "must be in range [-32, 31]"
123+
CANDI $1, X10, X11 // ERROR "rd must be the same as rs1"
124+
CANDI $1, X5 // ERROR "expected integer prime register in rd"
125+
CANDI $-64, X10 // ERROR "must be in range [-32, 31]"
126+
CANDI $63, X10 // ERROR "must be in range [-32, 31]"
127+
CMV X0, X5 // ERROR "cannot use register X0 in rs2"
128+
CMV X5, X6, X7 // ERROR "expected no register in rs1"
129+
CMV X5, X0 // ERROR "cannot use register X0 in rd"
130+
CMV F1, X5 // ERROR "expected integer register in rs2"
131+
CMV X5, F1 // ERROR "expected integer register in rd"
132+
CADD X5, X6, X7 // ERROR "rd must be the same as rs1"
133+
CADD X0, X8 // ERROR "cannot use register X0 in rs2"
134+
CADD X8, X0 // ERROR "cannot use register X0 in rd"
135+
CAND X10, X11, X12 // ERROR "rd must be the same as rs1"
136+
CAND X5, X11 // ERROR "expected integer prime register in rs2"
137+
CAND X10, X5 // ERROR "expected integer prime register in rd"
138+
COR X10, X11, X12 // ERROR "rd must be the same as rs1"
139+
COR X5, X11 // ERROR "expected integer prime register in rs2"
140+
COR X10, X5 // ERROR "expected integer prime register in rd"
141+
CXOR X10, X11, X12 // ERROR "rd must be the same as rs1"
142+
CXOR X5, X11 // ERROR "expected integer prime register in rs2"
143+
CXOR X10, X5 // ERROR "expected integer prime register in rd"
144+
CSUB X10, X11, X12 // ERROR "rd must be the same as rs1"
145+
CSUB X5, X11 // ERROR "expected integer prime register in rs2"
146+
CSUB X10, X5 // ERROR "expected integer prime register in rd"
147+
CADDW X10, X11, X12 // ERROR "rd must be the same as rs1"
148+
CADDW X5, X11 // ERROR "expected integer prime register in rs2"
149+
CADDW X10, X5 // ERROR "expected integer prime register in rd"
150+
CSUBW X10, X11, X12 // ERROR "rd must be the same as rs1"
151+
CSUBW X5, X11 // ERROR "expected integer prime register in rs2"
152+
CSUBW X10, X5 // ERROR "expected integer prime register in rd"
153+
CNOP X10 // ERROR "expected no register in rs2"
154+
CEBREAK X10 // ERROR "expected no register in rs2"
155+
18156
//
19157
// "V" Standard Extension for Vector Operations, Version 1.0
20158
//

0 commit comments

Comments
 (0)