golang.org/x/arch@v0.17.0/loong64/loong64asm/decode.go (about) 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 }