Source file src/cmd/vendor/golang.org/x/arch/riscv64/riscv64asm/decode.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package riscv64asm
     6  
     7  import (
     8  	"encoding/binary"
     9  	"errors"
    10  )
    11  
    12  type argTypeList [6]argType
    13  
    14  // An instFormat describes the format of an instruction encoding.
    15  type instFormat struct {
    16  	mask  uint32
    17  	value uint32
    18  	op    Op
    19  	// args describe how to decode the instruction arguments.
    20  	// args is stored as a fixed-size array.
    21  	// if there are fewer than len(args) arguments, args[i] == 0 marks
    22  	// the end of the argument list.
    23  	args argTypeList
    24  }
    25  
    26  var (
    27  	errShort   = errors.New("truncated instruction")
    28  	errUnknown = errors.New("unknown instruction")
    29  )
    30  
    31  var decoderCover []bool
    32  
    33  func init() {
    34  	decoderCover = make([]bool, len(instFormats))
    35  }
    36  
    37  // Decode decodes the 4 bytes in src as a single instruction.
    38  func Decode(src []byte) (Inst, error) {
    39  	length := len(src)
    40  	if length < 2 {
    41  		return Inst{}, errShort
    42  	}
    43  
    44  	var x uint32
    45  	// Non-RVC instructions always starts with 0x11
    46  	// So check whether src[0] & 3 == 3
    47  	if src[0]&3 == 3 {
    48  		if length < 4 {
    49  			return Inst{}, errShort
    50  		}
    51  		length = 4
    52  		x = binary.LittleEndian.Uint32(src)
    53  	} else {
    54  		length = 2
    55  		x = uint32(binary.LittleEndian.Uint16(src))
    56  	}
    57  
    58  Search:
    59  	for i, f := range instFormats {
    60  		if (x & f.mask) != f.value {
    61  			continue
    62  		}
    63  
    64  		if !validEncoding(f.op, x) {
    65  			continue Search
    66  		}
    67  
    68  		// Decode args.
    69  		var args Args
    70  		k := 0
    71  		for _, aop := range f.args {
    72  			if aop == 0 {
    73  				break
    74  			}
    75  			arg := decodeArg(aop, x, i)
    76  			if arg == nil {
    77  				if aop == arg_vm {
    78  					continue
    79  				}
    80  				if f.op != C_NOP {
    81  					// Cannot decode argument.
    82  					continue Search
    83  				}
    84  			}
    85  			args[k] = arg
    86  			k++
    87  		}
    88  
    89  		if length == 2 {
    90  			args = convertCompressedIns(&f, args)
    91  		}
    92  
    93  		decoderCover[i] = true
    94  		inst := Inst{
    95  			Op:   f.op,
    96  			Args: args,
    97  			Enc:  x,
    98  			Len:  length,
    99  		}
   100  		return inst, nil
   101  	}
   102  	return Inst{}, errUnknown
   103  }
   104  
   105  // decodeArg decodes the arg described by aop from the instruction bits x.
   106  // It returns nil if x cannot be decoded according to aop.
   107  func decodeArg(aop argType, x uint32, index int) Arg {
   108  	switch aop {
   109  	case arg_rd:
   110  		return X0 + Reg((x>>7)&((1<<5)-1))
   111  
   112  	case arg_rs1:
   113  		return X0 + Reg((x>>15)&((1<<5)-1))
   114  
   115  	case arg_rs2:
   116  		return X0 + Reg((x>>20)&((1<<5)-1))
   117  
   118  	case arg_rs3:
   119  		return X0 + Reg((x>>27)&((1<<5)-1))
   120  
   121  	case arg_fd:
   122  		return F0 + Reg((x>>7)&((1<<5)-1))
   123  
   124  	case arg_fs1:
   125  		return F0 + Reg((x>>15)&((1<<5)-1))
   126  
   127  	case arg_fs2:
   128  		return F0 + Reg((x>>20)&((1<<5)-1))
   129  
   130  	case arg_fs3:
   131  		return F0 + Reg((x>>27)&((1<<5)-1))
   132  
   133  	case arg_vd:
   134  		return V0 + Reg((x>>7)&((1<<5)-1))
   135  
   136  	case arg_vm:
   137  		if x&(1<<25) == 0 {
   138  			return V0
   139  		} else {
   140  			return nil
   141  		}
   142  
   143  	case arg_vs1:
   144  		return V0 + Reg((x>>15)&((1<<5)-1))
   145  
   146  	case arg_vs2:
   147  		return V0 + Reg((x>>20)&((1<<5)-1))
   148  
   149  	case arg_vs3:
   150  		return V0 + Reg((x>>7)&((1<<5)-1))
   151  
   152  	case arg_rs1_ptr:
   153  		return RegPtr{X0 + Reg((x>>15)&((1<<5)-1))}
   154  
   155  	case arg_rs1_mem:
   156  		imm := x >> 20
   157  		// Sign-extend
   158  		if imm>>uint32(12-1) == 1 {
   159  			imm |= 0xfffff << 12
   160  		}
   161  		return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}}
   162  
   163  	case arg_rs1_store:
   164  		imm := (x<<20)>>27 | (x>>25)<<5
   165  		// Sign-extend
   166  		if imm>>uint32(12-1) == 1 {
   167  			imm |= 0xfffff << 12
   168  		}
   169  		return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}}
   170  
   171  	case arg_pred:
   172  		imm := x << 4 >> 28
   173  		return MemOrder(uint8(imm))
   174  
   175  	case arg_succ:
   176  		imm := x << 8 >> 28
   177  		return MemOrder(uint8(imm))
   178  
   179  	case arg_csr:
   180  		imm := x >> 20
   181  		return CSR(imm)
   182  
   183  	case arg_zimm:
   184  		imm := x << 12 >> 27
   185  		return Uimm{imm, true}
   186  
   187  	case arg_shamt5:
   188  		imm := x << 7 >> 27
   189  		return Uimm{imm, false}
   190  
   191  	case arg_shamt6:
   192  		imm := x << 6 >> 26
   193  		return Uimm{imm, false}
   194  
   195  	case arg_imm12:
   196  		imm := x >> 20
   197  		// Sign-extend
   198  		if imm>>uint32(12-1) == 1 {
   199  			imm |= 0xfffff << 12
   200  		}
   201  		return Simm{int32(imm), true, 12}
   202  
   203  	case arg_imm20:
   204  		imm := x >> 12
   205  		return Uimm{imm, false}
   206  
   207  	case arg_jimm20:
   208  		imm := (x>>31)<<20 | (x<<1)>>22<<1 | (x<<11)>>31<<11 | (x<<12)>>24<<12
   209  		// Sign-extend
   210  		if imm>>uint32(21-1) == 1 {
   211  			imm |= 0x7ff << 21
   212  		}
   213  		return Simm{int32(imm), true, 21}
   214  
   215  	case arg_simm12:
   216  		imm := (x<<20)>>27 | (x>>25)<<5
   217  		// Sign-extend
   218  		if imm>>uint32(12-1) == 1 {
   219  			imm |= 0xfffff << 12
   220  		}
   221  		return Simm{int32(imm), true, 12}
   222  
   223  	case arg_bimm12:
   224  		imm := (x<<20)>>28<<1 | (x<<1)>>26<<5 | (x<<24)>>31<<11 | (x>>31)<<12
   225  		// Sign-extend
   226  		if imm>>uint32(13-1) == 1 {
   227  			imm |= 0x7ffff << 13
   228  		}
   229  		return Simm{int32(imm), true, 13}
   230  
   231  	case arg_simm5:
   232  		imm := x << 12 >> 27
   233  		// Sign-extend
   234  		if imm>>uint32(5-1) == 1 {
   235  			imm |= 0x7ffffff << 5
   236  		}
   237  		return Simm{int32(imm), true, 5}
   238  
   239  	case arg_zimm5:
   240  		imm := x << 12 >> 27
   241  		return Uimm{imm, true}
   242  
   243  	case arg_vtype_zimm10:
   244  		imm := x << 2 >> 22
   245  		return VType(imm)
   246  
   247  	case arg_vtype_zimm11:
   248  		imm := x << 1 >> 21
   249  		return VType(imm)
   250  
   251  	case arg_rd_p, arg_rs2_p:
   252  		return X8 + Reg((x>>2)&((1<<3)-1))
   253  
   254  	case arg_fd_p, arg_fs2_p:
   255  		return F8 + Reg((x>>2)&((1<<3)-1))
   256  
   257  	case arg_rs1_p, arg_rd_rs1_p:
   258  		return X8 + Reg((x>>7)&((1<<3)-1))
   259  
   260  	case arg_rd_n0, arg_rs1_n0, arg_rd_rs1_n0, arg_c_rs1_n0:
   261  		if X0+Reg((x>>7)&((1<<5)-1)) == X0 {
   262  			return nil
   263  		}
   264  		return X0 + Reg((x>>7)&((1<<5)-1))
   265  
   266  	case arg_c_rs2_n0:
   267  		if X0+Reg((x>>2)&((1<<5)-1)) == X0 {
   268  			return nil
   269  		}
   270  		return X0 + Reg((x>>2)&((1<<5)-1))
   271  
   272  	case arg_c_fs2:
   273  		return F0 + Reg((x>>2)&((1<<5)-1))
   274  
   275  	case arg_c_rs2:
   276  		return X0 + Reg((x>>2)&((1<<5)-1))
   277  
   278  	case arg_rd_n2:
   279  		if X0+Reg((x>>7)&((1<<5)-1)) == X0 || X0+Reg((x>>7)&((1<<5)-1)) == X2 {
   280  			return nil
   281  		}
   282  		return X0 + Reg((x>>7)&((1<<5)-1))
   283  
   284  	case arg_c_imm6:
   285  		imm := (x<<25)>>27 | (x<<19)>>31<<5
   286  		// Sign-extend
   287  		if imm>>uint32(6-1) == 1 {
   288  			imm |= 0x3ffffff << 6
   289  		}
   290  		return Simm{int32(imm), true, 6}
   291  
   292  	case arg_c_nzimm6:
   293  		imm := (x<<25)>>27 | (x<<19)>>31<<5
   294  		// Sign-extend
   295  		if imm>>uint32(6-1) == 1 {
   296  			imm |= 0x3ffffff << 6
   297  		}
   298  		if int32(imm) == 0 {
   299  			return nil
   300  		}
   301  		return Simm{int32(imm), true, 6}
   302  
   303  	case arg_c_nzuimm6:
   304  		imm := (x<<25)>>27 | (x<<19)>>31<<5
   305  		if int32(imm) == 0 {
   306  			return nil
   307  		}
   308  		return Uimm{imm, false}
   309  
   310  	case arg_c_uimm7:
   311  		imm := (x<<26)>>31<<6 | (x<<25)>>31<<2 | (x<<19)>>29<<3
   312  		return Uimm{imm, false}
   313  
   314  	case arg_c_uimm8:
   315  		imm := (x<<25)>>30<<6 | (x<<19)>>29<<3
   316  		return Uimm{imm, false}
   317  
   318  	case arg_c_uimm8sp_s:
   319  		imm := (x<<23)>>30<<6 | (x<<19)>>28<<2
   320  		return Uimm{imm, false}
   321  
   322  	case arg_c_uimm8sp:
   323  		imm := (x<<25)>>29<<2 | (x<<19)>>31<<5 | (x<<28)>>30<<6
   324  		return Uimm{imm, false}
   325  
   326  	case arg_c_uimm9sp_s:
   327  		imm := (x<<22)>>29<<6 | (x<<19)>>29<<3
   328  		return Uimm{imm, false}
   329  
   330  	case arg_c_uimm9sp:
   331  		imm := (x<<25)>>30<<3 | (x<<19)>>31<<5 | (x<<27)>>29<<6
   332  		return Uimm{imm, false}
   333  
   334  	case arg_c_bimm9:
   335  		imm := (x<<29)>>31<<5 | (x<<27)>>30<<1 | (x<<25)>>30<<6 | (x<<19)>>31<<8 | (x<<20)>>30<<3
   336  		// Sign-extend
   337  		if imm>>uint32(9-1) == 1 {
   338  			imm |= 0x7fffff << 9
   339  		}
   340  		return Simm{int32(imm), true, 9}
   341  
   342  	case arg_c_nzimm10:
   343  		imm := (x<<29)>>31<<5 | (x<<27)>>30<<7 | (x<<26)>>31<<6 | (x<<25)>>31<<4 | (x<<19)>>31<<9
   344  		// Sign-extend
   345  		if imm>>uint32(10-1) == 1 {
   346  			imm |= 0x3fffff << 10
   347  		}
   348  		if int32(imm) == 0 {
   349  			return nil
   350  		}
   351  		return Simm{int32(imm), true, 10}
   352  
   353  	case arg_c_nzuimm10:
   354  		imm := (x<<26)>>31<<3 | (x<<25)>>31<<2 | (x<<21)>>28<<6 | (x<<19)>>30<<4
   355  		if int32(imm) == 0 {
   356  			return nil
   357  		}
   358  		return Uimm{imm, false}
   359  
   360  	case arg_c_imm12:
   361  		imm := (x<<29)>>31<<5 | (x<<26)>>29<<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
   362  		// Sign-extend
   363  		if imm>>uint32(12-1) == 1 {
   364  			imm |= 0xfffff << 12
   365  		}
   366  		return Simm{int32(imm), true, 12}
   367  
   368  	case arg_c_nzimm18:
   369  		imm := (x<<25)>>27<<12 | (x<<19)>>31<<17
   370  		// Sign-extend
   371  		if imm>>uint32(18-1) == 1 {
   372  			imm |= 0x3fff << 18
   373  		}
   374  		if int32(imm) == 0 {
   375  			return nil
   376  		}
   377  		return Simm{int32(imm), true, 18}
   378  
   379  	default:
   380  		return nil
   381  	}
   382  }
   383  
   384  // convertCompressedIns rewrites the RVC Instruction to regular Instructions
   385  func convertCompressedIns(f *instFormat, args Args) Args {
   386  	var newargs Args
   387  	switch f.op {
   388  	case C_ADDI4SPN:
   389  		f.op = ADDI
   390  		newargs[0] = args[0]
   391  		newargs[1] = Reg(X2)
   392  		newargs[2] = Simm{int32(args[1].(Uimm).Imm), true, 12}
   393  
   394  	case C_LW:
   395  		f.op = LW
   396  		newargs[0] = args[0]
   397  		newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   398  
   399  	case C_SW:
   400  		f.op = SW
   401  		newargs[0] = args[1]
   402  		newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   403  
   404  	case C_NOP:
   405  		f.op = ADDI
   406  		newargs[0] = X0
   407  		newargs[1] = X0
   408  		newargs[2] = Simm{0, true, 12}
   409  
   410  	case C_ADDI:
   411  		f.op = ADDI
   412  		newargs[0] = args[0]
   413  		newargs[1] = args[0]
   414  		newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
   415  
   416  	case C_LI:
   417  		f.op = ADDI
   418  		newargs[0] = args[0]
   419  		newargs[1] = Reg(X0)
   420  		newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
   421  
   422  	case C_ADDI16SP:
   423  		f.op = ADDI
   424  		newargs[0] = Reg(X2)
   425  		newargs[1] = Reg(X2)
   426  		newargs[2] = Simm{args[0].(Simm).Imm, true, 12}
   427  
   428  	case C_LUI:
   429  		f.op = LUI
   430  		newargs[0] = args[0]
   431  		newargs[1] = Uimm{uint32(args[1].(Simm).Imm >> 12), false}
   432  
   433  	case C_ANDI:
   434  		f.op = ANDI
   435  		newargs[0] = args[0]
   436  		newargs[1] = args[0]
   437  		newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
   438  
   439  	case C_SUB:
   440  		f.op = SUB
   441  		newargs[0] = args[0]
   442  		newargs[1] = args[0]
   443  		newargs[2] = args[1]
   444  
   445  	case C_XOR:
   446  		f.op = XOR
   447  		newargs[0] = args[0]
   448  		newargs[1] = args[0]
   449  		newargs[2] = args[1]
   450  
   451  	case C_OR:
   452  		f.op = OR
   453  		newargs[0] = args[0]
   454  		newargs[1] = args[0]
   455  		newargs[2] = args[1]
   456  
   457  	case C_AND:
   458  		f.op = AND
   459  		newargs[0] = args[0]
   460  		newargs[1] = args[0]
   461  		newargs[2] = args[1]
   462  
   463  	case C_J:
   464  		f.op = JAL
   465  		newargs[0] = Reg(X0)
   466  		newargs[1] = Simm{args[0].(Simm).Imm, true, 21}
   467  
   468  	case C_BEQZ:
   469  		f.op = BEQ
   470  		newargs[0] = args[0]
   471  		newargs[1] = Reg(X0)
   472  		newargs[2] = Simm{args[1].(Simm).Imm, true, 13}
   473  
   474  	case C_BNEZ:
   475  		f.op = BNE
   476  		newargs[0] = args[0]
   477  		newargs[1] = Reg(X0)
   478  		newargs[2] = Simm{args[1].(Simm).Imm, true, 13}
   479  
   480  	case C_LWSP:
   481  		f.op = LW
   482  		newargs[0] = args[0]
   483  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   484  
   485  	case C_JR:
   486  		f.op = JALR
   487  		newargs[0] = Reg(X0)
   488  		newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}}
   489  
   490  	case C_MV:
   491  		f.op = ADD
   492  		newargs[0] = args[0]
   493  		newargs[1] = Reg(X0)
   494  		newargs[2] = args[1]
   495  
   496  	case C_EBREAK:
   497  		f.op = EBREAK
   498  
   499  	case C_JALR:
   500  		f.op = JALR
   501  		newargs[0] = Reg(X1)
   502  		newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}}
   503  
   504  	case C_ADD:
   505  		f.op = ADD
   506  		newargs[0] = args[0]
   507  		newargs[1] = args[0]
   508  		newargs[2] = args[1]
   509  
   510  	case C_SWSP:
   511  		f.op = SW
   512  		newargs[0] = args[0]
   513  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   514  
   515  	// riscv64 compressed instructions
   516  	case C_LD:
   517  		f.op = LD
   518  		newargs[0] = args[0]
   519  		newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   520  
   521  	case C_SD:
   522  		f.op = SD
   523  		newargs[0] = args[1]
   524  		newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   525  
   526  	case C_ADDIW:
   527  		f.op = ADDIW
   528  		newargs[0] = args[0]
   529  		newargs[1] = args[0]
   530  		newargs[2] = Simm{args[1].(Simm).Imm, true, 12}
   531  
   532  	case C_SRLI:
   533  		f.op = SRLI
   534  		newargs[0] = args[0]
   535  		newargs[1] = args[0]
   536  		newargs[2] = args[1]
   537  
   538  	case C_SRAI:
   539  		f.op = SRAI
   540  		newargs[0] = args[0]
   541  		newargs[1] = args[0]
   542  		newargs[2] = args[1]
   543  
   544  	case C_SUBW:
   545  		f.op = SUBW
   546  		newargs[0] = args[0]
   547  		newargs[1] = args[0]
   548  		newargs[2] = args[1]
   549  
   550  	case C_ADDW:
   551  		f.op = ADDW
   552  		newargs[0] = args[0]
   553  		newargs[1] = args[0]
   554  		newargs[2] = args[1]
   555  
   556  	case C_SLLI:
   557  		f.op = SLLI
   558  		newargs[0] = args[0]
   559  		newargs[1] = args[0]
   560  		newargs[2] = args[1]
   561  
   562  	case C_LDSP:
   563  		f.op = LD
   564  		newargs[0] = args[0]
   565  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   566  
   567  	case C_SDSP:
   568  		f.op = SD
   569  		newargs[0] = args[0]
   570  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   571  
   572  	// riscv double precision floating point compressed instructions
   573  	case C_FLD:
   574  		f.op = FLD
   575  		newargs[0] = args[0]
   576  		newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   577  
   578  	case C_FSD:
   579  		f.op = FSD
   580  		newargs[0] = args[1]
   581  		newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}}
   582  
   583  	case C_FLDSP:
   584  		f.op = FLD
   585  		newargs[0] = args[0]
   586  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   587  
   588  	case C_FSDSP:
   589  		f.op = FSD
   590  		newargs[0] = args[0]
   591  		newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}}
   592  
   593  	case C_UNIMP:
   594  		f.op = CSRRW
   595  		newargs[0] = Reg(X0)
   596  		newargs[1] = CSR(CYCLE)
   597  		newargs[2] = Reg(X0)
   598  	}
   599  	return newargs
   600  }
   601  
   602  func validEncoding(op Op, x uint32) bool {
   603  	switch op {
   604  	// The AMOCAS_Q requires the first register in the pair to be even numbered;
   605  	// encodings with odd numbered registers specified in rs2 and rd are reserved.
   606  	case AMOCAS_Q, AMOCAS_Q_AQ, AMOCAS_Q_AQRL, AMOCAS_Q_RL:
   607  		rd := (x >> 7) & 0x1f
   608  		rs2 := (x >> 20) & 0x1f
   609  		if (rd&1) != 0 || (rs2&1) != 0 {
   610  			return false
   611  		}
   612  	}
   613  	return true
   614  }
   615  

View as plain text