github.com/bir3/gocompiler@v0.9.2202/src/xvendor/golang.org/x/arch/arm/armasm/inst.go (about)

     1  // Copyright 2014 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 armasm
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  )
    11  
    12  // A Mode is an instruction execution mode.
    13  type Mode int
    14  
    15  const (
    16  	_ Mode = iota
    17  	ModeARM
    18  	ModeThumb
    19  )
    20  
    21  func (m Mode) String() string {
    22  	switch m {
    23  	case ModeARM:
    24  		return "ARM"
    25  	case ModeThumb:
    26  		return "Thumb"
    27  	}
    28  	return fmt.Sprintf("Mode(%d)", int(m))
    29  }
    30  
    31  // An Op is an ARM opcode.
    32  type Op uint16
    33  
    34  // NOTE: The actual Op values are defined in tables.go.
    35  // They are chosen to simplify instruction decoding and
    36  // are not a dense packing from 0 to N, although the
    37  // density is high, probably at least 90%.
    38  
    39  func (op Op) String() string {
    40  	if op >= Op(len(opstr)) || opstr[op] == "" {
    41  		return fmt.Sprintf("Op(%d)", int(op))
    42  	}
    43  	return opstr[op]
    44  }
    45  
    46  // An Inst is a single instruction.
    47  type Inst struct {
    48  	Op   Op     // Opcode mnemonic
    49  	Enc  uint32 // Raw encoding bits.
    50  	Len  int    // Length of encoding in bytes.
    51  	Args Args   // Instruction arguments, in ARM manual order.
    52  }
    53  
    54  func (i Inst) String() string {
    55  	var buf bytes.Buffer
    56  	buf.WriteString(i.Op.String())
    57  	for j, arg := range i.Args {
    58  		if arg == nil {
    59  			break
    60  		}
    61  		if j == 0 {
    62  			buf.WriteString(" ")
    63  		} else {
    64  			buf.WriteString(", ")
    65  		}
    66  		buf.WriteString(arg.String())
    67  	}
    68  	return buf.String()
    69  }
    70  
    71  // An Args holds the instruction arguments.
    72  // If an instruction has fewer than 4 arguments,
    73  // the final elements in the array are nil.
    74  type Args [4]Arg
    75  
    76  // An Arg is a single instruction argument, one of these types:
    77  // Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
    78  type Arg interface {
    79  	IsArg()
    80  	String() string
    81  }
    82  
    83  type Float32Imm float32
    84  
    85  func (Float32Imm) IsArg() {}
    86  
    87  func (f Float32Imm) String() string {
    88  	return fmt.Sprintf("#%v", float32(f))
    89  }
    90  
    91  type Float64Imm float32
    92  
    93  func (Float64Imm) IsArg() {}
    94  
    95  func (f Float64Imm) String() string {
    96  	return fmt.Sprintf("#%v", float64(f))
    97  }
    98  
    99  // An Imm is an integer constant.
   100  type Imm uint32
   101  
   102  func (Imm) IsArg() {}
   103  
   104  func (i Imm) String() string {
   105  	return fmt.Sprintf("#%#x", uint32(i))
   106  }
   107  
   108  // An ImmAlt is an alternate encoding of an integer constant.
   109  type ImmAlt struct {
   110  	Val uint8
   111  	Rot uint8
   112  }
   113  
   114  func (ImmAlt) IsArg() {}
   115  
   116  func (i ImmAlt) Imm() Imm {
   117  	v := uint32(i.Val)
   118  	r := uint(i.Rot)
   119  	return Imm(v>>r | v<<(32-r))
   120  }
   121  
   122  func (i ImmAlt) String() string {
   123  	return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
   124  }
   125  
   126  // A Label is a text (code) address.
   127  type Label uint32
   128  
   129  func (Label) IsArg() {}
   130  
   131  func (i Label) String() string {
   132  	return fmt.Sprintf("%#x", uint32(i))
   133  }
   134  
   135  // A Reg is a single register.
   136  // The zero value denotes R0, not the absence of a register.
   137  type Reg uint8
   138  
   139  const (
   140  	R0 Reg = iota
   141  	R1
   142  	R2
   143  	R3
   144  	R4
   145  	R5
   146  	R6
   147  	R7
   148  	R8
   149  	R9
   150  	R10
   151  	R11
   152  	R12
   153  	R13
   154  	R14
   155  	R15
   156  
   157  	S0
   158  	S1
   159  	S2
   160  	S3
   161  	S4
   162  	S5
   163  	S6
   164  	S7
   165  	S8
   166  	S9
   167  	S10
   168  	S11
   169  	S12
   170  	S13
   171  	S14
   172  	S15
   173  	S16
   174  	S17
   175  	S18
   176  	S19
   177  	S20
   178  	S21
   179  	S22
   180  	S23
   181  	S24
   182  	S25
   183  	S26
   184  	S27
   185  	S28
   186  	S29
   187  	S30
   188  	S31
   189  
   190  	D0
   191  	D1
   192  	D2
   193  	D3
   194  	D4
   195  	D5
   196  	D6
   197  	D7
   198  	D8
   199  	D9
   200  	D10
   201  	D11
   202  	D12
   203  	D13
   204  	D14
   205  	D15
   206  	D16
   207  	D17
   208  	D18
   209  	D19
   210  	D20
   211  	D21
   212  	D22
   213  	D23
   214  	D24
   215  	D25
   216  	D26
   217  	D27
   218  	D28
   219  	D29
   220  	D30
   221  	D31
   222  
   223  	APSR
   224  	APSR_nzcv
   225  	FPSCR
   226  
   227  	SP = R13
   228  	LR = R14
   229  	PC = R15
   230  )
   231  
   232  func (Reg) IsArg() {}
   233  
   234  func (r Reg) String() string {
   235  	switch r {
   236  	case APSR:
   237  		return "APSR"
   238  	case APSR_nzcv:
   239  		return "APSR_nzcv"
   240  	case FPSCR:
   241  		return "FPSCR"
   242  	case SP:
   243  		return "SP"
   244  	case PC:
   245  		return "PC"
   246  	case LR:
   247  		return "LR"
   248  	}
   249  	if R0 <= r && r <= R15 {
   250  		return fmt.Sprintf("R%d", int(r-R0))
   251  	}
   252  	if S0 <= r && r <= S31 {
   253  		return fmt.Sprintf("S%d", int(r-S0))
   254  	}
   255  	if D0 <= r && r <= D31 {
   256  		return fmt.Sprintf("D%d", int(r-D0))
   257  	}
   258  	return fmt.Sprintf("Reg(%d)", int(r))
   259  }
   260  
   261  // A RegX represents a fraction of a multi-value register.
   262  // The Index field specifies the index number,
   263  // but the size of the fraction is not specified.
   264  // It must be inferred from the instruction and the register type.
   265  // For example, in a VMOV instruction, RegX{D5, 1} represents
   266  // the top 32 bits of the 64-bit D5 register.
   267  type RegX struct {
   268  	Reg   Reg
   269  	Index int
   270  }
   271  
   272  func (RegX) IsArg() {}
   273  
   274  func (r RegX) String() string {
   275  	return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
   276  }
   277  
   278  // A RegList is a register list.
   279  // Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
   280  type RegList uint16
   281  
   282  func (RegList) IsArg() {}
   283  
   284  func (r RegList) String() string {
   285  	var buf bytes.Buffer
   286  	fmt.Fprintf(&buf, "{")
   287  	sep := ""
   288  	for i := 0; i < 16; i++ {
   289  		if r&(1<<uint(i)) != 0 {
   290  			fmt.Fprintf(&buf, "%s%s", sep, Reg(i).String())
   291  			sep = ","
   292  		}
   293  	}
   294  	fmt.Fprintf(&buf, "}")
   295  	return buf.String()
   296  }
   297  
   298  // An Endian is the argument to the SETEND instruction.
   299  type Endian uint8
   300  
   301  const (
   302  	LittleEndian Endian = 0
   303  	BigEndian    Endian = 1
   304  )
   305  
   306  func (Endian) IsArg() {}
   307  
   308  func (e Endian) String() string {
   309  	if e != 0 {
   310  		return "BE"
   311  	}
   312  	return "LE"
   313  }
   314  
   315  // A Shift describes an ARM shift operation.
   316  type Shift uint8
   317  
   318  const (
   319  	ShiftLeft        Shift = 0 // left shift
   320  	ShiftRight       Shift = 1 // logical (unsigned) right shift
   321  	ShiftRightSigned Shift = 2 // arithmetic (signed) right shift
   322  	RotateRight      Shift = 3 // right rotate
   323  	RotateRightExt   Shift = 4 // right rotate through carry (Count will always be 1)
   324  )
   325  
   326  var shiftName = [...]string{
   327  	"LSL", "LSR", "ASR", "ROR", "RRX",
   328  }
   329  
   330  func (s Shift) String() string {
   331  	if s < 5 {
   332  		return shiftName[s]
   333  	}
   334  	return fmt.Sprintf("Shift(%d)", int(s))
   335  }
   336  
   337  // A RegShift is a register shifted by a constant.
   338  type RegShift struct {
   339  	Reg   Reg
   340  	Shift Shift
   341  	Count uint8
   342  }
   343  
   344  func (RegShift) IsArg() {}
   345  
   346  func (r RegShift) String() string {
   347  	return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
   348  }
   349  
   350  // A RegShiftReg is a register shifted by a register.
   351  type RegShiftReg struct {
   352  	Reg      Reg
   353  	Shift    Shift
   354  	RegCount Reg
   355  }
   356  
   357  func (RegShiftReg) IsArg() {}
   358  
   359  func (r RegShiftReg) String() string {
   360  	return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
   361  }
   362  
   363  // A PCRel describes a memory address (usually a code label)
   364  // as a distance relative to the program counter.
   365  // TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
   366  type PCRel int32
   367  
   368  func (PCRel) IsArg() {}
   369  
   370  func (r PCRel) String() string {
   371  	return fmt.Sprintf("PC%+#x", int32(r))
   372  }
   373  
   374  // An AddrMode is an ARM addressing mode.
   375  type AddrMode uint8
   376  
   377  const (
   378  	_             AddrMode = iota
   379  	AddrPostIndex          // [R], X – use address R, set R = R + X
   380  	AddrPreIndex           // [R, X]! – use address R + X, set R = R + X
   381  	AddrOffset             // [R, X] – use address R + X
   382  	AddrLDM                // R – [R] but formats as R, for LDM/STM only
   383  	AddrLDM_WB             // R! - [R], X where X is instruction-specific amount, for LDM/STM only
   384  )
   385  
   386  // A Mem is a memory reference made up of a base R and index expression X.
   387  // The effective memory address is R or R+X depending on AddrMode.
   388  // The index expression is X = Sign*(Index Shift Count) + Offset,
   389  // but in any instruction either Sign = 0 or Offset = 0.
   390  type Mem struct {
   391  	Base   Reg
   392  	Mode   AddrMode
   393  	Sign   int8
   394  	Index  Reg
   395  	Shift  Shift
   396  	Count  uint8
   397  	Offset int16
   398  }
   399  
   400  func (Mem) IsArg() {}
   401  
   402  func (m Mem) String() string {
   403  	R := m.Base.String()
   404  	X := ""
   405  	if m.Sign != 0 {
   406  		X = "+"
   407  		if m.Sign < 0 {
   408  			X = "-"
   409  		}
   410  		X += m.Index.String()
   411  		if m.Shift != ShiftLeft || m.Count != 0 {
   412  			X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
   413  		}
   414  	} else {
   415  		X = fmt.Sprintf("#%d", m.Offset)
   416  	}
   417  
   418  	switch m.Mode {
   419  	case AddrOffset:
   420  		if X == "#0" {
   421  			return fmt.Sprintf("[%s]", R)
   422  		}
   423  		return fmt.Sprintf("[%s, %s]", R, X)
   424  	case AddrPreIndex:
   425  		return fmt.Sprintf("[%s, %s]!", R, X)
   426  	case AddrPostIndex:
   427  		return fmt.Sprintf("[%s], %s", R, X)
   428  	case AddrLDM:
   429  		if X == "#0" {
   430  			return R
   431  		}
   432  	case AddrLDM_WB:
   433  		if X == "#0" {
   434  			return R + "!"
   435  		}
   436  	}
   437  	return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
   438  }