| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package ppc64asm |
| |
| import ( |
| "bytes" |
| "fmt" |
| ) |
| |
| type Inst struct { |
| Op Op // Opcode mnemonic |
| Enc uint32 // Raw encoding bits (if Len == 8, this is the prefix word) |
| Len int // Length of encoding in bytes. |
| SuffixEnc uint32 // Raw encoding bits of second word (if Len == 8) |
| Args Args // Instruction arguments, in Power ISA manual order. |
| } |
| |
| func (i Inst) String() string { |
| var buf bytes.Buffer |
| buf.WriteString(i.Op.String()) |
| for j, arg := range i.Args { |
| if arg == nil { |
| break |
| } |
| if j == 0 { |
| buf.WriteString(" ") |
| } else { |
| buf.WriteString(", ") |
| } |
| buf.WriteString(arg.String()) |
| } |
| return buf.String() |
| } |
| |
| // An Op is an instruction operation. |
| type Op uint16 |
| |
| func (o Op) String() string { |
| if int(o) >= len(opstr) || opstr[o] == "" { |
| return fmt.Sprintf("Op(%d)", int(o)) |
| } |
| return opstr[o] |
| } |
| |
| // An Arg is a single instruction argument, one of these types: Reg, CondReg, SpReg, Imm, PCRel, Label, or Offset. |
| type Arg interface { |
| IsArg() |
| String() string |
| } |
| |
| // An Args holds the instruction arguments. |
| // If an instruction has fewer than 6 arguments, |
| // the final elements in the array are nil. |
| type Args [6]Arg |
| |
| // A Reg is a single register. The zero value means R0, not the absence of a register. |
| // It also includes special registers. |
| type Reg uint16 |
| |
| const ( |
| _ Reg = iota |
| R0 |
| R1 |
| R2 |
| R3 |
| R4 |
| R5 |
| R6 |
| R7 |
| R8 |
| R9 |
| R10 |
| R11 |
| R12 |
| R13 |
| R14 |
| R15 |
| R16 |
| R17 |
| R18 |
| R19 |
| R20 |
| R21 |
| R22 |
| R23 |
| R24 |
| R25 |
| R26 |
| R27 |
| R28 |
| R29 |
| R30 |
| R31 |
| F0 |
| F1 |
| F2 |
| F3 |
| F4 |
| F5 |
| F6 |
| F7 |
| F8 |
| F9 |
| F10 |
| F11 |
| F12 |
| F13 |
| F14 |
| F15 |
| F16 |
| F17 |
| F18 |
| F19 |
| F20 |
| F21 |
| F22 |
| F23 |
| F24 |
| F25 |
| F26 |
| F27 |
| F28 |
| F29 |
| F30 |
| F31 |
| V0 // VSX extension, F0 is V0[0:63]. |
| V1 |
| V2 |
| V3 |
| V4 |
| V5 |
| V6 |
| V7 |
| V8 |
| V9 |
| V10 |
| V11 |
| V12 |
| V13 |
| V14 |
| V15 |
| V16 |
| V17 |
| V18 |
| V19 |
| V20 |
| V21 |
| V22 |
| V23 |
| V24 |
| V25 |
| V26 |
| V27 |
| V28 |
| V29 |
| V30 |
| V31 |
| VS0 |
| VS1 |
| VS2 |
| VS3 |
| VS4 |
| VS5 |
| VS6 |
| VS7 |
| VS8 |
| VS9 |
| VS10 |
| VS11 |
| VS12 |
| VS13 |
| VS14 |
| VS15 |
| VS16 |
| VS17 |
| VS18 |
| VS19 |
| VS20 |
| VS21 |
| VS22 |
| VS23 |
| VS24 |
| VS25 |
| VS26 |
| VS27 |
| VS28 |
| VS29 |
| VS30 |
| VS31 |
| VS32 |
| VS33 |
| VS34 |
| VS35 |
| VS36 |
| VS37 |
| VS38 |
| VS39 |
| VS40 |
| VS41 |
| VS42 |
| VS43 |
| VS44 |
| VS45 |
| VS46 |
| VS47 |
| VS48 |
| VS49 |
| VS50 |
| VS51 |
| VS52 |
| VS53 |
| VS54 |
| VS55 |
| VS56 |
| VS57 |
| VS58 |
| VS59 |
| VS60 |
| VS61 |
| VS62 |
| VS63 |
| A0 // MMA registers. These are effectively shadow registers of four adjacent VSR's [An*4,An*4+3] |
| A1 |
| A2 |
| A3 |
| A4 |
| A5 |
| A6 |
| A7 |
| ) |
| |
| func (Reg) IsArg() {} |
| func (r Reg) String() string { |
| switch { |
| case R0 <= r && r <= R31: |
| return fmt.Sprintf("r%d", int(r-R0)) |
| case F0 <= r && r <= F31: |
| return fmt.Sprintf("f%d", int(r-F0)) |
| case V0 <= r && r <= V31: |
| return fmt.Sprintf("v%d", int(r-V0)) |
| case VS0 <= r && r <= VS63: |
| return fmt.Sprintf("vs%d", int(r-VS0)) |
| case A0 <= r && r <= A7: |
| return fmt.Sprintf("a%d", int(r-A0)) |
| default: |
| return fmt.Sprintf("Reg(%d)", int(r)) |
| } |
| } |
| |
| // CondReg is a bit or field in the condition register. |
| type CondReg int8 |
| |
| const ( |
| _ CondReg = iota |
| // Condition Regster bits |
| Cond0LT |
| Cond0GT |
| Cond0EQ |
| Cond0SO |
| Cond1LT |
| Cond1GT |
| Cond1EQ |
| Cond1SO |
| Cond2LT |
| Cond2GT |
| Cond2EQ |
| Cond2SO |
| Cond3LT |
| Cond3GT |
| Cond3EQ |
| Cond3SO |
| Cond4LT |
| Cond4GT |
| Cond4EQ |
| Cond4SO |
| Cond5LT |
| Cond5GT |
| Cond5EQ |
| Cond5SO |
| Cond6LT |
| Cond6GT |
| Cond6EQ |
| Cond6SO |
| Cond7LT |
| Cond7GT |
| Cond7EQ |
| Cond7SO |
| // Condition Register Fields |
| CR0 |
| CR1 |
| CR2 |
| CR3 |
| CR4 |
| CR5 |
| CR6 |
| CR7 |
| ) |
| |
| func (CondReg) IsArg() {} |
| func (c CondReg) String() string { |
| switch { |
| default: |
| return fmt.Sprintf("CondReg(%d)", int(c)) |
| case c >= CR0: |
| return fmt.Sprintf("CR%d", int(c-CR0)) |
| case c >= Cond0LT && c < CR0: |
| return fmt.Sprintf("Cond%d%s", int((c-Cond0LT)/4), [4]string{"LT", "GT", "EQ", "SO"}[(c-Cond0LT)%4]) |
| } |
| } |
| |
| // SpReg is a special register, its meaning depends on Op. |
| type SpReg uint16 |
| |
| const ( |
| SpRegZero SpReg = 0 |
| ) |
| |
| func (SpReg) IsArg() {} |
| func (s SpReg) String() string { |
| return fmt.Sprintf("SpReg(%d)", int(s)) |
| } |
| |
| // PCRel is a PC-relative offset, used only in branch instructions. |
| type PCRel int32 |
| |
| func (PCRel) IsArg() {} |
| func (r PCRel) String() string { |
| return fmt.Sprintf("PC%+#x", int32(r)) |
| } |
| |
| // A Label is a code (text) address, used only in absolute branch instructions. |
| type Label uint32 |
| |
| func (Label) IsArg() {} |
| func (l Label) String() string { |
| return fmt.Sprintf("%#x", uint32(l)) |
| } |
| |
| // Imm represents an immediate number. |
| type Imm int64 |
| |
| func (Imm) IsArg() {} |
| func (i Imm) String() string { |
| return fmt.Sprintf("%d", int32(i)) |
| } |
| |
| // Offset represents a memory offset immediate. |
| type Offset int64 |
| |
| func (Offset) IsArg() {} |
| func (o Offset) String() string { |
| return fmt.Sprintf("%+d", int32(o)) |
| } |