Source file src/cmd/vendor/golang.org/x/arch/loong64/loong64asm/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 loong64asm
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  )
    11  
    12  type instArgs [5]instArg
    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 instArgs
    24  }
    25  
    26  var (
    27  	errShort   = fmt.Errorf("truncated instruction")
    28  	errUnknown = fmt.Errorf("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 Inst, err error) {
    39  	if len(src) < 4 {
    40  		return Inst{}, errShort
    41  	}
    42  
    43  	x := binary.LittleEndian.Uint32(src)
    44  
    45  Search:
    46  	for i := range instFormats {
    47  		f := &instFormats[i]
    48  
    49  		if (x & f.mask) != f.value {
    50  			continue
    51  		}
    52  
    53  		// Decode args.
    54  		var args Args
    55  		for j, aop := range f.args {
    56  			if aop == 0 {
    57  				break
    58  			}
    59  
    60  			arg := decodeArg(aop, x, i)
    61  			if arg == nil {
    62  				// Cannot decode argument
    63  				continue Search
    64  			}
    65  
    66  			args[j] = arg
    67  		}
    68  
    69  		decoderCover[i] = true
    70  		inst = Inst{
    71  			Op:   f.op,
    72  			Args: args,
    73  			Enc:  x,
    74  		}
    75  		return inst, nil
    76  	}
    77  
    78  	return Inst{}, errUnknown
    79  }
    80  
    81  // decodeArg decodes the arg described by aop from the instruction bits x.
    82  // It returns nil if x cannot be decoded according to aop.
    83  func decodeArg(aop instArg, x uint32, index int) Arg {
    84  	switch aop {
    85  	case arg_fd:
    86  		return F0 + Reg(x&((1<<5)-1))
    87  
    88  	case arg_fj:
    89  		return F0 + Reg((x>>5)&((1<<5)-1))
    90  
    91  	case arg_fk:
    92  		return F0 + Reg((x>>10)&((1<<5)-1))
    93  
    94  	case arg_fa:
    95  		return F0 + Reg((x>>15)&((1<<5)-1))
    96  
    97  	case arg_rd:
    98  		return R0 + Reg(x&((1<<5)-1))
    99  
   100  	case arg_rj:
   101  		return R0 + Reg((x>>5)&((1<<5)-1))
   102  
   103  	case arg_rk:
   104  		return R0 + Reg((x>>10)&((1<<5)-1))
   105  
   106  	case arg_fcsr_4_0:
   107  		return FCSR0 + Fcsr(x&((1<<5)-1))
   108  
   109  	case arg_fcsr_9_5:
   110  		return FCSR0 + Fcsr((x>>5)&((1<<5)-1))
   111  
   112  	case arg_cd:
   113  		return FCC0 + Fcc(x&((1<<3)-1))
   114  
   115  	case arg_cj:
   116  		return FCC0 + Fcc((x>>5)&((1<<3)-1))
   117  
   118  	case arg_ca:
   119  		return FCC0 + Fcc((x>>15)&((1<<3)-1))
   120  
   121  	case arg_op_4_0:
   122  		tmp := x & ((1 << 5) - 1)
   123  		return Uimm{tmp, false}
   124  
   125  	case arg_csr_23_10:
   126  		tmp := (x >> 10) & ((1 << 14) - 1)
   127  		return Uimm{tmp, false}
   128  
   129  	case arg_sa2_16_15:
   130  		f := &instFormats[index]
   131  		tmp := SaSimm((x >> 15) & ((1 << 2) - 1))
   132  		if (f.op == ALSL_D) || (f.op == ALSL_W) || (f.op == ALSL_WU) {
   133  			return tmp + 1
   134  		} else {
   135  			return tmp + 0
   136  		}
   137  
   138  	case arg_sa3_17_15:
   139  		return SaSimm((x >> 15) & ((1 << 3) - 1))
   140  
   141  	case arg_code_4_0:
   142  		return CodeSimm(x & ((1 << 5) - 1))
   143  
   144  	case arg_code_14_0:
   145  		return CodeSimm(x & ((1 << 15) - 1))
   146  
   147  	case arg_ui5_14_10:
   148  		tmp := (x >> 10) & ((1 << 5) - 1)
   149  		return Uimm{tmp, false}
   150  
   151  	case arg_ui6_15_10:
   152  		tmp := (x >> 10) & ((1 << 6) - 1)
   153  		return Uimm{tmp, false}
   154  
   155  	case arg_ui12_21_10:
   156  		tmp := ((x >> 10) & ((1 << 12) - 1) & 0xfff)
   157  		return Uimm{tmp, false}
   158  
   159  	case arg_lsbw:
   160  		tmp := (x >> 10) & ((1 << 5) - 1)
   161  		return Uimm{tmp, false}
   162  
   163  	case arg_msbw:
   164  		tmp := (x >> 16) & ((1 << 5) - 1)
   165  		return Uimm{tmp, false}
   166  
   167  	case arg_lsbd:
   168  		tmp := (x >> 10) & ((1 << 6) - 1)
   169  		return Uimm{tmp, false}
   170  
   171  	case arg_msbd:
   172  		tmp := (x >> 16) & ((1 << 6) - 1)
   173  		return Uimm{tmp, false}
   174  
   175  	case arg_hint_4_0:
   176  		tmp := x & ((1 << 5) - 1)
   177  		return Uimm{tmp, false}
   178  
   179  	case arg_hint_14_0:
   180  		tmp := x & ((1 << 15) - 1)
   181  		return Uimm{tmp, false}
   182  
   183  	case arg_level_14_0:
   184  		tmp := x & ((1 << 15) - 1)
   185  		return Uimm{tmp, false}
   186  
   187  	case arg_level_17_10:
   188  		tmp := (x >> 10) & ((1 << 8) - 1)
   189  		return Uimm{tmp, false}
   190  
   191  	case arg_seq_17_10:
   192  		tmp := (x >> 10) & ((1 << 8) - 1)
   193  		return Uimm{tmp, false}
   194  
   195  	case arg_si12_21_10:
   196  		var tmp int16
   197  
   198  		// no int12, so sign-extend a 12-bit signed to 16-bit signed
   199  		if (x & 0x200000) == 0x200000 {
   200  			tmp = int16(((x >> 10) & ((1 << 12) - 1)) | 0xf000)
   201  		} else {
   202  			tmp = int16(((x >> 10) & ((1 << 12) - 1)) | 0x0000)
   203  		}
   204  		return Simm16{tmp, 12}
   205  
   206  	case arg_si14_23_10:
   207  		var tmp int32
   208  		if (x & 0x800000) == 0x800000 {
   209  			tmp = int32((((x >> 10) & ((1 << 14) - 1)) << 2) | 0xffff0000)
   210  		} else {
   211  			tmp = int32((((x >> 10) & ((1 << 14) - 1)) << 2) | 0x00000000)
   212  		}
   213  		return Simm32{tmp, 14}
   214  
   215  	case arg_si16_25_10:
   216  		var tmp int32
   217  
   218  		if (x & 0x2000000) == 0x2000000 {
   219  			tmp = int32(((x >> 10) & ((1 << 16) - 1)) | 0xffff0000)
   220  		} else {
   221  			tmp = int32(((x >> 10) & ((1 << 16) - 1)) | 0x00000000)
   222  		}
   223  
   224  		return Simm32{tmp, 16}
   225  
   226  	case arg_si20_24_5:
   227  		var tmp int32
   228  		if (x & 0x1000000) == 0x1000000 {
   229  			tmp = int32(((x >> 5) & ((1 << 20) - 1)) | 0xfff00000)
   230  		} else {
   231  			tmp = int32(((x >> 5) & ((1 << 20) - 1)) | 0x00000000)
   232  		}
   233  		return Simm32{tmp, 20}
   234  
   235  	case arg_offset_20_0:
   236  		var tmp int32
   237  
   238  		if (x & 0x10) == 0x10 {
   239  			tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 21) - 1)) << 2) | 0xff800000)
   240  		} else {
   241  			tmp = int32((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 21) - 1)) << 2)
   242  		}
   243  
   244  		return OffsetSimm{tmp, 21}
   245  
   246  	case arg_offset_15_0:
   247  		var tmp int32
   248  		if (x & 0x2000000) == 0x2000000 {
   249  			tmp = int32((((x >> 10) & ((1 << 16) - 1)) << 2) | 0xfffc0000)
   250  		} else {
   251  			tmp = int32((((x >> 10) & ((1 << 16) - 1)) << 2) | 0x00000000)
   252  		}
   253  
   254  		return OffsetSimm{tmp, 16}
   255  
   256  	case arg_offset_25_0:
   257  		var tmp int32
   258  
   259  		if (x & 0x200) == 0x200 {
   260  			tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 26) - 1)) << 2) | 0xf0000000)
   261  		} else {
   262  			tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 26) - 1)) << 2) | 0x00000000)
   263  		}
   264  
   265  		return OffsetSimm{tmp, 26}
   266  	default:
   267  		return nil
   268  	}
   269  }
   270  

View as plain text