riscv64: implement RV64GC_zba_zbb_zbs GNU/Plan9 format disassembler

Support decoding RV64GC_zba_zbb_zbs instructions as GNU & Plan9 format,
relies on riscv64spec/spec.go to generate instruction tables

Change-Id: I3b2793a7dd9faa3ac18d85361a8627eba0923068
Reviewed-on: https://go-review.googlesource.com/c/arch/+/602915
Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
This commit is contained in:
Lin Runze 2024-08-04 19:19:12 +08:00 коммит произвёл Joel Sing
Родитель 292026d483
Коммит 7874f23b9c
8 изменённых файлов: 3925 добавлений и 8 удалений

116
riscv64/riscv64asm/arg.go Normal file
Просмотреть файл

@ -0,0 +1,116 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv64asm
// Naming for Go decoder arguments:
//
// - arg_rd: a general purpose register rd encoded in rd[11:7] field
//
// - arg_rs1: a general purpose register rs1 encoded in rs1[19:15] field
//
// - arg_rs2: a general purpose register rs2 encoded in rs2[24:20] field
//
// - arg_rs3: a general purpose register rs3 encoded in rs3[31:27] field
//
// - arg_fd: a floating point register rd encoded in rd[11:7] field
//
// - arg_fs1: a floating point register rs1 encoded in rs1[19:15] field
//
// - arg_fs2: a floating point register rs2 encoded in rs2[24:20] field
//
// - arg_fs3: a floating point register rs3 encoded in rs3[31:27] field
//
// - arg_csr: a control status register encoded in csr[31:20] field
//
// - arg_rs1_mem: source register with offset in load commands
//
// - arg_rs1_store: source register with offset in store commands
//
// - arg_rs1_amo: source register with offset in atomic commands
//
// - arg_pred: predecessor memory ordering information encoded in pred[27:24] field
// For details, please refer to chapter 2.7 of ISA manual volume 1
//
// - arg_succ: successor memory ordering information encoded in succ[23:20] field
// For details, please refer to chapter 2.7 of ISA manual volume 1
//
// - arg_zimm: a unsigned immediate encoded in zimm[19:15] field
//
// - arg_imm12: an I-type immediate encoded in imm12[31:20] field
//
// - arg_simm12: a S-type immediate encoded in simm12[31:25|11:7] field
//
// - arg_bimm12: a B-type immediate encoded in bimm12[31:25|11:7] field
//
// - arg_imm20: an U-type immediate encoded in imm20[31:12] field
//
// - arg_jimm20: a J-type immediate encoded in jimm20[31:12] field
//
// - arg_shamt5: a shift amount encoded in shamt5[24:20] field
//
// - arg_shamt6: a shift amount encoded in shamt6[25:20] field
//
type argType uint16
const (
_ argType = iota
arg_rd
arg_rs1
arg_rs2
arg_rs3
arg_fd
arg_fs1
arg_fs2
arg_fs3
arg_csr
arg_rs1_amo
arg_rs1_mem
arg_rs1_store
arg_pred
arg_succ
arg_zimm
arg_imm12
arg_simm12
arg_bimm12
arg_imm20
arg_jimm20
arg_shamt5
arg_shamt6
// RISC-V Compressed Extension Args
arg_rd_p
arg_fd_p
arg_rs1_p
arg_rd_rs1_p
arg_fs2_p
arg_rs2_p
arg_rd_n0
arg_rs1_n0
arg_rd_rs1_n0
arg_c_rs1_n0
arg_c_rs2_n0
arg_c_fs2
arg_c_rs2
arg_rd_n2
arg_c_imm6
arg_c_nzimm6
arg_c_nzuimm6
arg_c_uimm7
arg_c_uimm8
arg_c_uimm8sp_s
arg_c_uimm8sp
arg_c_uimm9sp_s
arg_c_uimm9sp
arg_c_bimm9
arg_c_nzimm10
arg_c_nzuimm10
arg_c_imm12
arg_c_nzimm18
)

Просмотреть файл

@ -0,0 +1,577 @@
// Code generated by "stringer -type=CSR"; DO NOT EDIT.
package riscv64asm
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[USTATUS-0]
_ = x[FFLAGS-1]
_ = x[FRM-2]
_ = x[FCSR-3]
_ = x[UIE-4]
_ = x[UTVEC-5]
_ = x[UTVT-7]
_ = x[VSTART-8]
_ = x[VXSAT-9]
_ = x[VXRM-10]
_ = x[VCSR-15]
_ = x[USCRATCH-64]
_ = x[UEPC-65]
_ = x[UCAUSE-66]
_ = x[UTVAL-67]
_ = x[UIP-68]
_ = x[UNXTI-69]
_ = x[UINTSTATUS-70]
_ = x[USCRATCHCSW-72]
_ = x[USCRATCHCSWL-73]
_ = x[SSTATUS-256]
_ = x[SEDELEG-258]
_ = x[SIDELEG-259]
_ = x[SIE-260]
_ = x[STVEC-261]
_ = x[SCOUNTEREN-262]
_ = x[STVT-263]
_ = x[SSCRATCH-320]
_ = x[SEPC-321]
_ = x[SCAUSE-322]
_ = x[STVAL-323]
_ = x[SIP-324]
_ = x[SNXTI-325]
_ = x[SINTSTATUS-326]
_ = x[SSCRATCHCSW-328]
_ = x[SSCRATCHCSWL-329]
_ = x[SATP-384]
_ = x[VSSTATUS-512]
_ = x[VSIE-516]
_ = x[VSTVEC-517]
_ = x[VSSCRATCH-576]
_ = x[VSEPC-577]
_ = x[VSCAUSE-578]
_ = x[VSTVAL-579]
_ = x[VSIP-580]
_ = x[VSATP-640]
_ = x[MSTATUS-768]
_ = x[MISA-769]
_ = x[MEDELEG-770]
_ = x[MIDELEG-771]
_ = x[MIE-772]
_ = x[MTVEC-773]
_ = x[MCOUNTEREN-774]
_ = x[MTVT-775]
_ = x[MSTATUSH-784]
_ = x[MCOUNTINHIBIT-800]
_ = x[MHPMEVENT3-803]
_ = x[MHPMEVENT4-804]
_ = x[MHPMEVENT5-805]
_ = x[MHPMEVENT6-806]
_ = x[MHPMEVENT7-807]
_ = x[MHPMEVENT8-808]
_ = x[MHPMEVENT9-809]
_ = x[MHPMEVENT10-810]
_ = x[MHPMEVENT11-811]
_ = x[MHPMEVENT12-812]
_ = x[MHPMEVENT13-813]
_ = x[MHPMEVENT14-814]
_ = x[MHPMEVENT15-815]
_ = x[MHPMEVENT16-816]
_ = x[MHPMEVENT17-817]
_ = x[MHPMEVENT18-818]
_ = x[MHPMEVENT19-819]
_ = x[MHPMEVENT20-820]
_ = x[MHPMEVENT21-821]
_ = x[MHPMEVENT22-822]
_ = x[MHPMEVENT23-823]
_ = x[MHPMEVENT24-824]
_ = x[MHPMEVENT25-825]
_ = x[MHPMEVENT26-826]
_ = x[MHPMEVENT27-827]
_ = x[MHPMEVENT28-828]
_ = x[MHPMEVENT29-829]
_ = x[MHPMEVENT30-830]
_ = x[MHPMEVENT31-831]
_ = x[MSCRATCH-832]
_ = x[MEPC-833]
_ = x[MCAUSE-834]
_ = x[MTVAL-835]
_ = x[MIP-836]
_ = x[MNXTI-837]
_ = x[MINTSTATUS-838]
_ = x[MSCRATCHCSW-840]
_ = x[MSCRATCHCSWL-841]
_ = x[MTINST-842]
_ = x[MTVAL2-843]
_ = x[PMPCFG0-928]
_ = x[PMPCFG1-929]
_ = x[PMPCFG2-930]
_ = x[PMPCFG3-931]
_ = x[PMPADDR0-944]
_ = x[PMPADDR1-945]
_ = x[PMPADDR2-946]
_ = x[PMPADDR3-947]
_ = x[PMPADDR4-948]
_ = x[PMPADDR5-949]
_ = x[PMPADDR6-950]
_ = x[PMPADDR7-951]
_ = x[PMPADDR8-952]
_ = x[PMPADDR9-953]
_ = x[PMPADDR10-954]
_ = x[PMPADDR11-955]
_ = x[PMPADDR12-956]
_ = x[PMPADDR13-957]
_ = x[PMPADDR14-958]
_ = x[PMPADDR15-959]
_ = x[HSTATUS-1536]
_ = x[HEDELEG-1538]
_ = x[HIDELEG-1539]
_ = x[HIE-1540]
_ = x[HTIMEDELTA-1541]
_ = x[HCOUNTEREN-1542]
_ = x[HGEIE-1543]
_ = x[HTIMEDELTAH-1557]
_ = x[HTVAL-1603]
_ = x[HIP-1604]
_ = x[HVIP-1605]
_ = x[HTINST-1610]
_ = x[HGATP-1664]
_ = x[TSELECT-1952]
_ = x[TDATA1-1953]
_ = x[TDATA2-1954]
_ = x[TDATA3-1955]
_ = x[TINFO-1956]
_ = x[TCONTROL-1957]
_ = x[MCONTEXT-1960]
_ = x[MNOISE-1961]
_ = x[SCONTEXT-1962]
_ = x[DCSR-1968]
_ = x[DPC-1969]
_ = x[DSCRATCH0-1970]
_ = x[DSCRATCH1-1971]
_ = x[MCYCLE-2816]
_ = x[MINSTRET-2818]
_ = x[MHPMCOUNTER3-2819]
_ = x[MHPMCOUNTER4-2820]
_ = x[MHPMCOUNTER5-2821]
_ = x[MHPMCOUNTER6-2822]
_ = x[MHPMCOUNTER7-2823]
_ = x[MHPMCOUNTER8-2824]
_ = x[MHPMCOUNTER9-2825]
_ = x[MHPMCOUNTER10-2826]
_ = x[MHPMCOUNTER11-2827]
_ = x[MHPMCOUNTER12-2828]
_ = x[MHPMCOUNTER13-2829]
_ = x[MHPMCOUNTER14-2830]
_ = x[MHPMCOUNTER15-2831]
_ = x[MHPMCOUNTER16-2832]
_ = x[MHPMCOUNTER17-2833]
_ = x[MHPMCOUNTER18-2834]
_ = x[MHPMCOUNTER19-2835]
_ = x[MHPMCOUNTER20-2836]
_ = x[MHPMCOUNTER21-2837]
_ = x[MHPMCOUNTER22-2838]
_ = x[MHPMCOUNTER23-2839]
_ = x[MHPMCOUNTER24-2840]
_ = x[MHPMCOUNTER25-2841]
_ = x[MHPMCOUNTER26-2842]
_ = x[MHPMCOUNTER27-2843]
_ = x[MHPMCOUNTER28-2844]
_ = x[MHPMCOUNTER29-2845]
_ = x[MHPMCOUNTER30-2846]
_ = x[MHPMCOUNTER31-2847]
_ = x[MCYCLEH-2944]
_ = x[MINSTRETH-2946]
_ = x[MHPMCOUNTER3H-2947]
_ = x[MHPMCOUNTER4H-2948]
_ = x[MHPMCOUNTER5H-2949]
_ = x[MHPMCOUNTER6H-2950]
_ = x[MHPMCOUNTER7H-2951]
_ = x[MHPMCOUNTER8H-2952]
_ = x[MHPMCOUNTER9H-2953]
_ = x[MHPMCOUNTER10H-2954]
_ = x[MHPMCOUNTER11H-2955]
_ = x[MHPMCOUNTER12H-2956]
_ = x[MHPMCOUNTER13H-2957]
_ = x[MHPMCOUNTER14H-2958]
_ = x[MHPMCOUNTER15H-2959]
_ = x[MHPMCOUNTER16H-2960]
_ = x[MHPMCOUNTER17H-2961]
_ = x[MHPMCOUNTER18H-2962]
_ = x[MHPMCOUNTER19H-2963]
_ = x[MHPMCOUNTER20H-2964]
_ = x[MHPMCOUNTER21H-2965]
_ = x[MHPMCOUNTER22H-2966]
_ = x[MHPMCOUNTER23H-2967]
_ = x[MHPMCOUNTER24H-2968]
_ = x[MHPMCOUNTER25H-2969]
_ = x[MHPMCOUNTER26H-2970]
_ = x[MHPMCOUNTER27H-2971]
_ = x[MHPMCOUNTER28H-2972]
_ = x[MHPMCOUNTER29H-2973]
_ = x[MHPMCOUNTER30H-2974]
_ = x[MHPMCOUNTER31H-2975]
_ = x[CYCLE-3072]
_ = x[TIME-3073]
_ = x[INSTRET-3074]
_ = x[HPMCOUNTER3-3075]
_ = x[HPMCOUNTER4-3076]
_ = x[HPMCOUNTER5-3077]
_ = x[HPMCOUNTER6-3078]
_ = x[HPMCOUNTER7-3079]
_ = x[HPMCOUNTER8-3080]
_ = x[HPMCOUNTER9-3081]
_ = x[HPMCOUNTER10-3082]
_ = x[HPMCOUNTER11-3083]
_ = x[HPMCOUNTER12-3084]
_ = x[HPMCOUNTER13-3085]
_ = x[HPMCOUNTER14-3086]
_ = x[HPMCOUNTER15-3087]
_ = x[HPMCOUNTER16-3088]
_ = x[HPMCOUNTER17-3089]
_ = x[HPMCOUNTER18-3090]
_ = x[HPMCOUNTER19-3091]
_ = x[HPMCOUNTER20-3092]
_ = x[HPMCOUNTER21-3093]
_ = x[HPMCOUNTER22-3094]
_ = x[HPMCOUNTER23-3095]
_ = x[HPMCOUNTER24-3096]
_ = x[HPMCOUNTER25-3097]
_ = x[HPMCOUNTER26-3098]
_ = x[HPMCOUNTER27-3099]
_ = x[HPMCOUNTER28-3100]
_ = x[HPMCOUNTER29-3101]
_ = x[HPMCOUNTER30-3102]
_ = x[HPMCOUNTER31-3103]
_ = x[VL-3104]
_ = x[VTYPE-3105]
_ = x[VLENB-3106]
_ = x[CYCLEH-3200]
_ = x[TIMEH-3201]
_ = x[INSTRETH-3202]
_ = x[HPMCOUNTER3H-3203]
_ = x[HPMCOUNTER4H-3204]
_ = x[HPMCOUNTER5H-3205]
_ = x[HPMCOUNTER6H-3206]
_ = x[HPMCOUNTER7H-3207]
_ = x[HPMCOUNTER8H-3208]
_ = x[HPMCOUNTER9H-3209]
_ = x[HPMCOUNTER10H-3210]
_ = x[HPMCOUNTER11H-3211]
_ = x[HPMCOUNTER12H-3212]
_ = x[HPMCOUNTER13H-3213]
_ = x[HPMCOUNTER14H-3214]
_ = x[HPMCOUNTER15H-3215]
_ = x[HPMCOUNTER16H-3216]
_ = x[HPMCOUNTER17H-3217]
_ = x[HPMCOUNTER18H-3218]
_ = x[HPMCOUNTER19H-3219]
_ = x[HPMCOUNTER20H-3220]
_ = x[HPMCOUNTER21H-3221]
_ = x[HPMCOUNTER22H-3222]
_ = x[HPMCOUNTER23H-3223]
_ = x[HPMCOUNTER24H-3224]
_ = x[HPMCOUNTER25H-3225]
_ = x[HPMCOUNTER26H-3226]
_ = x[HPMCOUNTER27H-3227]
_ = x[HPMCOUNTER28H-3228]
_ = x[HPMCOUNTER29H-3229]
_ = x[HPMCOUNTER30H-3230]
_ = x[HPMCOUNTER31H-3231]
_ = x[HGEIP-3602]
_ = x[MVENDORID-3857]
_ = x[MARCHID-3858]
_ = x[MIMPID-3859]
_ = x[MHARTID-3860]
_ = x[MENTROPY-3861]
}
const _CSR_name = "USTATUSFFLAGSFRMFCSRUIEUTVECUTVTVSTARTVXSATVXRMVCSRUSCRATCHUEPCUCAUSEUTVALUIPUNXTIUINTSTATUSUSCRATCHCSWUSCRATCHCSWLSSTATUSSEDELEGSIDELEGSIESTVECSCOUNTERENSTVTSSCRATCHSEPCSCAUSESTVALSIPSNXTISINTSTATUSSSCRATCHCSWSSCRATCHCSWLSATPVSSTATUSVSIEVSTVECVSSCRATCHVSEPCVSCAUSEVSTVALVSIPVSATPMSTATUSMISAMEDELEGMIDELEGMIEMTVECMCOUNTERENMTVTMSTATUSHMCOUNTINHIBITMHPMEVENT3MHPMEVENT4MHPMEVENT5MHPMEVENT6MHPMEVENT7MHPMEVENT8MHPMEVENT9MHPMEVENT10MHPMEVENT11MHPMEVENT12MHPMEVENT13MHPMEVENT14MHPMEVENT15MHPMEVENT16MHPMEVENT17MHPMEVENT18MHPMEVENT19MHPMEVENT20MHPMEVENT21MHPMEVENT22MHPMEVENT23MHPMEVENT24MHPMEVENT25MHPMEVENT26MHPMEVENT27MHPMEVENT28MHPMEVENT29MHPMEVENT30MHPMEVENT31MSCRATCHMEPCMCAUSEMTVALMIPMNXTIMINTSTATUSMSCRATCHCSWMSCRATCHCSWLMTINSTMTVAL2PMPCFG0PMPCFG1PMPCFG2PMPCFG3PMPADDR0PMPADDR1PMPADDR2PMPADDR3PMPADDR4PMPADDR5PMPADDR6PMPADDR7PMPADDR8PMPADDR9PMPADDR10PMPADDR11PMPADDR12PMPADDR13PMPADDR14PMPADDR15HSTATUSHEDELEGHIDELEGHIEHTIMEDELTAHCOUNTERENHGEIEHTIMEDELTAHHTVALHIPHVIPHTINSTHGATPTSELECTTDATA1TDATA2TDATA3TINFOTCONTROLMCONTEXTMNOISESCONTEXTDCSRDPCDSCRATCH0DSCRATCH1MCYCLEMINSTRETMHPMCOUNTER3MHPMCOUNTER4MHPMCOUNTER5MHPMCOUNTER6MHPMCOUNTER7MHPMCOUNTER8MHPMCOUNTER9MHPMCOUNTER10MHPMCOUNTER11MHPMCOUNTER12MHPMCOUNTER13MHPMCOUNTER14MHPMCOUNTER15MHPMCOUNTER16MHPMCOUNTER17MHPMCOUNTER18MHPMCOUNTER19MHPMCOUNTER20MHPMCOUNTER21MHPMCOUNTER22MHPMCOUNTER23MHPMCOUNTER24MHPMCOUNTER25MHPMCOUNTER26MHPMCOUNTER27MHPMCOUNTER28MHPMCOUNTER29MHPMCOUNTER30MHPMCOUNTER31MCYCLEHMINSTRETHMHPMCOUNTER3HMHPMCOUNTER4HMHPMCOUNTER5HMHPMCOUNTER6HMHPMCOUNTER7HMHPMCOUNTER8HMHPMCOUNTER9HMHPMCOUNTER10HMHPMCOUNTER11HMHPMCOUNTER12HMHPMCOUNTER13HMHPMCOUNTER14HMHPMCOUNTER15HMHPMCOUNTER16HMHPMCOUNTER17HMHPMCOUNTER18HMHPMCOUNTER19HMHPMCOUNTER20HMHPMCOUNTER21HMHPMCOUNTER22HMHPMCOUNTER23HMHPMCOUNTER24HMHPMCOUNTER25HMHPMCOUNTER26HMHPMCOUNTER27HMHPMCOUNTER28HMHPMCOUNTER29HMHPMCOUNTER30HMHPMCOUNTER31HCYCLETIMEINSTRETHPMCOUNTER3HPMCOUNTER4HPMCOUNTER5HPMCOUNTER6HPMCOUNTER7HPMCOUNTER8HPMCOUNTER9HPMCOUNTER10HPMCOUNTER11HPMCOUNTER12HPMCOUNTER13HPMCOUNTER14HPMCOUNTER15HPMCOUNTER16HPMCOUNTER17HPMCOUNTER18HPMCOUNTER19HPMCOUNTER20HPMCOUNTER21HPMCOUNTER22HPMCOUNTER23HPMCOUNTER24HPMCOUNTER25HPMCOUNTER26HPMCOUNTER27HPMCOUNTER28HPMCOUNTER29HPMCOUNTER30HPMCOUNTER31VLVTYPEVLENBCYCLEHTIMEHINSTRETHHPMCOUNTER3HHPMCOUNTER4HHPMCOUNTER5HHPMCOUNTER6HHPMCOUNTER7HHPMCOUNTER8HHPMCOUNTER9HHPMCOUNTER10HHPMCOUNTER11HHPMCOUNTER12HHPMCOUNTER13HHPMCOUNTER14HHPMCOUNTER15HHPMCOUNTER16HHPMCOUNTER17HHPMCOUNTER18HHPMCOUNTER19HHPMCOUNTER20HHPMCOUNTER21HHPMCOUNTER22HHPMCOUNTER23HHPMCOUNTER24HHPMCOUNTER25HHPMCOUNTER26HHPMCOUNTER27HHPMCOUNTER28HHPMCOUNTER29HHPMCOUNTER30HHPMCOUNTER31HHGEIPMVENDORIDMARCHIDMIMPIDMHARTIDMENTROPY"
var _CSR_map = map[CSR]string{
0: _CSR_name[0:7],
1: _CSR_name[7:13],
2: _CSR_name[13:16],
3: _CSR_name[16:20],
4: _CSR_name[20:23],
5: _CSR_name[23:28],
7: _CSR_name[28:32],
8: _CSR_name[32:38],
9: _CSR_name[38:43],
10: _CSR_name[43:47],
15: _CSR_name[47:51],
64: _CSR_name[51:59],
65: _CSR_name[59:63],
66: _CSR_name[63:69],
67: _CSR_name[69:74],
68: _CSR_name[74:77],
69: _CSR_name[77:82],
70: _CSR_name[82:92],
72: _CSR_name[92:103],
73: _CSR_name[103:115],
256: _CSR_name[115:122],
258: _CSR_name[122:129],
259: _CSR_name[129:136],
260: _CSR_name[136:139],
261: _CSR_name[139:144],
262: _CSR_name[144:154],
263: _CSR_name[154:158],
320: _CSR_name[158:166],
321: _CSR_name[166:170],
322: _CSR_name[170:176],
323: _CSR_name[176:181],
324: _CSR_name[181:184],
325: _CSR_name[184:189],
326: _CSR_name[189:199],
328: _CSR_name[199:210],
329: _CSR_name[210:222],
384: _CSR_name[222:226],
512: _CSR_name[226:234],
516: _CSR_name[234:238],
517: _CSR_name[238:244],
576: _CSR_name[244:253],
577: _CSR_name[253:258],
578: _CSR_name[258:265],
579: _CSR_name[265:271],
580: _CSR_name[271:275],
640: _CSR_name[275:280],
768: _CSR_name[280:287],
769: _CSR_name[287:291],
770: _CSR_name[291:298],
771: _CSR_name[298:305],
772: _CSR_name[305:308],
773: _CSR_name[308:313],
774: _CSR_name[313:323],
775: _CSR_name[323:327],
784: _CSR_name[327:335],
800: _CSR_name[335:348],
803: _CSR_name[348:358],
804: _CSR_name[358:368],
805: _CSR_name[368:378],
806: _CSR_name[378:388],
807: _CSR_name[388:398],
808: _CSR_name[398:408],
809: _CSR_name[408:418],
810: _CSR_name[418:429],
811: _CSR_name[429:440],
812: _CSR_name[440:451],
813: _CSR_name[451:462],
814: _CSR_name[462:473],
815: _CSR_name[473:484],
816: _CSR_name[484:495],
817: _CSR_name[495:506],
818: _CSR_name[506:517],
819: _CSR_name[517:528],
820: _CSR_name[528:539],
821: _CSR_name[539:550],
822: _CSR_name[550:561],
823: _CSR_name[561:572],
824: _CSR_name[572:583],
825: _CSR_name[583:594],
826: _CSR_name[594:605],
827: _CSR_name[605:616],
828: _CSR_name[616:627],
829: _CSR_name[627:638],
830: _CSR_name[638:649],
831: _CSR_name[649:660],
832: _CSR_name[660:668],
833: _CSR_name[668:672],
834: _CSR_name[672:678],
835: _CSR_name[678:683],
836: _CSR_name[683:686],
837: _CSR_name[686:691],
838: _CSR_name[691:701],
840: _CSR_name[701:712],
841: _CSR_name[712:724],
842: _CSR_name[724:730],
843: _CSR_name[730:736],
928: _CSR_name[736:743],
929: _CSR_name[743:750],
930: _CSR_name[750:757],
931: _CSR_name[757:764],
944: _CSR_name[764:772],
945: _CSR_name[772:780],
946: _CSR_name[780:788],
947: _CSR_name[788:796],
948: _CSR_name[796:804],
949: _CSR_name[804:812],
950: _CSR_name[812:820],
951: _CSR_name[820:828],
952: _CSR_name[828:836],
953: _CSR_name[836:844],
954: _CSR_name[844:853],
955: _CSR_name[853:862],
956: _CSR_name[862:871],
957: _CSR_name[871:880],
958: _CSR_name[880:889],
959: _CSR_name[889:898],
1536: _CSR_name[898:905],
1538: _CSR_name[905:912],
1539: _CSR_name[912:919],
1540: _CSR_name[919:922],
1541: _CSR_name[922:932],
1542: _CSR_name[932:942],
1543: _CSR_name[942:947],
1557: _CSR_name[947:958],
1603: _CSR_name[958:963],
1604: _CSR_name[963:966],
1605: _CSR_name[966:970],
1610: _CSR_name[970:976],
1664: _CSR_name[976:981],
1952: _CSR_name[981:988],
1953: _CSR_name[988:994],
1954: _CSR_name[994:1000],
1955: _CSR_name[1000:1006],
1956: _CSR_name[1006:1011],
1957: _CSR_name[1011:1019],
1960: _CSR_name[1019:1027],
1961: _CSR_name[1027:1033],
1962: _CSR_name[1033:1041],
1968: _CSR_name[1041:1045],
1969: _CSR_name[1045:1048],
1970: _CSR_name[1048:1057],
1971: _CSR_name[1057:1066],
2816: _CSR_name[1066:1072],
2818: _CSR_name[1072:1080],
2819: _CSR_name[1080:1092],
2820: _CSR_name[1092:1104],
2821: _CSR_name[1104:1116],
2822: _CSR_name[1116:1128],
2823: _CSR_name[1128:1140],
2824: _CSR_name[1140:1152],
2825: _CSR_name[1152:1164],
2826: _CSR_name[1164:1177],
2827: _CSR_name[1177:1190],
2828: _CSR_name[1190:1203],
2829: _CSR_name[1203:1216],
2830: _CSR_name[1216:1229],
2831: _CSR_name[1229:1242],
2832: _CSR_name[1242:1255],
2833: _CSR_name[1255:1268],
2834: _CSR_name[1268:1281],
2835: _CSR_name[1281:1294],
2836: _CSR_name[1294:1307],
2837: _CSR_name[1307:1320],
2838: _CSR_name[1320:1333],
2839: _CSR_name[1333:1346],
2840: _CSR_name[1346:1359],
2841: _CSR_name[1359:1372],
2842: _CSR_name[1372:1385],
2843: _CSR_name[1385:1398],
2844: _CSR_name[1398:1411],
2845: _CSR_name[1411:1424],
2846: _CSR_name[1424:1437],
2847: _CSR_name[1437:1450],
2944: _CSR_name[1450:1457],
2946: _CSR_name[1457:1466],
2947: _CSR_name[1466:1479],
2948: _CSR_name[1479:1492],
2949: _CSR_name[1492:1505],
2950: _CSR_name[1505:1518],
2951: _CSR_name[1518:1531],
2952: _CSR_name[1531:1544],
2953: _CSR_name[1544:1557],
2954: _CSR_name[1557:1571],
2955: _CSR_name[1571:1585],
2956: _CSR_name[1585:1599],
2957: _CSR_name[1599:1613],
2958: _CSR_name[1613:1627],
2959: _CSR_name[1627:1641],
2960: _CSR_name[1641:1655],
2961: _CSR_name[1655:1669],
2962: _CSR_name[1669:1683],
2963: _CSR_name[1683:1697],
2964: _CSR_name[1697:1711],
2965: _CSR_name[1711:1725],
2966: _CSR_name[1725:1739],
2967: _CSR_name[1739:1753],
2968: _CSR_name[1753:1767],
2969: _CSR_name[1767:1781],
2970: _CSR_name[1781:1795],
2971: _CSR_name[1795:1809],
2972: _CSR_name[1809:1823],
2973: _CSR_name[1823:1837],
2974: _CSR_name[1837:1851],
2975: _CSR_name[1851:1865],
3072: _CSR_name[1865:1870],
3073: _CSR_name[1870:1874],
3074: _CSR_name[1874:1881],
3075: _CSR_name[1881:1892],
3076: _CSR_name[1892:1903],
3077: _CSR_name[1903:1914],
3078: _CSR_name[1914:1925],
3079: _CSR_name[1925:1936],
3080: _CSR_name[1936:1947],
3081: _CSR_name[1947:1958],
3082: _CSR_name[1958:1970],
3083: _CSR_name[1970:1982],
3084: _CSR_name[1982:1994],
3085: _CSR_name[1994:2006],
3086: _CSR_name[2006:2018],
3087: _CSR_name[2018:2030],
3088: _CSR_name[2030:2042],
3089: _CSR_name[2042:2054],
3090: _CSR_name[2054:2066],
3091: _CSR_name[2066:2078],
3092: _CSR_name[2078:2090],
3093: _CSR_name[2090:2102],
3094: _CSR_name[2102:2114],
3095: _CSR_name[2114:2126],
3096: _CSR_name[2126:2138],
3097: _CSR_name[2138:2150],
3098: _CSR_name[2150:2162],
3099: _CSR_name[2162:2174],
3100: _CSR_name[2174:2186],
3101: _CSR_name[2186:2198],
3102: _CSR_name[2198:2210],
3103: _CSR_name[2210:2222],
3104: _CSR_name[2222:2224],
3105: _CSR_name[2224:2229],
3106: _CSR_name[2229:2234],
3200: _CSR_name[2234:2240],
3201: _CSR_name[2240:2245],
3202: _CSR_name[2245:2253],
3203: _CSR_name[2253:2265],
3204: _CSR_name[2265:2277],
3205: _CSR_name[2277:2289],
3206: _CSR_name[2289:2301],
3207: _CSR_name[2301:2313],
3208: _CSR_name[2313:2325],
3209: _CSR_name[2325:2337],
3210: _CSR_name[2337:2350],
3211: _CSR_name[2350:2363],
3212: _CSR_name[2363:2376],
3213: _CSR_name[2376:2389],
3214: _CSR_name[2389:2402],
3215: _CSR_name[2402:2415],
3216: _CSR_name[2415:2428],
3217: _CSR_name[2428:2441],
3218: _CSR_name[2441:2454],
3219: _CSR_name[2454:2467],
3220: _CSR_name[2467:2480],
3221: _CSR_name[2480:2493],
3222: _CSR_name[2493:2506],
3223: _CSR_name[2506:2519],
3224: _CSR_name[2519:2532],
3225: _CSR_name[2532:2545],
3226: _CSR_name[2545:2558],
3227: _CSR_name[2558:2571],
3228: _CSR_name[2571:2584],
3229: _CSR_name[2584:2597],
3230: _CSR_name[2597:2610],
3231: _CSR_name[2610:2623],
3602: _CSR_name[2623:2628],
3857: _CSR_name[2628:2637],
3858: _CSR_name[2637:2644],
3859: _CSR_name[2644:2650],
3860: _CSR_name[2650:2657],
3861: _CSR_name[2657:2665],
}
func (i CSR) String() string {
if str, ok := _CSR_map[i]; ok {
return str
}
return "CSR(" + strconv.FormatInt(int64(i), 10) + ")"
}

Просмотреть файл

@ -0,0 +1,550 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv64asm
import (
"encoding/binary"
"errors"
)
type argTypeList [6]argType
// An instFormat describes the format of an instruction encoding.
type instFormat struct {
mask uint32
value uint32
op Op
// args describe how to decode the instruction arguments.
// args is stored as a fixed-size array.
// if there are fewer than len(args) arguments, args[i] == 0 marks
// the end of the argument list.
args argTypeList
}
var (
errShort = errors.New("truncated instruction")
errUnknown = errors.New("unknown instruction")
)
var decoderCover []bool
func init() {
decoderCover = make([]bool, len(instFormats))
}
// Decode decodes the 4 bytes in src as a single instruction.
func Decode(src []byte) (Inst, error) {
length := len(src)
if length < 2 {
return Inst{}, errShort
}
var x uint32
// Non-RVC instructions always starts with 0x11
// So check whether src[0] & 3 == 3
if src[0]&3 == 3 {
if length < 4 {
return Inst{}, errShort
}
length = 4
x = binary.LittleEndian.Uint32(src)
} else {
length = 2
x = uint32(binary.LittleEndian.Uint16(src))
}
Search:
for i, f := range instFormats {
if (x & f.mask) != f.value {
continue
}
// Decode args.
var args Args
for j, aop := range f.args {
if aop == 0 {
break
}
arg := decodeArg(aop, x, i)
if arg == nil && f.op != C_NOP {
// Cannot decode argument.
continue Search
}
args[j] = arg
}
if length == 2 {
args = convertCompressedIns(&f, args)
}
decoderCover[i] = true
inst := Inst{
Op: f.op,
Args: args,
Enc: x,
Len: length,
}
return inst, nil
}
return Inst{}, errUnknown
}
// decodeArg decodes the arg described by aop from the instruction bits x.
// It returns nil if x cannot be decoded according to aop.
func decodeArg(aop argType, x uint32, index int) Arg {
switch aop {
case arg_rd:
return X0 + Reg((x>>7)&((1<<5)-1))
case arg_rs1:
return X0 + Reg((x>>15)&((1<<5)-1))
case arg_rs2:
return X0 + Reg((x>>20)&((1<<5)-1))
case arg_rs3:
return X0 + Reg((x>>27)&((1<<5)-1))
case arg_fd:
return F0 + Reg((x>>7)&((1<<5)-1))
case arg_fs1:
return F0 + Reg((x>>15)&((1<<5)-1))
case arg_fs2:
return F0 + Reg((x>>20)&((1<<5)-1))
case arg_fs3:
return F0 + Reg((x>>27)&((1<<5)-1))
case arg_rs1_amo:
return AmoReg{X0 + Reg((x>>15)&((1<<5)-1))}
case arg_rs1_mem:
imm := x >> 20
// Sign-extend
if imm>>uint32(12-1) == 1 {
imm |= 0xfffff << 12
}
return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}}
case arg_rs1_store:
imm := (x<<20)>>27 | (x>>25)<<5
// Sign-extend
if imm>>uint32(12-1) == 1 {
imm |= 0xfffff << 12
}
return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}}
case arg_pred:
imm := x << 4 >> 28
return MemOrder(uint8(imm))
case arg_succ:
imm := x << 8 >> 28
return MemOrder(uint8(imm))
case arg_csr:
imm := x >> 20
return CSR(imm)
case arg_zimm:
imm := x << 12 >> 27
return Uimm{imm, true}
case arg_shamt5:
imm := x << 7 >> 27
return Uimm{imm, false}
case arg_shamt6:
imm := x << 6 >> 26
return Uimm{imm, false}
case arg_imm12:
imm := x >> 20
// Sign-extend
if imm>>uint32(12-1) == 1 {
imm |= 0xfffff << 12
}
return Simm{int32(imm), true, 12}
case arg_imm20:
imm := x >> 12
return Uimm{imm, false}
case arg_jimm20:
imm := (x>>31)<<20 | (x<<1)>>22<<1 | (x<<11)>>31<<11 | (x<<12)>>24<<12
// Sign-extend
if imm>>uint32(21-1) == 1 {
imm |= 0x7ff << 21
}
return Simm{int32(imm), true, 21}
case arg_simm12:
imm := (x<<20)>>27 | (x>>25)<<5
// Sign-extend
if imm>>uint32(12-1) == 1 {
imm |= 0xfffff << 12
}
return Simm{int32(imm), true, 12}
case arg_bimm12:
imm := (x<<20)>>28<<1 | (x<<1)>>26<<5 | (x<<24)>>31<<11 | (x>>31)<<12
// Sign-extend
if imm>>uint32(13-1) == 1 {
imm |= 0x7ffff << 13
}
return Simm{int32(imm), true, 13}
case arg_rd_p, arg_rs2_p:
return X8 + Reg((x>>2)&((1<<3)-1))
case arg_fd_p, arg_fs2_p:
return F8 + Reg((x>>2)&((1<<3)-1))
case arg_rs1_p, arg_rd_rs1_p:
return X8 + Reg((x>>7)&((1<<3)-1))
case arg_rd_n0, arg_rs1_n0, arg_rd_rs1_n0, arg_c_rs1_n0:
if X0+Reg((x>>7)&((1<<5)-1)) == X0 {
return nil
}
return X0 + Reg((x>>7)&((1<<5)-1))
case arg_c_rs2_n0:
if X0+Reg((x>>2)&((1<<5)-1)) == X0 {
return nil
}
return X0 + Reg((x>>2)&((1<<5)-1))
case arg_c_fs2:
return F0 + Reg((x>>2)&((1<<5)-1))
case arg_c_rs2:
return X0 + Reg((x>>2)&((1<<5)-1))
case arg_rd_n2:
if X0+Reg((x>>7)&((1<<5)-1)) == X0 || X0+Reg((x>>7)&((1<<5)-1)) == X2 {
return nil
}
return X0 + Reg((x>>7)&((1<<5)-1))
case arg_c_imm6:
imm := (x<<25)>>27 | (x<<19)>>31<<5
// Sign-extend
if imm>>uint32(6-1) == 1 {
imm |= 0x3ffffff << 6
}
return Simm{int32(imm), true, 6}
case arg_c_nzimm6:
imm := (x<<25)>>27 | (x<<19)>>31<<5
// Sign-extend
if imm>>uint32(6-1) == 1 {
imm |= 0x3ffffff << 6
}
if int32(imm) == 0 {
return nil
}
return Simm{int32(imm), true, 6}
case arg_c_nzuimm6:
imm := (x<<25)>>27 | (x<<19)>>31<<5
if int32(imm) == 0 {
return nil
}
return Uimm{imm, false}
case arg_c_uimm7:
imm := (x<<26)>>31<<6 | (x<<25)>>31<<2 | (x<<19)>>29<<3
return Uimm{imm, false}
case arg_c_uimm8:
imm := (x<<25)>>30<<6 | (x<<19)>>29<<3
return Uimm{imm, false}
case arg_c_uimm8sp_s:
imm := (x<<23)>>30<<6 | (x<<19)>>28<<2
return Uimm{imm, false}
case arg_c_uimm8sp:
imm := (x<<25)>>29<<2 | (x<<19)>>31<<5 | (x<<28)>>30<<6
return Uimm{imm, false}
case arg_c_uimm9sp_s:
imm := (x<<22)>>29<<6 | (x<<19)>>29<<3
return Uimm{imm, false}
case arg_c_uimm9sp:
imm := (x<<25)>>30<<3 | (x<<19)>>31<<5 | (x<<27)>>29<<6
return Uimm{imm, false}
case arg_c_bimm9:
imm := (x<<29)>>31<<5 | (x<<27)>>30<<1 | (x<<25)>>30<<6 | (x<<19)>>31<<8 | (x<<20)>>30<<3
// Sign-extend
if imm>>uint32(9-1) == 1 {
imm |= 0x7fffff << 9
}
return Simm{int32(imm), true, 9}
case arg_c_nzimm10:
imm := (x<<29)>>31<<5 | (x<<27)>>30<<7 | (x<<26)>>31<<6 | (x<<25)>>31<<4 | (x<<19)>>31<<9
// Sign-extend
if imm>>uint32(10-1) == 1 {
imm |= 0x3fffff << 10
}
if int32(imm) == 0 {
return nil
}
return Simm{int32(imm), true, 10}
case arg_c_nzuimm10:
imm := (x<<26)>>31<<3 | (x<<25)>>31<<2 | (x<<21)>>28<<6 | (x<<19)>>30<<4
if int32(imm) == 0 {
return nil
}
return Uimm{imm, false}
case arg_c_imm12:
imm := (x<<29)>>31<<5 | (x<<26)>>28<<1 | (x<<25)>>31<<7 | (x<<24)>>31<<6 | (x<<23)>>31<<10 | (x<<21)>>30<<8 | (x<<20)>>31<<4 | (x<<19)>>31<<11
// Sign-extend
if imm>>uint32(12-1) == 1 {
imm |= 0xfffff << 12
}
return Simm{int32(imm), true, 12}
case arg_c_nzimm18:
imm := (x<<25)>>27<<12 | (x<<19)>>31<<17
// Sign-extend
if imm>>uint32(18-1) == 1 {
imm |= 0x3fff << 18
}
if int32(imm) == 0 {
return nil
}
return Simm{int32(imm), true, 18}
default:
return nil
}
}
// convertCompressedIns rewrites the RVC Instruction to regular Instructions
func convertCompressedIns(f *instFormat, args Args) Args {
var newargs Args
switch f.op {
case C_ADDI4SPN:
f.op = ADDI
newargs[0] = args[0]
newargs[1] = Reg(X2)
newargs[2] = Simm{int32(args[1].(Uimm).Imm), true, 12}
case C_LW:
f.op = LW
newargs[0] = args[0]
newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_SW:
f.op = SW
newargs[0] = args[1]
newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_NOP:
f.op = ADDI
newargs[0] = X0
newargs[1] = X0
newargs[2] = Simm{0, true, 12}
case C_ADDI:
f.op = ADDI
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
case C_LI:
f.op = ADDI
newargs[0] = args[0]
newargs[1] = Reg(X0)
newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
case C_ADDI16SP:
f.op = ADDI
newargs[0] = Reg(X2)
newargs[1] = Reg(X2)
newargs[2] = Simm{args[0].(Simm).Imm, true, 12}
case C_LUI:
f.op = LUI
newargs[0] = args[0]
newargs[1] = Uimm{uint32(args[1].(Simm).Imm >> 12), false}
case C_ANDI:
f.op = ANDI
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
case C_SUB:
f.op = SUB
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_XOR:
f.op = XOR
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_OR:
f.op = OR
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_AND:
f.op = AND
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_J:
f.op = JAL
newargs[0] = Reg(X0)
newargs[1] = Simm{args[0].(Simm).Imm, true, 21}
case C_BEQZ:
f.op = BEQ
newargs[0] = args[0]
newargs[1] = Reg(X0)
newargs[2] = Simm{args[1].(Simm).Imm, true, 13}
case C_BNEZ:
f.op = BNE
newargs[0] = args[0]
newargs[1] = Reg(X0)
newargs[2] = Simm{args[1].(Simm).Imm, true, 13}
case C_LWSP:
f.op = LW
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
case C_JR:
f.op = JALR
newargs[0] = Reg(X0)
newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}}
case C_MV:
f.op = ADD
newargs[0] = args[0]
newargs[1] = Reg(X0)
newargs[2] = args[1]
case C_EBREAK:
f.op = EBREAK
case C_JALR:
f.op = JALR
newargs[0] = Reg(X1)
newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}}
case C_ADD:
f.op = ADD
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_SWSP:
f.op = SW
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
// riscv64 compressed instructions
case C_LD:
f.op = LD
newargs[0] = args[0]
newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_SD:
f.op = SD
newargs[0] = args[1]
newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_ADDIW:
f.op = ADDIW
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
case C_SRLI:
f.op = SRLI
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_SRAI:
f.op = SRAI
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_SUBW:
f.op = SUBW
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_ADDW:
f.op = ADDW
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_SLLI:
f.op = SLLI
newargs[0] = args[0]
newargs[1] = args[0]
newargs[2] = args[1]
case C_LDSP:
f.op = LD
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
case C_SDSP:
f.op = SD
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
// riscv double precision floating point compressed instructions
case C_FLD:
f.op = FLD
newargs[0] = args[0]
newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_FSD:
f.op = FSD
newargs[0] = args[1]
newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
case C_FLDSP:
f.op = FLD
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
case C_FSDSP:
f.op = FSD
newargs[0] = args[0]
newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
case C_UNIMP:
f.op = CSRRW
newargs[0] = Reg(X0)
newargs[1] = CSR(CYCLE)
newargs[2] = Reg(X0)
}
return newargs
}

328
riscv64/riscv64asm/gnu.go Normal file
Просмотреть файл

@ -0,0 +1,328 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv64asm
import (
"strings"
)
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This form typically matches the syntax defined in the RISC-V Instruction Set Manual. See
// https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf
func GNUSyntax(inst Inst) string {
op := strings.ToLower(inst.Op.String())
var args []string
for _, a := range inst.Args {
if a == nil {
break
}
args = append(args, strings.ToLower(a.String()))
}
switch inst.Op {
case ADDI, ADDIW, ANDI, ORI, SLLI, SLLIW, SRAI, SRAIW, SRLI, SRLIW, XORI:
if inst.Op == ADDI {
if inst.Args[1].(Reg) == X0 && inst.Args[0].(Reg) != X0 {
op = "li"
args[1] = args[2]
args = args[:len(args)-1]
break
}
if inst.Args[2].(Simm).Imm == 0 {
if inst.Args[0].(Reg) == X0 && inst.Args[1].(Reg) == X0 {
op = "nop"
args = nil
} else {
op = "mv"
args = args[:len(args)-1]
}
}
}
if inst.Op == ADDIW && inst.Args[2].(Simm).Imm == 0 {
op = "sext.w"
args = args[:len(args)-1]
}
if inst.Op == XORI && inst.Args[2].(Simm).String() == "-1" {
op = "not"
args = args[:len(args)-1]
}
case ADD:
if inst.Args[1].(Reg) == X0 {
op = "mv"
args[1] = args[2]
args = args[:len(args)-1]
}
case BEQ:
if inst.Args[1].(Reg) == X0 {
op = "beqz"
args[1] = args[2]
args = args[:len(args)-1]
}
case BGE:
if inst.Args[1].(Reg) == X0 {
op = "bgez"
args[1] = args[2]
args = args[:len(args)-1]
} else if inst.Args[0].(Reg) == X0 {
op = "blez"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case BLT:
if inst.Args[1].(Reg) == X0 {
op = "bltz"
args[1] = args[2]
args = args[:len(args)-1]
} else if inst.Args[0].(Reg) == X0 {
op = "bgtz"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case BNE:
if inst.Args[1].(Reg) == X0 {
op = "bnez"
args[1] = args[2]
args = args[:len(args)-1]
}
case CSRRC:
if inst.Args[0].(Reg) == X0 {
op = "csrc"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case CSRRCI:
if inst.Args[0].(Reg) == X0 {
op = "csrci"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case CSRRS:
if inst.Args[2].(Reg) == X0 {
switch inst.Args[1].(CSR) {
case FCSR:
op = "frcsr"
args = args[:len(args)-2]
case FFLAGS:
op = "frflags"
args = args[:len(args)-2]
case FRM:
op = "frrm"
args = args[:len(args)-2]
// rdcycleh, rdinstreth and rdtimeh are RV-32 only instructions.
// So not included there.
case CYCLE:
op = "rdcycle"
args = args[:len(args)-2]
case INSTRET:
op = "rdinstret"
args = args[:len(args)-2]
case TIME:
op = "rdtime"
args = args[:len(args)-2]
default:
op = "csrr"
args = args[:len(args)-1]
}
} else if inst.Args[0].(Reg) == X0 {
op = "csrs"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case CSRRSI:
if inst.Args[0].(Reg) == X0 {
op = "csrsi"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
case CSRRW:
switch inst.Args[1].(CSR) {
case FCSR:
op = "fscsr"
if inst.Args[0].(Reg) == X0 {
args[0] = args[2]
args = args[:len(args)-2]
} else {
args[1] = args[2]
args = args[:len(args)-1]
}
case FFLAGS:
op = "fsflags"
if inst.Args[0].(Reg) == X0 {
args[0] = args[2]
args = args[:len(args)-2]
} else {
args[1] = args[2]
args = args[:len(args)-1]
}
case FRM:
op = "fsrm"
if inst.Args[0].(Reg) == X0 {
args[0] = args[2]
args = args[:len(args)-2]
} else {
args[1] = args[2]
args = args[:len(args)-1]
}
case CYCLE:
if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
op = "unimp"
args = nil
}
default:
if inst.Args[0].(Reg) == X0 {
op = "csrw"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
}
case CSRRWI:
if inst.Args[0].(Reg) == X0 {
op = "csrwi"
args[0], args[1] = args[1], args[2]
args = args[:len(args)-1]
}
// When both pred and succ equals to iorw, the GNU objdump will omit them.
case FENCE:
if inst.Args[0].(MemOrder).String() == "iorw" &&
inst.Args[1].(MemOrder).String() == "iorw" {
args = nil
}
case FSGNJX_D:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fabs.d"
args = args[:len(args)-1]
}
case FSGNJX_S:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fabs.s"
args = args[:len(args)-1]
}
case FSGNJ_D:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fmv.d"
args = args[:len(args)-1]
}
case FSGNJ_S:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fmv.s"
args = args[:len(args)-1]
}
case FSGNJN_D:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fneg.d"
args = args[:len(args)-1]
}
case FSGNJN_S:
if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
op = "fneg.s"
args = args[:len(args)-1]
}
case JAL:
if inst.Args[0].(Reg) == X0 {
op = "j"
args[0] = args[1]
args = args[:len(args)-1]
} else if inst.Args[0].(Reg) == X1 {
op = "jal"
args[0] = args[1]
args = args[:len(args)-1]
}
case JALR:
if inst.Args[0].(Reg) == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
args[0] = inst.Args[1].(RegOffset).OfsReg.String()
args = args[:len(args)-1]
}
if inst.Args[0].(Reg) == X0 {
if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
op = "ret"
args = nil
} else if inst.Args[1].(RegOffset).Ofs.Imm == 0 {
op = "jr"
args[0] = inst.Args[1].(RegOffset).OfsReg.String()
args = args[:len(args)-1]
} else {
op = "jr"
args[0] = inst.Args[1].(RegOffset).String()
args = args[:len(args)-1]
}
}
case SLTIU:
if inst.Args[2].(Simm).String() == "1" {
op = "seqz"
args = args[:len(args)-1]
}
case SLT:
if inst.Args[1].(Reg) == X0 {
op = "sgtz"
args[1] = args[2]
args = args[:len(args)-1]
} else if inst.Args[2].(Reg) == X0 {
op = "sltz"
args = args[:len(args)-1]
}
case SLTU:
if inst.Args[1].(Reg) == X0 {
op = "snez"
args[1] = args[2]
args = args[:len(args)-1]
}
case SUB:
if inst.Args[1].(Reg) == X0 {
op = "neg"
args[1] = args[2]
args = args[:len(args)-1]
}
case SUBW:
if inst.Args[1].(Reg) == X0 {
op = "negw"
args[1] = args[2]
args = args[:len(args)-1]
}
}
if args != nil {
op += " " + strings.Join(args, ",")
}
return op
}

495
riscv64/riscv64asm/inst.go Normal file
Просмотреть файл

@ -0,0 +1,495 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv64asm
import (
"fmt"
"strings"
)
// An Op is a RISC-V opcode.
type Op uint16
// NOTE: The actual Op values are defined in tables.go.
func (op Op) String() string {
if op >= Op(len(opstr)) || opstr[op] == "" {
return fmt.Sprintf("Op(%d)", op)
}
return opstr[op]
}
// An Arg is a single instruction argument.
type Arg interface {
String() string
}
// An Args holds the instruction arguments.
// If an instruction has fewer than 6 arguments,
// the final elements in the array are nil.
type Args [6]Arg
// An Inst is a single instruction.
type Inst struct {
Op Op // Opcode mnemonic.
Enc uint32 // Raw encoding bits.
Args Args // Instruction arguments, in RISC-V mamual order.
Len int // Length of encoded instruction in bytes
}
func (i Inst) String() string {
var args []string
for _, arg := range i.Args {
if arg == nil {
break
}
args = append(args, arg.String())
}
if len(args) == 0 {
return i.Op.String()
}
return i.Op.String() + " " + strings.Join(args, ",")
}
// A Reg is a single register.
// The zero value denotes X0, not the absence of a register.
type Reg uint16
const (
// General-purpose register
X0 Reg = iota
X1
X2
X3
X4
X5
X6
X7
X8
X9
X10
X11
X12
X13
X14
X15
X16
X17
X18
X19
X20
X21
X22
X23
X24
X25
X26
X27
X28
X29
X30
X31
//Float point register
F0
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
F25
F26
F27
F28
F29
F30
F31
)
func (r Reg) String() string {
switch {
case r >= X0 && r <= X31:
return fmt.Sprintf("x%d", r)
case r >= F0 && r <= F31:
return fmt.Sprintf("f%d", r-F0)
default:
return fmt.Sprintf("Unknown(%d)", r)
}
}
// A CSR is a single control and status register.
// Use stringer to generate CSR match table.
//
//go:generate stringer -type=CSR
type CSR uint16
const (
// Control status register
USTATUS CSR = 0x0000
FFLAGS CSR = 0x0001
FRM CSR = 0x0002
FCSR CSR = 0x0003
UIE CSR = 0x0004
UTVEC CSR = 0x0005
UTVT CSR = 0x0007
VSTART CSR = 0x0008
VXSAT CSR = 0x0009
VXRM CSR = 0x000a
VCSR CSR = 0x000f
USCRATCH CSR = 0x0040
UEPC CSR = 0x0041
UCAUSE CSR = 0x0042
UTVAL CSR = 0x0043
UIP CSR = 0x0044
UNXTI CSR = 0x0045
UINTSTATUS CSR = 0x0046
USCRATCHCSW CSR = 0x0048
USCRATCHCSWL CSR = 0x0049
SSTATUS CSR = 0x0100
SEDELEG CSR = 0x0102
SIDELEG CSR = 0x0103
SIE CSR = 0x0104
STVEC CSR = 0x0105
SCOUNTEREN CSR = 0x0106
STVT CSR = 0x0107
SSCRATCH CSR = 0x0140
SEPC CSR = 0x0141
SCAUSE CSR = 0x0142
STVAL CSR = 0x0143
SIP CSR = 0x0144
SNXTI CSR = 0x0145
SINTSTATUS CSR = 0x0146
SSCRATCHCSW CSR = 0x0148
SSCRATCHCSWL CSR = 0x0149
SATP CSR = 0x0180
VSSTATUS CSR = 0x0200
VSIE CSR = 0x0204
VSTVEC CSR = 0x0205
VSSCRATCH CSR = 0x0240
VSEPC CSR = 0x0241
VSCAUSE CSR = 0x0242
VSTVAL CSR = 0x0243
VSIP CSR = 0x0244
VSATP CSR = 0x0280
MSTATUS CSR = 0x0300
MISA CSR = 0x0301
MEDELEG CSR = 0x0302
MIDELEG CSR = 0x0303
MIE CSR = 0x0304
MTVEC CSR = 0x0305
MCOUNTEREN CSR = 0x0306
MTVT CSR = 0x0307
MSTATUSH CSR = 0x0310
MCOUNTINHIBIT CSR = 0x0320
MHPMEVENT3 CSR = 0x0323
MHPMEVENT4 CSR = 0x0324
MHPMEVENT5 CSR = 0x0325
MHPMEVENT6 CSR = 0x0326
MHPMEVENT7 CSR = 0x0327
MHPMEVENT8 CSR = 0x0328
MHPMEVENT9 CSR = 0x0329
MHPMEVENT10 CSR = 0x032a
MHPMEVENT11 CSR = 0x032b
MHPMEVENT12 CSR = 0x032c
MHPMEVENT13 CSR = 0x032d
MHPMEVENT14 CSR = 0x032e
MHPMEVENT15 CSR = 0x032f
MHPMEVENT16 CSR = 0x0330
MHPMEVENT17 CSR = 0x0331
MHPMEVENT18 CSR = 0x0332
MHPMEVENT19 CSR = 0x0333
MHPMEVENT20 CSR = 0x0334
MHPMEVENT21 CSR = 0x0335
MHPMEVENT22 CSR = 0x0336
MHPMEVENT23 CSR = 0x0337
MHPMEVENT24 CSR = 0x0338
MHPMEVENT25 CSR = 0x0339
MHPMEVENT26 CSR = 0x033a
MHPMEVENT27 CSR = 0x033b
MHPMEVENT28 CSR = 0x033c
MHPMEVENT29 CSR = 0x033d
MHPMEVENT30 CSR = 0x033e
MHPMEVENT31 CSR = 0x033f
MSCRATCH CSR = 0x0340
MEPC CSR = 0x0341
MCAUSE CSR = 0x0342
MTVAL CSR = 0x0343
MIP CSR = 0x0344
MNXTI CSR = 0x0345
MINTSTATUS CSR = 0x0346
MSCRATCHCSW CSR = 0x0348
MSCRATCHCSWL CSR = 0x0349
MTINST CSR = 0x034a
MTVAL2 CSR = 0x034b
PMPCFG0 CSR = 0x03a0
PMPCFG1 CSR = 0x03a1
PMPCFG2 CSR = 0x03a2
PMPCFG3 CSR = 0x03a3
PMPADDR0 CSR = 0x03b0
PMPADDR1 CSR = 0x03b1
PMPADDR2 CSR = 0x03b2
PMPADDR3 CSR = 0x03b3
PMPADDR4 CSR = 0x03b4
PMPADDR5 CSR = 0x03b5
PMPADDR6 CSR = 0x03b6
PMPADDR7 CSR = 0x03b7
PMPADDR8 CSR = 0x03b8
PMPADDR9 CSR = 0x03b9
PMPADDR10 CSR = 0x03ba
PMPADDR11 CSR = 0x03bb
PMPADDR12 CSR = 0x03bc
PMPADDR13 CSR = 0x03bd
PMPADDR14 CSR = 0x03be
PMPADDR15 CSR = 0x03bf
HSTATUS CSR = 0x0600
HEDELEG CSR = 0x0602
HIDELEG CSR = 0x0603
HIE CSR = 0x0604
HTIMEDELTA CSR = 0x0605
HCOUNTEREN CSR = 0x0606
HGEIE CSR = 0x0607
HTIMEDELTAH CSR = 0x0615
HTVAL CSR = 0x0643
HIP CSR = 0x0644
HVIP CSR = 0x0645
HTINST CSR = 0x064a
HGATP CSR = 0x0680
TSELECT CSR = 0x07a0
TDATA1 CSR = 0x07a1
TDATA2 CSR = 0x07a2
TDATA3 CSR = 0x07a3
TINFO CSR = 0x07a4
TCONTROL CSR = 0x07a5
MCONTEXT CSR = 0x07a8
MNOISE CSR = 0x07a9
SCONTEXT CSR = 0x07aa
DCSR CSR = 0x07b0
DPC CSR = 0x07b1
DSCRATCH0 CSR = 0x07b2
DSCRATCH1 CSR = 0x07b3
MCYCLE CSR = 0x0b00
MINSTRET CSR = 0x0b02
MHPMCOUNTER3 CSR = 0x0b03
MHPMCOUNTER4 CSR = 0x0b04
MHPMCOUNTER5 CSR = 0x0b05
MHPMCOUNTER6 CSR = 0x0b06
MHPMCOUNTER7 CSR = 0x0b07
MHPMCOUNTER8 CSR = 0x0b08
MHPMCOUNTER9 CSR = 0x0b09
MHPMCOUNTER10 CSR = 0x0b0a
MHPMCOUNTER11 CSR = 0x0b0b
MHPMCOUNTER12 CSR = 0x0b0c
MHPMCOUNTER13 CSR = 0x0b0d
MHPMCOUNTER14 CSR = 0x0b0e
MHPMCOUNTER15 CSR = 0x0b0f
MHPMCOUNTER16 CSR = 0x0b10
MHPMCOUNTER17 CSR = 0x0b11
MHPMCOUNTER18 CSR = 0x0b12
MHPMCOUNTER19 CSR = 0x0b13
MHPMCOUNTER20 CSR = 0x0b14
MHPMCOUNTER21 CSR = 0x0b15
MHPMCOUNTER22 CSR = 0x0b16
MHPMCOUNTER23 CSR = 0x0b17
MHPMCOUNTER24 CSR = 0x0b18
MHPMCOUNTER25 CSR = 0x0b19
MHPMCOUNTER26 CSR = 0x0b1a
MHPMCOUNTER27 CSR = 0x0b1b
MHPMCOUNTER28 CSR = 0x0b1c
MHPMCOUNTER29 CSR = 0x0b1d
MHPMCOUNTER30 CSR = 0x0b1e
MHPMCOUNTER31 CSR = 0x0b1f
MCYCLEH CSR = 0x0b80
MINSTRETH CSR = 0x0b82
MHPMCOUNTER3H CSR = 0x0b83
MHPMCOUNTER4H CSR = 0x0b84
MHPMCOUNTER5H CSR = 0x0b85
MHPMCOUNTER6H CSR = 0x0b86
MHPMCOUNTER7H CSR = 0x0b87
MHPMCOUNTER8H CSR = 0x0b88
MHPMCOUNTER9H CSR = 0x0b89
MHPMCOUNTER10H CSR = 0x0b8a
MHPMCOUNTER11H CSR = 0x0b8b
MHPMCOUNTER12H CSR = 0x0b8c
MHPMCOUNTER13H CSR = 0x0b8d
MHPMCOUNTER14H CSR = 0x0b8e
MHPMCOUNTER15H CSR = 0x0b8f
MHPMCOUNTER16H CSR = 0x0b90
MHPMCOUNTER17H CSR = 0x0b91
MHPMCOUNTER18H CSR = 0x0b92
MHPMCOUNTER19H CSR = 0x0b93
MHPMCOUNTER20H CSR = 0x0b94
MHPMCOUNTER21H CSR = 0x0b95
MHPMCOUNTER22H CSR = 0x0b96
MHPMCOUNTER23H CSR = 0x0b97
MHPMCOUNTER24H CSR = 0x0b98
MHPMCOUNTER25H CSR = 0x0b99
MHPMCOUNTER26H CSR = 0x0b9a
MHPMCOUNTER27H CSR = 0x0b9b
MHPMCOUNTER28H CSR = 0x0b9c
MHPMCOUNTER29H CSR = 0x0b9d
MHPMCOUNTER30H CSR = 0x0b9e
MHPMCOUNTER31H CSR = 0x0b9f
CYCLE CSR = 0x0c00
TIME CSR = 0x0c01
INSTRET CSR = 0x0c02
HPMCOUNTER3 CSR = 0x0c03
HPMCOUNTER4 CSR = 0x0c04
HPMCOUNTER5 CSR = 0x0c05
HPMCOUNTER6 CSR = 0x0c06
HPMCOUNTER7 CSR = 0x0c07
HPMCOUNTER8 CSR = 0x0c08
HPMCOUNTER9 CSR = 0x0c09
HPMCOUNTER10 CSR = 0x0c0a
HPMCOUNTER11 CSR = 0x0c0b
HPMCOUNTER12 CSR = 0x0c0c
HPMCOUNTER13 CSR = 0x0c0d
HPMCOUNTER14 CSR = 0x0c0e
HPMCOUNTER15 CSR = 0x0c0f
HPMCOUNTER16 CSR = 0x0c10
HPMCOUNTER17 CSR = 0x0c11
HPMCOUNTER18 CSR = 0x0c12
HPMCOUNTER19 CSR = 0x0c13
HPMCOUNTER20 CSR = 0x0c14
HPMCOUNTER21 CSR = 0x0c15
HPMCOUNTER22 CSR = 0x0c16
HPMCOUNTER23 CSR = 0x0c17
HPMCOUNTER24 CSR = 0x0c18
HPMCOUNTER25 CSR = 0x0c19
HPMCOUNTER26 CSR = 0x0c1a
HPMCOUNTER27 CSR = 0x0c1b
HPMCOUNTER28 CSR = 0x0c1c
HPMCOUNTER29 CSR = 0x0c1d
HPMCOUNTER30 CSR = 0x0c1e
HPMCOUNTER31 CSR = 0x0c1f
VL CSR = 0x0c20
VTYPE CSR = 0x0c21
VLENB CSR = 0x0c22
CYCLEH CSR = 0x0c80
TIMEH CSR = 0x0c81
INSTRETH CSR = 0x0c82
HPMCOUNTER3H CSR = 0x0c83
HPMCOUNTER4H CSR = 0x0c84
HPMCOUNTER5H CSR = 0x0c85
HPMCOUNTER6H CSR = 0x0c86
HPMCOUNTER7H CSR = 0x0c87
HPMCOUNTER8H CSR = 0x0c88
HPMCOUNTER9H CSR = 0x0c89
HPMCOUNTER10H CSR = 0x0c8a
HPMCOUNTER11H CSR = 0x0c8b
HPMCOUNTER12H CSR = 0x0c8c
HPMCOUNTER13H CSR = 0x0c8d
HPMCOUNTER14H CSR = 0x0c8e
HPMCOUNTER15H CSR = 0x0c8f
HPMCOUNTER16H CSR = 0x0c90
HPMCOUNTER17H CSR = 0x0c91
HPMCOUNTER18H CSR = 0x0c92
HPMCOUNTER19H CSR = 0x0c93
HPMCOUNTER20H CSR = 0x0c94
HPMCOUNTER21H CSR = 0x0c95
HPMCOUNTER22H CSR = 0x0c96
HPMCOUNTER23H CSR = 0x0c97
HPMCOUNTER24H CSR = 0x0c98
HPMCOUNTER25H CSR = 0x0c99
HPMCOUNTER26H CSR = 0x0c9a
HPMCOUNTER27H CSR = 0x0c9b
HPMCOUNTER28H CSR = 0x0c9c
HPMCOUNTER29H CSR = 0x0c9d
HPMCOUNTER30H CSR = 0x0c9e
HPMCOUNTER31H CSR = 0x0c9f
HGEIP CSR = 0x0e12
MVENDORID CSR = 0x0f11
MARCHID CSR = 0x0f12
MIMPID CSR = 0x0f13
MHARTID CSR = 0x0f14
MENTROPY CSR = 0x0f15
)
// An Uimm is an unsigned immediate number
type Uimm struct {
Imm uint32 // 32-bit unsigned integer
Decimal bool // Print format of the immediate, either decimal or hexadecimal
}
func (ui Uimm) String() string {
if ui.Decimal {
return fmt.Sprintf("%d", ui.Imm)
}
return fmt.Sprintf("%#x", ui.Imm)
}
// A Simm is a signed immediate number
type Simm struct {
Imm int32 // 32-bit signed integer
Decimal bool // Print format of the immediate, either decimal or hexadecimal
Width uint8 // Actual width of the Simm
}
func (si Simm) String() string {
if si.Decimal {
return fmt.Sprintf("%d", si.Imm)
}
return fmt.Sprintf("%#x", si.Imm)
}
// An AmoReg is an atomic address register used in AMO instructions
type AmoReg struct {
reg Reg // Avoid promoted String method
}
func (amoReg AmoReg) String() string {
return fmt.Sprintf("(%s)", amoReg.reg)
}
// A RegOffset is a register with offset value
type RegOffset struct {
OfsReg Reg
Ofs Simm
}
func (regofs RegOffset) String() string {
return fmt.Sprintf("%s(%s)", regofs.Ofs, regofs.OfsReg)
}
// A MemOrder is a memory order hint in fence instruction
type MemOrder uint8
func (memOrder MemOrder) String() string {
var str string
if memOrder<<7>>7 == 1 {
str += "i"
}
if memOrder>>1<<7>>7 == 1 {
str += "o"
}
if memOrder>>2<<7>>7 == 1 {
str += "r"
}
if memOrder>>3<<7>>7 == 1 {
str += "w"
}
return str
}

Просмотреть файл

@ -0,0 +1,377 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv64asm
import (
"fmt"
"io"
"strconv"
"strings"
)
// GoSyntax returns the Go assembler syntax for the instruction.
// The syntax was originally defined by Plan 9.
// The pc is the program counter of the instruction, used for
// expanding PC-relative addresses into absolute ones.
// The symname function queries the symbol table for the program
// being disassembled. Given a target address it returns the name
// and base address of the symbol containing the target, if any;
// otherwise it returns "", 0.
// The reader text should read from the text segment using text addresses
// as offsets; it is used to display pc-relative loads as constant loads.
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
if symname == nil {
symname = func(uint64) (string, uint64) { return "", 0 }
}
var args []string
for _, a := range inst.Args {
if a == nil {
break
}
args = append(args, plan9Arg(&inst, pc, symname, a))
}
op := inst.Op.String()
switch inst.Op {
case AMOADD_D, AMOADD_D_AQ, AMOADD_D_RL, AMOADD_D_AQRL, AMOADD_W, AMOADD_W_AQ,
AMOADD_W_RL, AMOADD_W_AQRL, AMOAND_D, AMOAND_D_AQ, AMOAND_D_RL, AMOAND_D_AQRL,
AMOAND_W, AMOAND_W_AQ, AMOAND_W_RL, AMOAND_W_AQRL, AMOMAXU_D, AMOMAXU_D_AQ,
AMOMAXU_D_RL, AMOMAXU_D_AQRL, AMOMAXU_W, AMOMAXU_W_AQ, AMOMAXU_W_RL, AMOMAXU_W_AQRL,
AMOMAX_D, AMOMAX_D_AQ, AMOMAX_D_RL, AMOMAX_D_AQRL, AMOMAX_W, AMOMAX_W_AQ, AMOMAX_W_RL,
AMOMAX_W_AQRL, AMOMINU_D, AMOMINU_D_AQ, AMOMINU_D_RL, AMOMINU_D_AQRL, AMOMINU_W,
AMOMINU_W_AQ, AMOMINU_W_RL, AMOMINU_W_AQRL, AMOMIN_D, AMOMIN_D_AQ, AMOMIN_D_RL,
AMOMIN_D_AQRL, AMOMIN_W, AMOMIN_W_AQ, AMOMIN_W_RL, AMOMIN_W_AQRL, AMOOR_D, AMOOR_D_AQ,
AMOOR_D_RL, AMOOR_D_AQRL, AMOOR_W, AMOOR_W_AQ, AMOOR_W_RL, AMOOR_W_AQRL, AMOSWAP_D,
AMOSWAP_D_AQ, AMOSWAP_D_RL, AMOSWAP_D_AQRL, AMOSWAP_W, AMOSWAP_W_AQ, AMOSWAP_W_RL,
AMOSWAP_W_AQRL, AMOXOR_D, AMOXOR_D_AQ, AMOXOR_D_RL, AMOXOR_D_AQRL, AMOXOR_W,
AMOXOR_W_AQ, AMOXOR_W_RL, AMOXOR_W_AQRL, SC_D, SC_D_AQ, SC_D_RL, SC_D_AQRL,
SC_W, SC_W_AQ, SC_W_RL, SC_W_AQRL:
// Atomic instructions have special operand order.
args[2], args[1] = args[1], args[2]
case ADDI:
if inst.Args[2].(Simm).Imm == 0 {
op = "MOV"
args = args[:len(args)-1]
}
case ADDIW:
if inst.Args[2].(Simm).Imm == 0 {
op = "MOVW"
args = args[:len(args)-1]
}
case ANDI:
if inst.Args[2].(Simm).Imm == 255 {
op = "MOVBU"
args = args[:len(args)-1]
}
case BEQ:
if inst.Args[1].(Reg) == X0 {
op = "BEQZ"
args[1] = args[2]
args = args[:len(args)-1]
}
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
case BGE:
if inst.Args[1].(Reg) == X0 {
op = "BGEZ"
args[1] = args[2]
args = args[:len(args)-1]
}
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
case BLT:
if inst.Args[1].(Reg) == X0 {
op = "BLTZ"
args[1] = args[2]
args = args[:len(args)-1]
}
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
case BNE:
if inst.Args[1].(Reg) == X0 {
op = "BNEZ"
args[1] = args[2]
args = args[:len(args)-1]
}
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
case BLTU, BGEU:
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
case CSRRW:
switch inst.Args[1].(CSR) {
case FCSR:
op = "FSCSR"
args[1] = args[2]
args = args[:len(args)-1]
case FFLAGS:
op = "FSFLAGS"
args[1] = args[2]
args = args[:len(args)-1]
case FRM:
op = "FSRM"
args[1] = args[2]
args = args[:len(args)-1]
case CYCLE:
if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
op = "UNIMP"
args = nil
}
}
case CSRRS:
if inst.Args[2].(Reg) == X0 {
switch inst.Args[1].(CSR) {
case FCSR:
op = "FRCSR"
args = args[:len(args)-2]
case FFLAGS:
op = "FRFLAGS"
args = args[:len(args)-2]
case FRM:
op = "FRRM"
args = args[:len(args)-2]
case CYCLE:
op = "RDCYCLE"
args = args[:len(args)-2]
case CYCLEH:
op = "RDCYCLEH"
args = args[:len(args)-2]
case INSTRET:
op = "RDINSTRET"
args = args[:len(args)-2]
case INSTRETH:
op = "RDINSTRETH"
args = args[:len(args)-2]
case TIME:
op = "RDTIME"
args = args[:len(args)-2]
case TIMEH:
op = "RDTIMEH"
args = args[:len(args)-2]
}
}
// Fence instruction in plan9 doesn't have any operands.
case FENCE:
args = nil
case FMADD_D, FMADD_H, FMADD_Q, FMADD_S, FMSUB_D, FMSUB_H,
FMSUB_Q, FMSUB_S, FNMADD_D, FNMADD_H, FNMADD_Q, FNMADD_S,
FNMSUB_D, FNMSUB_H, FNMSUB_Q, FNMSUB_S:
args[1], args[3] = args[3], args[1]
case FSGNJ_S:
if inst.Args[2] == inst.Args[1] {
op = "MOVF"
args = args[:len(args)-1]
}
case FSGNJ_D:
if inst.Args[2] == inst.Args[1] {
op = "MOVD"
args = args[:len(args)-1]
}
case FSGNJX_S:
if inst.Args[2] == inst.Args[1] {
op = "FABSS"
args = args[:len(args)-1]
}
case FSGNJX_D:
if inst.Args[2] == inst.Args[1] {
op = "FABSD"
args = args[:len(args)-1]
}
case FSGNJN_S:
if inst.Args[2] == inst.Args[1] {
op = "FNEGS"
args = args[:len(args)-1]
}
case FSGNJN_D:
if inst.Args[2] == inst.Args[1] {
op = "FNESD"
args = args[:len(args)-1]
}
case LD, SD:
op = "MOV"
if inst.Op == SD {
args[0], args[1] = args[1], args[0]
}
case LB, SB:
op = "MOVB"
if inst.Op == SB {
args[0], args[1] = args[1], args[0]
}
case LH, SH:
op = "MOVH"
if inst.Op == SH {
args[0], args[1] = args[1], args[0]
}
case LW, SW:
op = "MOVW"
if inst.Op == SW {
args[0], args[1] = args[1], args[0]
}
case LBU:
op = "MOVBU"
case LHU:
op = "MOVHU"
case LWU:
op = "MOVWU"
case FLW, FSW:
op = "MOVF"
if inst.Op == FLW {
args[0], args[1] = args[1], args[0]
}
case FLD, FSD:
op = "MOVD"
if inst.Op == FLD {
args[0], args[1] = args[1], args[0]
}
case SUB:
if inst.Args[1].(Reg) == X0 {
op = "NEG"
args[1] = args[2]
args = args[:len(args)-1]
}
case XORI:
if inst.Args[2].(Simm).String() == "-1" {
op = "NOT"
args = args[:len(args)-1]
}
case SLTIU:
if inst.Args[2].(Simm).Imm == 1 {
op = "SEQZ"
args = args[:len(args)-1]
}
case SLTU:
if inst.Args[1].(Reg) == X0 {
op = "SNEZ"
args[1] = args[2]
args = args[:len(args)-1]
}
case JAL:
if inst.Args[0].(Reg) == X0 {
op = "JMP"
args[0] = args[1]
args = args[:len(args)-1]
} else if inst.Args[0].(Reg) == X1 {
op = "CALL"
args[0] = args[1]
args = args[:len(args)-1]
} else {
args[0], args[1] = args[1], args[0]
}
case JALR:
if inst.Args[0].(Reg) == X0 {
if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
op = "RET"
args = nil
break
}
op = "JMP"
args[0] = args[1]
args = args[:len(args)-1]
} else if inst.Args[0].(Reg) == X1 {
op = "CALL"
args[0] = args[1]
args = args[:len(args)-1]
} else {
args[0], args[1] = args[1], args[0]
}
}
// Reverse args, placing dest last.
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
// Change to plan9 opcode format
// Atomic instructions do not have reorder suffix, so remove them
op = strings.Replace(op, ".AQRL", "", -1)
op = strings.Replace(op, ".AQ", "", -1)
op = strings.Replace(op, ".RL", "", -1)
op = strings.Replace(op, ".", "", -1)
if args != nil {
op += " " + strings.Join(args, ", ")
}
return op
}
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
switch a := arg.(type) {
case Uimm:
return fmt.Sprintf("$%d", uint32(a.Imm))
case Simm:
imm, _ := strconv.Atoi(a.String())
if a.Width == 13 || a.Width == 21 {
addr := int64(pc) + int64(imm)
if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
return fmt.Sprintf("%s(SB)", s)
}
return fmt.Sprintf("%d(PC)", imm/4)
}
return fmt.Sprintf("$%d", int32(imm))
case Reg:
if a <= 31 {
return fmt.Sprintf("X%d", a)
} else {
return fmt.Sprintf("F%d", a-32)
}
case RegOffset:
if a.Ofs.Imm == 0 {
return fmt.Sprintf("(X%d)", a.OfsReg)
} else {
return fmt.Sprintf("%s(X%d)", a.Ofs.String(), a.OfsReg)
}
case AmoReg:
return fmt.Sprintf("(X%d)", a.reg)
default:
return strings.ToUpper(arg.String())
}
}

1474
riscv64/riscv64asm/tables.go Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -51,7 +51,7 @@ var extensions = []string{
}
const (
prologueSec = "// Generated by riscv64spec riscv-opcodes\n// DO NOT EDIT\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage riscv64asm\n\n"
prologueSec = "// Code generated by riscv64spec riscv-opcodes\n// DO NOT EDIT\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage riscv64asm\n\n"
opSec = "const (\n\t_ Op = iota\n"
opstrSec = "var opstr = [...]string{\n"
instFormatsSec = "var instFormats = [...]instFormat{\n"
@ -175,7 +175,7 @@ func genInst(words []string) {
var value uint32
var mask uint32
var instArgs []string
var argTypeList []string
for i := 1; i < len(words); i++ {
if strings.Contains(words[i], "=") {
@ -188,13 +188,13 @@ func genInst(words []string) {
value |= subval
mask |= submsk
} else if len(words[i]) > 0 {
instArgs = append(instArgs, words[i])
argTypeList = append(argTypeList, words[i])
}
}
instArgsStr := inferFormats(instArgs, op)
instArgsStr := inferFormats(argTypeList, op)
instFormatComment := "// " + strings.Replace(op, "_", ".", -1) + " " + strings.Replace(instArgsStr, "arg_", "", -1)
instFormat := fmt.Sprintf("{mask: %#08x, value: %#08x, op: %s, args: instArgs{%s}},", mask, value, op, instArgsStr)
instFormat := fmt.Sprintf("{mask: %#08x, value: %#08x, op: %s, args: argTypeList{%s}},", mask, value, op, instArgsStr)
// Handle the suffix of atomic instruction.
if isAtomic(op) {
@ -206,7 +206,7 @@ func genInst(words []string) {
avalue := value | (uint32(i) << 25)
amask := mask | 0x06000000
ainstFormatComment := "// " + strings.Replace(aop, "_", ".", -1) + " " + strings.Replace(instArgsStr, "arg_", "", -1)
ainstFormat := fmt.Sprintf("{mask: %#08x, value: %#08x, op: %s, args: instArgs{%s}},", amask, avalue, aop, instArgsStr)
ainstFormat := fmt.Sprintf("{mask: %#08x, value: %#08x, op: %s, args: argTypeList{%s}},", amask, avalue, aop, instArgsStr)
ops = append(ops, aop)
opstrs[aop] = aopstr
instFormats[aop] = ainstFormat
@ -227,7 +227,7 @@ func genInst(words []string) {
// U-Type (inst rd, imm),
// SB-Type (inst rs1, rs2, offset)
// S-Type (inst rs2, offset(rs1))
func inferFormats(instArgs []string, op string) string {
func inferFormats(argTypeList []string, op string) string {
switch {
case strings.Contains(op, "AMO") || strings.Contains(op, "SC_"):
return "arg_rd, arg_rs2, arg_rs1_amo"
@ -265,7 +265,7 @@ func inferFormats(instArgs []string, op string) string {
default:
var instStr []string
for _, arg := range instArgs {
for _, arg := range argTypeList {
if decodeArgs(arg, op) != "" {
instStr = append(instStr, decodeArgs(arg, op))
}