...

Source file src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go

     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	}
   439	

View as plain text