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

View as plain text