345 lines
4.2 KiB
Go
345 lines
4.2 KiB
Go
// 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
|
|
Len int // Length of encoding in bytes.
|
|
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 4 arguments,
|
|
// the final elements in the array are nil.
|
|
type Args [5]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
|
|
)
|
|
|
|
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))
|
|
default:
|
|
return fmt.Sprintf("Reg(%d)", int(r))
|
|
}
|
|
}
|
|
|
|
// CondReg is a bit or field in the conditon 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 int32
|
|
|
|
func (Imm) IsArg() {}
|
|
func (i Imm) String() string {
|
|
return fmt.Sprintf("%d", int32(i))
|
|
}
|
|
|
|
// Offset represents a memory offset immediate.
|
|
type Offset int32
|
|
|
|
func (Offset) IsArg() {}
|
|
func (o Offset) String() string {
|
|
return fmt.Sprintf("%+d", int32(o))
|
|
}
|