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

View as plain text