golang.org/x/arch@v0.17.0/s390x/s390xasm/inst.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 s390xasm 6 7 import ( 8 "bytes" 9 "fmt" 10 "strings" 11 ) 12 13 type Inst struct { 14 Op Op // Opcode mnemonic 15 Enc uint64 // Raw encoding bits 16 Len int // Length of encoding in bytes. 17 Args Args // Instruction arguments, in s390x ISA manual order. 18 } 19 20 func (i Inst) String(pc uint64) string { 21 var buf bytes.Buffer 22 var rxb_check bool 23 m := i.Op.String() 24 if strings.HasPrefix(m, "v") || strings.Contains(m, "wfc") || strings.Contains(m, "wfk") { 25 rxb_check = true 26 } 27 mnemonic := HandleExtndMnemonic(&i) 28 buf.WriteString(fmt.Sprintf("%s", mnemonic)) 29 for j := 0; j < len(i.Args); j++ { 30 if i.Args[j] == nil { 31 break 32 } 33 str := i.Args[j].String(pc) 34 if j == 0 { 35 buf.WriteString(" ") 36 } else { 37 switch i.Args[j].(type) { 38 case VReg: 39 if _, ok := i.Args[j-1].(Disp12); ok { 40 buf.WriteString("(") 41 } else if _, ok := i.Args[j-1].(Disp20); ok { 42 buf.WriteString("(") 43 } else { 44 buf.WriteString(",") 45 } 46 case Reg: 47 if _, ok := i.Args[j-1].(Disp12); ok { 48 if str != "" { 49 buf.WriteString("(") 50 } 51 } else if _, ok := i.Args[j-1].(Disp20); ok { 52 if str != "" { 53 buf.WriteString("(") 54 } 55 } else { 56 buf.WriteString(",") 57 } 58 case Base: 59 if _, ok := i.Args[j-1].(VReg); ok { 60 buf.WriteString(",") 61 } else if _, ok := i.Args[j-1].(Reg); ok { 62 buf.WriteString(",") 63 } else if _, ok := i.Args[j-1].(Disp12); ok { 64 if str != "" { 65 buf.WriteString("(") 66 } 67 } else if _, ok := i.Args[j-1].(Disp20); ok { 68 if str != "" { 69 buf.WriteString("(") 70 } 71 } else if _, ok := i.Args[j-1].(Len); ok { 72 buf.WriteString(",") 73 } else if _, ok := i.Args[j-1].(Index); ok { 74 if ((i.Args[j-1].String(pc)) != "") && str != "" { 75 str = "," + str 76 } else if str == "" { 77 str = ")" 78 } 79 } 80 case Index, Len: 81 if str != "" || (i.Args[j+1].String(pc)) != "" { 82 buf.WriteString("(") 83 } else { 84 j = j + 1 85 } 86 default: 87 buf.WriteString(",") 88 } 89 } 90 buf.WriteString(str) 91 if rxb_check && i.Args[j+2] == nil { 92 break 93 } 94 } 95 return buf.String() 96 } 97 98 // An Op is an instruction operation. 99 type Op uint16 100 101 func (o Op) String() string { 102 if int(o) >= len(opstr) || opstr[o] == "" { 103 return fmt.Sprintf("Op(%d)", int(o)) 104 } 105 return opstr[o] 106 } 107 108 // An Arg is a single instruction argument. 109 // One of these types: Reg, Base, Index, Disp20, Disp12, Len, Mask, Sign8, Sign16, Sign32, RegIm12, RegIm16, RegIm24, RegIm32. 110 type Arg interface { 111 IsArg() 112 String(pc uint64) string 113 } 114 115 // An Args holds the instruction arguments. 116 // If an instruction has fewer than 6 arguments, 117 // the final elements in the array are nil. 118 type Args [8]Arg 119 120 // Base represents an 4-bit Base Register field 121 type Base uint8 122 123 const ( 124 B0 Base = iota 125 B1 126 B2 127 B3 128 B4 129 B5 130 B6 131 B7 132 B8 133 B9 134 B10 135 B11 136 B12 137 B13 138 B14 139 B15 140 ) 141 142 func (Base) IsArg() {} 143 func (r Base) String(pc uint64) string { 144 switch { 145 case B1 <= r && r <= B15: 146 s := "%" 147 return fmt.Sprintf("%sr%d)", s, int(r-B0)) 148 case B0 == r: 149 return fmt.Sprintf("") 150 default: 151 return fmt.Sprintf("Base(%d)", int(r)) 152 } 153 } 154 155 // Index represents an 4-bit Index Register field 156 type Index uint8 157 158 const ( 159 X0 Index = iota 160 X1 161 X2 162 X3 163 X4 164 X5 165 X6 166 X7 167 X8 168 X9 169 X10 170 X11 171 X12 172 X13 173 X14 174 X15 175 ) 176 177 func (Index) IsArg() {} 178 func (r Index) String(pc uint64) string { 179 switch { 180 case X1 <= r && r <= X15: 181 s := "%" 182 return fmt.Sprintf("%sr%d", s, int(r-X0)) 183 case X0 == r: 184 return fmt.Sprintf("") 185 default: 186 return fmt.Sprintf("Base(%d)", int(r)) 187 } 188 } 189 190 // Disp20 represents an 20-bit Unsigned Displacement 191 type Disp20 uint32 192 193 func (Disp20) IsArg() {} 194 func (r Disp20) String(pc uint64) string { 195 if (r>>19)&0x01 == 1 { 196 return fmt.Sprintf("%d", int32(r|0xfff<<20)) 197 } else { 198 return fmt.Sprintf("%d", int32(r)) 199 } 200 } 201 202 // Disp12 represents an 12-bit Unsigned Displacement 203 type Disp12 uint16 204 205 func (Disp12) IsArg() {} 206 func (r Disp12) String(pc uint64) string { 207 return fmt.Sprintf("%d", r) 208 } 209 210 // RegIm12 represents an 12-bit Register immediate number. 211 type RegIm12 uint16 212 213 func (RegIm12) IsArg() {} 214 func (r RegIm12) String(pc uint64) string { 215 if (r>>11)&0x01 == 1 { 216 return fmt.Sprintf("%#x", pc+(2*uint64(int16(r|0xf<<12)))) 217 } else { 218 return fmt.Sprintf("%#x", pc+(2*uint64(int16(r)))) 219 } 220 } 221 222 // RegIm16 represents an 16-bit Register immediate number. 223 type RegIm16 uint16 224 225 func (RegIm16) IsArg() {} 226 func (r RegIm16) String(pc uint64) string { 227 return fmt.Sprintf("%#x", pc+(2*uint64(int16(r)))) 228 } 229 230 // RegIm24 represents an 24-bit Register immediate number. 231 type RegIm24 uint32 232 233 func (RegIm24) IsArg() {} 234 func (r RegIm24) String(pc uint64) string { 235 if (r>>23)&0x01 == 1 { 236 return fmt.Sprintf("%#x", pc+(2*uint64(int32(r|0xff<<24)))) 237 } else { 238 return fmt.Sprintf("%#x", pc+(2*uint64(int32(r)))) 239 } 240 } 241 242 // RegIm32 represents an 32-bit Register immediate number. 243 type RegIm32 uint32 244 245 func (RegIm32) IsArg() {} 246 func (r RegIm32) String(pc uint64) string { 247 return fmt.Sprintf("%#x", pc+(2*uint64(int32(r)))) 248 } 249 250 // A Reg is a single register. The zero value means R0, not the absence of a register. 251 // It also includes special registers. 252 type Reg uint16 253 254 const ( 255 R0 Reg = iota 256 R1 257 R2 258 R3 259 R4 260 R5 261 R6 262 R7 263 R8 264 R9 265 R10 266 R11 267 R12 268 R13 269 R14 270 R15 271 F0 272 F1 273 F2 274 F3 275 F4 276 F5 277 F6 278 F7 279 F8 280 F9 281 F10 282 F11 283 F12 284 F13 285 F14 286 F15 287 A0 288 A1 289 A2 290 A3 291 A4 292 A5 293 A6 294 A7 295 A8 296 A9 297 A10 298 A11 299 A12 300 A13 301 A14 302 A15 303 C0 304 C1 305 C2 306 C3 307 C4 308 C5 309 C6 310 C7 311 C8 312 C9 313 C10 314 C11 315 C12 316 C13 317 C14 318 C15 319 ) 320 321 func (Reg) IsArg() {} 322 func (r Reg) String(pc uint64) string { 323 s := "%" 324 switch { 325 case R0 <= r && r <= R15: 326 return fmt.Sprintf("%sr%d", s, int(r-R0)) 327 case F0 <= r && r <= F15: 328 return fmt.Sprintf("%sf%d", s, int(r-F0)) 329 case A0 <= r && r <= A15: 330 return fmt.Sprintf("%sa%d", s, int(r-A0)) 331 case C0 <= r && r <= C15: 332 return fmt.Sprintf("%sc%d", s, int(r-C0)) 333 default: 334 return fmt.Sprintf("Reg(%d)", int(r)) 335 } 336 } 337 338 // VReg is a vector register. The zero value means V0, not the absence of a register. 339 340 type VReg uint8 341 342 const ( 343 V0 VReg = iota 344 V1 345 V2 346 V3 347 V4 348 V5 349 V6 350 V7 351 V8 352 V9 353 V10 354 V11 355 V12 356 V13 357 V14 358 V15 359 V16 360 V17 361 V18 362 V19 363 V20 364 V21 365 V22 366 V23 367 V24 368 V25 369 V26 370 V27 371 V28 372 V29 373 V30 374 V31 375 ) 376 377 func (VReg) IsArg() {} 378 func (r VReg) String(pc uint64) string { 379 s := "%" 380 if V0 <= r && r <= V31 { 381 return fmt.Sprintf("%sv%d", s, int(r-V0)) 382 } else { 383 return fmt.Sprintf("VReg(%d)", int(r)) 384 } 385 } 386 387 // Imm represents an immediate number. 388 type Imm uint32 389 390 func (Imm) IsArg() {} 391 func (i Imm) String(pc uint64) string { 392 return fmt.Sprintf("%d", uint32(i)) 393 } 394 395 // Sign8 represents an 8-bit signed immediate number. 396 type Sign8 int8 397 398 func (Sign8) IsArg() {} 399 func (i Sign8) String(pc uint64) string { 400 return fmt.Sprintf("%d", i) 401 } 402 403 // Sign16 represents an 16-bit signed immediate number. 404 type Sign16 int16 405 406 func (Sign16) IsArg() {} 407 func (i Sign16) String(pc uint64) string { 408 return fmt.Sprintf("%d", i) 409 } 410 411 // Sign32 represents an 32-bit signed immediate number. 412 type Sign32 int32 413 414 func (Sign32) IsArg() {} 415 func (i Sign32) String(pc uint64) string { 416 return fmt.Sprintf("%d", i) 417 } 418 419 // Mask represents an 4-bit mask value 420 type Mask uint8 421 422 func (Mask) IsArg() {} 423 func (i Mask) String(pc uint64) string { 424 return fmt.Sprintf("%d", i) 425 } 426 427 // Len represents an 8-bit type holds 4/8-bit Len argument 428 type Len uint8 429 430 func (Len) IsArg() {} 431 func (i Len) String(pc uint64) string { 432 return fmt.Sprintf("%d", uint16(i)+1) 433 }