Source file src/cmd/vendor/golang.org/x/arch/s390x/s390xasm/inst.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 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  }
   434  

View as plain text