summaryrefslogtreecommitdiff
path: root/vendor/github.com/chenzhuoyu
diff options
context:
space:
mode:
authorLibravatar dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-03-11 10:12:06 +0000
committerLibravatar GitHub <noreply@github.com>2024-03-11 10:12:06 +0000
commite24efcac8b67baa9454bf27631e5e49f898a88d4 (patch)
treed9adec2f05e1d8714edee66062a4b95a81ee2a61 /vendor/github.com/chenzhuoyu
parent[bugfix] Fix whitespace move_id issue (#2742) (diff)
downloadgotosocial-e24efcac8b67baa9454bf27631e5e49f898a88d4.tar.xz
[chore]: Bump github.com/gin-contrib/cors from 1.5.0 to 1.7.0 (#2745)
Diffstat (limited to 'vendor/github.com/chenzhuoyu')
-rw-r--r--vendor/github.com/chenzhuoyu/iasm/x86_64/operands.go733
-rw-r--r--vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go117
-rw-r--r--vendor/github.com/chenzhuoyu/iasm/x86_64/program.go702
3 files changed, 819 insertions, 733 deletions
diff --git a/vendor/github.com/chenzhuoyu/iasm/x86_64/operands.go b/vendor/github.com/chenzhuoyu/iasm/x86_64/operands.go
index 966090225..8c4bc9f65 100644
--- a/vendor/github.com/chenzhuoyu/iasm/x86_64/operands.go
+++ b/vendor/github.com/chenzhuoyu/iasm/x86_64/operands.go
@@ -1,13 +1,13 @@
package x86_64
import (
- `errors`
- `fmt`
- `math`
- `reflect`
- `strconv`
- `strings`
- `sync/atomic`
+ "errors"
+ "fmt"
+ "math"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync/atomic"
)
// RelativeOffset represents an RIP-relative offset.
@@ -15,496 +15,635 @@ type RelativeOffset int32
// String implements the fmt.Stringer interface.
func (self RelativeOffset) String() string {
- if self == 0 {
- return "(%rip)"
- } else {
- return fmt.Sprintf("%d(%%rip)", self)
- }
+ if self == 0 {
+ return "(%rip)"
+ } else {
+ return fmt.Sprintf("%d(%%rip)", self)
+ }
}
// RoundingControl represents a floating-point rounding option.
type RoundingControl uint8
const (
- // RN_SAE represents "Round Nearest", which is the default rounding option.
- RN_SAE RoundingControl = iota
+ // RN_SAE represents "Round Nearest", which is the default rounding option.
+ RN_SAE RoundingControl = iota
- // RD_SAE represents "Round Down".
- RD_SAE
+ // RD_SAE represents "Round Down".
+ RD_SAE
- // RU_SAE represents "Round Up".
- RU_SAE
+ // RU_SAE represents "Round Up".
+ RU_SAE
- // RZ_SAE represents "Round towards Zero".
- RZ_SAE
+ // RZ_SAE represents "Round towards Zero".
+ RZ_SAE
)
-var _RC_NAMES = map[RoundingControl]string {
- RN_SAE: "rn-sae",
- RD_SAE: "rd-sae",
- RU_SAE: "ru-sae",
- RZ_SAE: "rz-sae",
+var _RC_NAMES = map[RoundingControl]string{
+ RN_SAE: "rn-sae",
+ RD_SAE: "rd-sae",
+ RU_SAE: "ru-sae",
+ RZ_SAE: "rz-sae",
}
func (self RoundingControl) String() string {
- if v, ok := _RC_NAMES[self]; ok {
- return v
- } else {
- panic("invalid RoundingControl value")
- }
+ if v, ok := _RC_NAMES[self]; ok {
+ return v
+ } else {
+ panic("invalid RoundingControl value")
+ }
}
// ExceptionControl represents the "Suppress All Exceptions" flag.
type ExceptionControl uint8
const (
- // SAE represents the flag "Suppress All Exceptions" for floating point operations.
- SAE ExceptionControl = iota
+ // SAE represents the flag "Suppress All Exceptions" for floating point operations.
+ SAE ExceptionControl = iota
)
func (ExceptionControl) String() string {
- return "sae"
+ return "sae"
}
// AddressType indicates which kind of value that an Addressable object contains.
type AddressType uint
const (
- // None indicates the Addressable does not contain any addressable value.
- None AddressType = iota
+ // None indicates the Addressable does not contain any addressable value.
+ None AddressType = iota
- // Memory indicates the Addressable contains a memory address.
- Memory
+ // Memory indicates the Addressable contains a memory address.
+ Memory
- // Offset indicates the Addressable contains an RIP-relative offset.
- Offset
+ // Offset indicates the Addressable contains an RIP-relative offset.
+ Offset
- // Reference indicates the Addressable contains a label reference.
- Reference
+ // Reference indicates the Addressable contains a label reference.
+ Reference
)
// Disposable is a type of object that can be Free'd manually.
type Disposable interface {
- Free()
+ Free()
}
// Label represents a location within the program.
type Label struct {
- refs int64
- Name string
- Dest *Instruction
+ refs int64
+ Name string
+ Dest *Instruction
}
func (self *Label) offset(p uintptr, n int) RelativeOffset {
- if self.Dest == nil {
- panic("unresolved label: " + self.Name)
- } else {
- return RelativeOffset(self.Dest.pc - p - uintptr(n))
- }
+ if self.Dest == nil {
+ panic("unresolved label: " + self.Name)
+ } else {
+ return RelativeOffset(self.Dest.pc - p - uintptr(n))
+ }
}
// Free decreases the reference count of a Label, if the
// refcount drops to 0, the Label will be recycled.
func (self *Label) Free() {
- if atomic.AddInt64(&self.refs, -1) == 0 {
- freeLabel(self)
- }
+ if atomic.AddInt64(&self.refs, -1) == 0 {
+ //freeLabel(self)
+ }
}
// String implements the fmt.Stringer interface.
func (self *Label) String() string {
- if self.Dest == nil {
- return fmt.Sprintf("%s(%%rip)", self.Name)
- } else {
- return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
- }
+ if self.Dest == nil {
+ return fmt.Sprintf("%s(%%rip)", self.Name)
+ } else {
+ return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
+ }
}
// Retain increases the reference count of a Label.
func (self *Label) Retain() *Label {
- atomic.AddInt64(&self.refs, 1)
- return self
+ atomic.AddInt64(&self.refs, 1)
+ return self
}
// Evaluate implements the interface expr.Term.
func (self *Label) Evaluate() (int64, error) {
- if self.Dest != nil {
- return int64(self.Dest.pc), nil
- } else {
- return 0, errors.New("unresolved label: " + self.Name)
- }
+ if self.Dest != nil {
+ return int64(self.Dest.pc), nil
+ } else {
+ return 0, errors.New("unresolved label: " + self.Name)
+ }
}
// Addressable is a union to represent an addressable operand.
type Addressable struct {
- Type AddressType
- Memory MemoryAddress
- Offset RelativeOffset
- Reference *Label
+ Type AddressType
+ Memory MemoryAddress
+ Offset RelativeOffset
+ Reference *Label
}
// String implements the fmt.Stringer interface.
func (self *Addressable) String() string {
- switch self.Type {
- case None : return "(not addressable)"
- case Memory : return self.Memory.String()
- case Offset : return self.Offset.String()
- case Reference : return self.Reference.String()
- default : return "(invalid addressable)"
- }
+ switch self.Type {
+ case None:
+ return "(not addressable)"
+ case Memory:
+ return self.Memory.String()
+ case Offset:
+ return self.Offset.String()
+ case Reference:
+ return self.Reference.String()
+ default:
+ return "(invalid addressable)"
+ }
}
// MemoryOperand represents a memory operand for an instruction.
type MemoryOperand struct {
- refs int64
- Size int
- Addr Addressable
- Mask RegisterMask
- Masked bool
- Broadcast uint8
+ refs int64
+ Size int
+ Addr Addressable
+ Mask RegisterMask
+ Masked bool
+ Broadcast uint8
}
const (
- _Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
+ _Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
)
func (self *MemoryOperand) isVMX(evex bool) bool {
- return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
+ return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
}
func (self *MemoryOperand) isVMY(evex bool) bool {
- return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
+ return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
}
func (self *MemoryOperand) isVMZ() bool {
- return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
+ return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
}
func (self *MemoryOperand) isMem() bool {
- if (_Sizes & (1 << self.Broadcast)) == 0 {
- return false
- } else if self.Addr.Type == Memory {
- return self.Addr.Memory.isMem()
- } else if self.Addr.Type == Offset {
- return true
- } else if self.Addr.Type == Reference {
- return true
- } else {
- return false
- }
+ if (_Sizes & (1 << self.Broadcast)) == 0 {
+ return false
+ } else if self.Addr.Type == Memory {
+ return self.Addr.Memory.isMem()
+ } else if self.Addr.Type == Offset {
+ return true
+ } else if self.Addr.Type == Reference {
+ return true
+ } else {
+ return false
+ }
}
func (self *MemoryOperand) isSize(n int) bool {
- return self.Size == 0 || self.Size == n
+ return self.Size == 0 || self.Size == n
}
func (self *MemoryOperand) isBroadcast(n int, b uint8) bool {
- return self.Size == n && self.Broadcast == b
+ return self.Size == n && self.Broadcast == b
}
func (self *MemoryOperand) formatMask() string {
- if !self.Masked {
- return ""
- } else {
- return self.Mask.String()
- }
+ if !self.Masked {
+ return ""
+ } else {
+ return self.Mask.String()
+ }
}
func (self *MemoryOperand) formatBroadcast() string {
- if self.Broadcast == 0 {
- return ""
- } else {
- return fmt.Sprintf("{1to%d}", self.Broadcast)
- }
+ if self.Broadcast == 0 {
+ return ""
+ } else {
+ return fmt.Sprintf("{1to%d}", self.Broadcast)
+ }
}
func (self *MemoryOperand) ensureAddrValid() {
- switch self.Addr.Type {
- case None : break
- case Memory : self.Addr.Memory.EnsureValid()
- case Offset : break
- case Reference : break
- default : panic("invalid address type")
- }
+ switch self.Addr.Type {
+ case None:
+ break
+ case Memory:
+ self.Addr.Memory.EnsureValid()
+ case Offset:
+ break
+ case Reference:
+ break
+ default:
+ panic("invalid address type")
+ }
}
func (self *MemoryOperand) ensureSizeValid() {
- if (_Sizes & (1 << self.Size)) == 0 {
- panic("invalid memory operand size")
- }
+ if (_Sizes & (1 << self.Size)) == 0 {
+ panic("invalid memory operand size")
+ }
}
func (self *MemoryOperand) ensureBroadcastValid() {
- if (_Sizes & (1 << self.Broadcast)) == 0 {
- panic("invalid memory operand broadcast")
- }
+ if (_Sizes & (1 << self.Broadcast)) == 0 {
+ panic("invalid memory operand broadcast")
+ }
}
// Free decreases the reference count of a MemoryOperand, if the
// refcount drops to 0, the Label will be recycled.
func (self *MemoryOperand) Free() {
- if atomic.AddInt64(&self.refs, -1) == 0 {
- freeMemoryOperand(self)
- }
+ if atomic.AddInt64(&self.refs, -1) == 0 {
+ //freeMemoryOperand(self)
+ }
}
// String implements the fmt.Stringer interface.
func (self *MemoryOperand) String() string {
- return self.Addr.String() + self.formatMask() + self.formatBroadcast()
+ return self.Addr.String() + self.formatMask() + self.formatBroadcast()
}
// Retain increases the reference count of a MemoryOperand.
func (self *MemoryOperand) Retain() *MemoryOperand {
- atomic.AddInt64(&self.refs, 1)
- return self
+ atomic.AddInt64(&self.refs, 1)
+ return self
}
// EnsureValid checks if the memory operand is valid, if not, it panics.
func (self *MemoryOperand) EnsureValid() {
- self.ensureAddrValid()
- self.ensureSizeValid()
- self.ensureBroadcastValid()
+ self.ensureAddrValid()
+ self.ensureSizeValid()
+ self.ensureBroadcastValid()
}
// MemoryAddress represents a memory address.
type MemoryAddress struct {
- Base Register
- Index Register
- Scale uint8
- Displacement int32
+ Base Register
+ Index Register
+ Scale uint8
+ Displacement int32
}
const (
- _Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
+ _Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
)
func (self *MemoryAddress) isVMX(evex bool) bool {
- return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
+ return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
}
func (self *MemoryAddress) isVMY(evex bool) bool {
- return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
+ return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
}
func (self *MemoryAddress) isVMZ() bool {
- return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
+ return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
}
func (self *MemoryAddress) isMem() bool {
- return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
+ return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
}
func (self *MemoryAddress) isMemBase() bool {
- return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
- (self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
- (_Scales & (1 << self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
+ return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
+ (self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
+ (_Scales&(1<<self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
}
// String implements the fmt.Stringer interface.
func (self *MemoryAddress) String() string {
- var dp int
- var sb strings.Builder
+ var dp int
+ var sb strings.Builder
- /* the displacement part */
- if dp = int(self.Displacement); dp != 0 {
- sb.WriteString(strconv.Itoa(dp))
- }
+ /* the displacement part */
+ if dp = int(self.Displacement); dp != 0 {
+ sb.WriteString(strconv.Itoa(dp))
+ }
- /* the base register */
- if sb.WriteByte('('); self.Base != nil {
- sb.WriteByte('%')
- sb.WriteString(self.Base.String())
- }
+ /* the base register */
+ if sb.WriteByte('('); self.Base != nil {
+ sb.WriteByte('%')
+ sb.WriteString(self.Base.String())
+ }
- /* index is optional */
- if self.Index != nil {
- sb.WriteString(",%")
- sb.WriteString(self.Index.String())
+ /* index is optional */
+ if self.Index != nil {
+ sb.WriteString(",%")
+ sb.WriteString(self.Index.String())
- /* scale is also optional */
- if self.Scale >= 2 {
- sb.WriteByte(',')
- sb.WriteString(strconv.Itoa(int(self.Scale)))
- }
- }
+ /* scale is also optional */
+ if self.Scale >= 2 {
+ sb.WriteByte(',')
+ sb.WriteString(strconv.Itoa(int(self.Scale)))
+ }
+ }
- /* close the bracket */
- sb.WriteByte(')')
- return sb.String()
+ /* close the bracket */
+ sb.WriteByte(')')
+ return sb.String()
}
// EnsureValid checks if the memory address is valid, if not, it panics.
func (self *MemoryAddress) EnsureValid() {
- if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
- panic("not a valid memory address")
- }
+ if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
+ panic("not a valid memory address")
+ }
}
// Ref constructs a memory reference to a label.
func Ref(ref *Label) (v *MemoryOperand) {
- v = CreateMemoryOperand()
- v.Addr.Type = Reference
- v.Addr.Reference = ref
- return
+ v = CreateMemoryOperand()
+ v.Addr.Type = Reference
+ v.Addr.Reference = ref
+ return
}
// Abs construct a simple memory address that represents absolute addressing.
func Abs(disp int32) *MemoryOperand {
- return Sib(nil, nil, 0, disp)
+ return Sib(nil, nil, 0, disp)
}
// Ptr constructs a simple memory operand with base and displacement.
func Ptr(base Register, disp int32) *MemoryOperand {
- return Sib(base, nil, 0, disp)
+ return Sib(base, nil, 0, disp)
}
// Sib constructs a simple memory operand that represents a complete memory address.
func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) {
- v = CreateMemoryOperand()
- v.Addr.Type = Memory
- v.Addr.Memory.Base = base
- v.Addr.Memory.Index = index
- v.Addr.Memory.Scale = scale
- v.Addr.Memory.Displacement = disp
- v.EnsureValid()
- return
+ v = CreateMemoryOperand()
+ v.Addr.Type = Memory
+ v.Addr.Memory.Base = base
+ v.Addr.Memory.Index = index
+ v.Addr.Memory.Scale = scale
+ v.Addr.Memory.Displacement = disp
+ v.EnsureValid()
+ return
}
/** Operand Matching Helpers **/
-const _IntMask =
- (1 << reflect.Int ) |
- (1 << reflect.Int8 ) |
- (1 << reflect.Int16 ) |
- (1 << reflect.Int32 ) |
- (1 << reflect.Int64 ) |
- (1 << reflect.Uint ) |
- (1 << reflect.Uint8 ) |
- (1 << reflect.Uint16 ) |
- (1 << reflect.Uint32 ) |
- (1 << reflect.Uint64 ) |
- (1 << reflect.Uintptr)
+const _IntMask = (1 << reflect.Int) |
+ (1 << reflect.Int8) |
+ (1 << reflect.Int16) |
+ (1 << reflect.Int32) |
+ (1 << reflect.Int64) |
+ (1 << reflect.Uint) |
+ (1 << reflect.Uint8) |
+ (1 << reflect.Uint16) |
+ (1 << reflect.Uint32) |
+ (1 << reflect.Uint64) |
+ (1 << reflect.Uintptr)
func isInt(k reflect.Kind) bool {
- return (_IntMask & (1 << k)) != 0
+ return (_IntMask & (1 << k)) != 0
}
func asInt64(v interface{}) (int64, bool) {
- if isSpecial(v) {
- return 0, false
- } else if x := efaceOf(v); isInt(x.kind()) {
- return x.toInt64(), true
- } else {
- return 0, false
- }
+ if isSpecial(v) {
+ return 0, false
+ } else if x := efaceOf(v); isInt(x.kind()) {
+ return x.toInt64(), true
+ } else {
+ return 0, false
+ }
}
func inRange(v interface{}, low int64, high int64) bool {
- x, ok := asInt64(v)
- return ok && x >= low && x <= high
+ x, ok := asInt64(v)
+ return ok && x >= low && x <= high
}
func isSpecial(v interface{}) bool {
- switch v.(type) {
- case Register8 : return true
- case Register16 : return true
- case Register32 : return true
- case Register64 : return true
- case KRegister : return true
- case MMRegister : return true
- case XMMRegister : return true
- case YMMRegister : return true
- case ZMMRegister : return true
- case RelativeOffset : return true
- case RoundingControl : return true
- case ExceptionControl : return true
- default : return false
- }
+ switch v.(type) {
+ case Register8:
+ return true
+ case Register16:
+ return true
+ case Register32:
+ return true
+ case Register64:
+ return true
+ case KRegister:
+ return true
+ case MMRegister:
+ return true
+ case XMMRegister:
+ return true
+ case YMMRegister:
+ return true
+ case ZMMRegister:
+ return true
+ case RelativeOffset:
+ return true
+ case RoundingControl:
+ return true
+ case ExceptionControl:
+ return true
+ default:
+ return false
+ }
}
func isIndexable(v interface{}) bool {
- return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
-}
-
-func isImm4 (v interface{}) bool { return inRange(v, 0, 15) }
-func isImm8 (v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
-func isImm16 (v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
-func isImm32 (v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
-func isImm64 (v interface{}) bool { _, r := asInt64(v) ; return r }
-func isConst1 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 1 }
-func isConst3 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 3 }
-func isRel8 (v interface{}) bool { x, r := v.(RelativeOffset) ; return r && x >= math.MinInt8 && x <= math.MaxInt8 }
-func isRel32 (v interface{}) bool { _, r := v.(RelativeOffset) ; return r }
-func isLabel (v interface{}) bool { _, r := v.(*Label) ; return r }
-func isReg8 (v interface{}) bool { _, r := v.(Register8) ; return r }
-func isReg8REX (v interface{}) bool { x, r := v.(Register8) ; return r && (x & 0x80) == 0 && x >= SPL }
-func isReg16 (v interface{}) bool { _, r := v.(Register16) ; return r }
-func isReg32 (v interface{}) bool { _, r := v.(Register32) ; return r }
-func isReg64 (v interface{}) bool { _, r := v.(Register64) ; return r }
-func isMM (v interface{}) bool { _, r := v.(MMRegister) ; return r }
-func isXMM (v interface{}) bool { x, r := v.(XMMRegister) ; return r && x <= XMM15 }
-func isEVEXXMM (v interface{}) bool { _, r := v.(XMMRegister) ; return r }
-func isXMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z) }
-func isXMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg)) }
-func isYMM (v interface{}) bool { x, r := v.(YMMRegister) ; return r && x <= YMM15 }
-func isEVEXYMM (v interface{}) bool { _, r := v.(YMMRegister) ; return r }
-func isYMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z) }
-func isYMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg)) }
-func isZMM (v interface{}) bool { _, r := v.(ZMMRegister) ; return r }
-func isZMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z) }
-func isZMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg)) }
-func isK (v interface{}) bool { _, r := v.(KRegister) ; return r }
-func isKk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isK(v) || (r && isK(x.Reg) && !x.Mask.Z) }
-func isM (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !x.Masked }
-func isMk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z) }
-func isMkz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 }
-func isM8 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(1) }
-func isM16 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(2) }
-func isM16kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(2) }
-func isM32 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(4) }
-func isM32k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(4) }
-func isM32kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(4) }
-func isM64 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(8) }
-func isM64k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(8) }
-func isM64kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(8) }
-func isM128 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(16) }
-func isM128kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(16) }
-func isM256 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(32) }
-func isM256kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(32) }
-func isM512 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(64) }
-func isM512kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(64) }
-func isM64M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM64(v) || (r && x.isBroadcast(4, 2)) }
-func isM128M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(4, 4)) }
-func isM256M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(4, 8)) }
-func isM512M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(4, 16)) }
-func isM128M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(8, 2)) }
-func isM256M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(8, 4)) }
-func isM512M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(8, 8)) }
-func isVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(false) && !x.Masked }
-func isEVEXVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) && !x.Masked }
-func isVMXk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) }
-func isVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(false) && !x.Masked }
-func isEVEXVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) && !x.Masked }
-func isVMYk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) }
-func isVMZ (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() && !x.Masked }
-func isVMZk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() }
-func isSAE (v interface{}) bool { _, r := v.(ExceptionControl) ; return r }
-func isER (v interface{}) bool { _, r := v.(RoundingControl) ; return r }
+ return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
+}
+
+func isImm4(v interface{}) bool { return inRange(v, 0, 15) }
+func isImm8(v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
+func isImm16(v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
+func isImm32(v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
+func isImm64(v interface{}) bool { _, r := asInt64(v); return r }
+func isConst1(v interface{}) bool { x, r := asInt64(v); return r && x == 1 }
+func isConst3(v interface{}) bool { x, r := asInt64(v); return r && x == 3 }
+func isRel8(v interface{}) bool {
+ x, r := v.(RelativeOffset)
+ return r && x >= math.MinInt8 && x <= math.MaxInt8
+}
+func isRel32(v interface{}) bool { _, r := v.(RelativeOffset); return r }
+func isLabel(v interface{}) bool { _, r := v.(*Label); return r }
+func isReg8(v interface{}) bool { _, r := v.(Register8); return r }
+func isReg8REX(v interface{}) bool {
+ x, r := v.(Register8)
+ return r && (x&0x80) == 0 && x >= SPL
+}
+func isReg16(v interface{}) bool { _, r := v.(Register16); return r }
+func isReg32(v interface{}) bool { _, r := v.(Register32); return r }
+func isReg64(v interface{}) bool { _, r := v.(Register64); return r }
+func isMM(v interface{}) bool { _, r := v.(MMRegister); return r }
+func isXMM(v interface{}) bool { x, r := v.(XMMRegister); return r && x <= XMM15 }
+func isEVEXXMM(v interface{}) bool { _, r := v.(XMMRegister); return r }
+func isXMMk(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z)
+}
+func isXMMkz(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isXMM(v) || (r && isXMM(x.Reg))
+}
+func isYMM(v interface{}) bool { x, r := v.(YMMRegister); return r && x <= YMM15 }
+func isEVEXYMM(v interface{}) bool { _, r := v.(YMMRegister); return r }
+func isYMMk(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z)
+}
+func isYMMkz(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isYMM(v) || (r && isYMM(x.Reg))
+}
+func isZMM(v interface{}) bool { _, r := v.(ZMMRegister); return r }
+func isZMMk(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z)
+}
+func isZMMkz(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isZMM(v) || (r && isZMM(x.Reg))
+}
+func isK(v interface{}) bool { _, r := v.(KRegister); return r }
+func isKk(v interface{}) bool {
+ x, r := v.(MaskedRegister)
+ return isK(v) || (r && isK(x.Reg) && !x.Mask.Z)
+}
+func isM(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isMem() && x.Broadcast == 0 && !x.Masked
+}
+func isMk(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z)
+}
+func isMkz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isMem() && x.Broadcast == 0
+}
+func isM8(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(1)
+}
+func isM16(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(2)
+}
+func isM16kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(2)
+}
+func isM32(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(4)
+}
+func isM32k(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMk(v) && x.isSize(4)
+}
+func isM32kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(4)
+}
+func isM64(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(8)
+}
+func isM64k(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMk(v) && x.isSize(8)
+}
+func isM64kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(8)
+}
+func isM128(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(16)
+}
+func isM128kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(16)
+}
+func isM256(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(32)
+}
+func isM256kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(32)
+}
+func isM512(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isM(v) && x.isSize(64)
+}
+func isM512kz(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && isMkz(v) && x.isSize(64)
+}
+func isM64M32bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM64(v) || (r && x.isBroadcast(4, 2))
+}
+func isM128M32bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM128(v) || (r && x.isBroadcast(4, 4))
+}
+func isM256M32bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM256(v) || (r && x.isBroadcast(4, 8))
+}
+func isM512M32bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM512(v) || (r && x.isBroadcast(4, 16))
+}
+func isM128M64bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM128(v) || (r && x.isBroadcast(8, 2))
+}
+func isM256M64bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM256(v) || (r && x.isBroadcast(8, 4))
+}
+func isM512M64bcst(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return isM512(v) || (r && x.isBroadcast(8, 8))
+}
+func isVMX(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isVMX(false) && !x.Masked
+}
+func isEVEXVMX(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isVMX(true) && !x.Masked
+}
+func isVMXk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMX(true) }
+func isVMY(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isVMY(false) && !x.Masked
+}
+func isEVEXVMY(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isVMY(true) && !x.Masked
+}
+func isVMYk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMY(true) }
+func isVMZ(v interface{}) bool {
+ x, r := v.(*MemoryOperand)
+ return r && x.isVMZ() && !x.Masked
+}
+func isVMZk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMZ() }
+func isSAE(v interface{}) bool { _, r := v.(ExceptionControl); return r }
+func isER(v interface{}) bool { _, r := v.(RoundingControl); return r }
func isImmExt(v interface{}, ext int, min int64, max int64) bool {
- if x, ok := asInt64(v); !ok {
- return false
- } else if m := int64(1) << (8 * ext); x < m && x >= m + min {
- return true
- } else {
- return x <= max && x >= min
- }
+ if x, ok := asInt64(v); !ok {
+ return false
+ } else if m := int64(1) << (8 * ext); x < m && x >= m+min {
+ return true
+ } else {
+ return x <= max && x >= min
+ }
}
func isImm8Ext(v interface{}, ext int) bool {
- return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
+ return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
}
func isImm32Ext(v interface{}, ext int) bool {
- return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
+ return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
}
diff --git a/vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go b/vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go
index 06f85ac26..8e6cbbd8a 100644
--- a/vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go
+++ b/vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go
@@ -1,117 +1,38 @@
package x86_64
-import (
- `sync`
-)
-
-var (
- labelPool sync.Pool
- programPool sync.Pool
- instructionPool sync.Pool
- memoryOperandPool sync.Pool
-)
-
-func freeLabel(v *Label) {
- labelPool.Put(v)
-}
-
-func clearLabel(p *Label) *Label {
- *p = Label{}
- return p
-}
-
// CreateLabel creates a new Label, it may allocate a new one or grab one from a pool.
func CreateLabel(name string) *Label {
- var p *Label
- var v interface{}
+ p := new(Label)
- /* attempt to grab from the pool */
- if v = labelPool.Get(); v == nil {
- p = new(Label)
- } else {
- p = clearLabel(v.(*Label))
- }
-
- /* initialize the label */
- p.refs = 1
- p.Name = name
- return p
+ /* initialize the label */
+ p.refs = 1
+ p.Name = name
+ return p
}
func newProgram(arch *Arch) *Program {
- var p *Program
- var v interface{}
-
- /* attempt to grab from the pool */
- if v = programPool.Get(); v == nil {
- p = new(Program)
- } else {
- p = clearProgram(v.(*Program))
- }
-
- /* initialize the program */
- p.arch = arch
- return p
-}
-
-func freeProgram(p *Program) {
- programPool.Put(p)
-}
+ p := new(Program)
-func clearProgram(p *Program) *Program {
- *p = Program{}
- return p
+ /* initialize the program */
+ p.arch = arch
+ return p
}
func newInstruction(name string, argc int, argv Operands) *Instruction {
- var v interface{}
- var p *Instruction
-
- /* attempt to grab from the pool */
- if v = instructionPool.Get(); v == nil {
- p = new(Instruction)
- } else {
- p = clearInstruction(v.(*Instruction))
- }
-
- /* initialize the instruction */
- p.name = name
- p.argc = argc
- p.argv = argv
- return p
-}
-
-func freeInstruction(v *Instruction) {
- instructionPool.Put(v)
-}
+ p := new(Instruction)
-func clearInstruction(p *Instruction) *Instruction {
- *p = Instruction { prefix: p.prefix[:0] }
- return p
-}
-
-func freeMemoryOperand(m *MemoryOperand) {
- memoryOperandPool.Put(m)
-}
-
-func clearMemoryOperand(m *MemoryOperand) *MemoryOperand {
- *m = MemoryOperand{}
- return m
+ /* initialize the instruction */
+ p.name = name
+ p.argc = argc
+ p.argv = argv
+ return p
}
// CreateMemoryOperand creates a new MemoryOperand, it may allocate a new one or grab one from a pool.
func CreateMemoryOperand() *MemoryOperand {
- var v interface{}
- var p *MemoryOperand
-
- /* attempt to grab from the pool */
- if v = memoryOperandPool.Get(); v == nil {
- p = new(MemoryOperand)
- } else {
- p = clearMemoryOperand(v.(*MemoryOperand))
- }
+ p := new(MemoryOperand)
- /* initialize the memory operand */
- p.refs = 1
- return p
+ /* initialize the memory operand */
+ p.refs = 1
+ return p
}
diff --git a/vendor/github.com/chenzhuoyu/iasm/x86_64/program.go b/vendor/github.com/chenzhuoyu/iasm/x86_64/program.go
index 9f80618ef..31562491f 100644
--- a/vendor/github.com/chenzhuoyu/iasm/x86_64/program.go
+++ b/vendor/github.com/chenzhuoyu/iasm/x86_64/program.go
@@ -1,127 +1,149 @@
package x86_64
import (
- `fmt`
- `math`
- `math/bits`
+ "fmt"
+ "math"
+ "math/bits"
- `github.com/chenzhuoyu/iasm/expr`
+ "github.com/chenzhuoyu/iasm/expr"
)
type (
- _PseudoType int
- _InstructionEncoder func(*Program, ...interface{}) *Instruction
+ _PseudoType int
+ _InstructionEncoder func(*Program, ...interface{}) *Instruction
)
const (
- _PseudoNop _PseudoType = iota + 1
- _PseudoByte
- _PseudoWord
- _PseudoLong
- _PseudoQuad
- _PseudoData
- _PseudoAlign
+ _PseudoNop _PseudoType = iota + 1
+ _PseudoByte
+ _PseudoWord
+ _PseudoLong
+ _PseudoQuad
+ _PseudoData
+ _PseudoAlign
)
func (self _PseudoType) String() string {
- switch self {
- case _PseudoNop : return ".nop"
- case _PseudoByte : return ".byte"
- case _PseudoWord : return ".word"
- case _PseudoLong : return ".long"
- case _PseudoQuad : return ".quad"
- case _PseudoData : return ".data"
- case _PseudoAlign : return ".align"
- default : panic("unreachable")
- }
+ switch self {
+ case _PseudoNop:
+ return ".nop"
+ case _PseudoByte:
+ return ".byte"
+ case _PseudoWord:
+ return ".word"
+ case _PseudoLong:
+ return ".long"
+ case _PseudoQuad:
+ return ".quad"
+ case _PseudoData:
+ return ".data"
+ case _PseudoAlign:
+ return ".align"
+ default:
+ panic("unreachable")
+ }
}
type _Pseudo struct {
- kind _PseudoType
- data []byte
- uint uint64
- expr *expr.Expr
+ kind _PseudoType
+ data []byte
+ uint uint64
+ expr *expr.Expr
}
func (self *_Pseudo) free() {
- if self.expr != nil {
- self.expr.Free()
- }
+ if self.expr != nil {
+ self.expr.Free()
+ }
}
func (self *_Pseudo) encode(m *[]byte, pc uintptr) int {
- switch self.kind {
- case _PseudoNop : return 0
- case _PseudoByte : self.encodeByte(m) ; return 1
- case _PseudoWord : self.encodeWord(m) ; return 2
- case _PseudoLong : self.encodeLong(m) ; return 4
- case _PseudoQuad : self.encodeQuad(m) ; return 8
- case _PseudoData : self.encodeData(m) ; return len(self.data)
- case _PseudoAlign : self.encodeAlign(m, pc) ; return self.alignSize(pc)
- default : panic("invalid pseudo instruction")
- }
+ switch self.kind {
+ case _PseudoNop:
+ return 0
+ case _PseudoByte:
+ self.encodeByte(m)
+ return 1
+ case _PseudoWord:
+ self.encodeWord(m)
+ return 2
+ case _PseudoLong:
+ self.encodeLong(m)
+ return 4
+ case _PseudoQuad:
+ self.encodeQuad(m)
+ return 8
+ case _PseudoData:
+ self.encodeData(m)
+ return len(self.data)
+ case _PseudoAlign:
+ self.encodeAlign(m, pc)
+ return self.alignSize(pc)
+ default:
+ panic("invalid pseudo instruction")
+ }
}
func (self *_Pseudo) evalExpr(low int64, high int64) int64 {
- if v, err := self.expr.Evaluate(); err != nil {
- panic(err)
- } else if v < low || v > high {
- panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
- } else {
- return v
- }
+ if v, err := self.expr.Evaluate(); err != nil {
+ panic(err)
+ } else if v < low || v > high {
+ panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
+ } else {
+ return v
+ }
}
func (self *_Pseudo) alignSize(pc uintptr) int {
- if !ispow2(self.uint) {
- panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
- } else {
- return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
- }
+ if !ispow2(self.uint) {
+ panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
+ } else {
+ return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
+ }
}
func (self *_Pseudo) encodeData(m *[]byte) {
- if m != nil {
- *m = append(*m, self.data...)
- }
+ if m != nil {
+ *m = append(*m, self.data...)
+ }
}
func (self *_Pseudo) encodeByte(m *[]byte) {
- if m != nil {
- append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
- }
+ if m != nil {
+ append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
+ }
}
func (self *_Pseudo) encodeWord(m *[]byte) {
- if m != nil {
- append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
- }
+ if m != nil {
+ append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
+ }
}
func (self *_Pseudo) encodeLong(m *[]byte) {
- if m != nil {
- append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
- }
+ if m != nil {
+ append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
+ }
}
func (self *_Pseudo) encodeQuad(m *[]byte) {
- if m != nil {
- if v, err := self.expr.Evaluate(); err != nil {
- panic(err)
- } else {
- append64(m, uint64(v))
- }
- }
+ if m != nil {
+ if v, err := self.expr.Evaluate(); err != nil {
+ panic(err)
+ } else {
+ append64(m, uint64(v))
+ }
+ }
}
func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) {
- if m != nil {
- if self.expr == nil {
- expandmm(m, self.alignSize(pc), 0)
- } else {
- expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
- }
- }
+ if m != nil {
+ if self.expr == nil {
+ expandmm(m, self.alignSize(pc), 0)
+ } else {
+ expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
+ }
+ }
}
// Operands represents a sequence of operand required by an instruction.
@@ -131,15 +153,15 @@ type Operands [_N_args]interface{}
type InstructionDomain uint8
const (
- DomainGeneric InstructionDomain = iota
- DomainMMXSSE
- DomainAVX
- DomainFMA
- DomainCrypto
- DomainMask
- DomainAMDSpecific
- DomainMisc
- DomainPseudo
+ DomainGeneric InstructionDomain = iota
+ DomainMMXSSE
+ DomainAVX
+ DomainFMA
+ DomainCrypto
+ DomainMask
+ DomainAMDSpecific
+ DomainMisc
+ DomainPseudo
)
type (
@@ -147,139 +169,139 @@ type (
)
const (
- _B_none _BranchType = iota
- _B_conditional
- _B_unconditional
+ _B_none _BranchType = iota
+ _B_conditional
+ _B_unconditional
)
// Instruction represents an unencoded instruction.
type Instruction struct {
- next *Instruction
- pc uintptr
- nb int
- len int
- argc int
- name string
- argv Operands
- forms [_N_forms]_Encoding
- pseudo _Pseudo
- branch _BranchType
- domain InstructionDomain
- prefix []byte
+ next *Instruction
+ pc uintptr
+ nb int
+ len int
+ argc int
+ name string
+ argv Operands
+ forms [_N_forms]_Encoding
+ pseudo _Pseudo
+ branch _BranchType
+ domain InstructionDomain
+ prefix []byte
}
func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) {
- self.forms[self.len].flags = flags
- self.forms[self.len].encoder = encoder
- self.len++
+ self.forms[self.len].flags = flags
+ self.forms[self.len].encoder = encoder
+ self.len++
}
func (self *Instruction) free() {
- self.clear()
- self.pseudo.free()
- freeInstruction(self)
+ self.clear()
+ self.pseudo.free()
+ //freeInstruction(self)
}
func (self *Instruction) clear() {
- for i := 0; i < self.argc; i++ {
- if v, ok := self.argv[i].(Disposable); ok {
- v.Free()
- }
- }
+ for i := 0; i < self.argc; i++ {
+ if v, ok := self.argv[i].(Disposable); ok {
+ v.Free()
+ }
+ }
}
func (self *Instruction) check(e *_Encoding) bool {
- if (e.flags & _F_rel1) != 0 {
- return isRel8(self.argv[0])
- } else if (e.flags & _F_rel4) != 0 {
- return isRel32(self.argv[0]) || isLabel(self.argv[0])
- } else {
- return true
- }
+ if (e.flags & _F_rel1) != 0 {
+ return isRel8(self.argv[0])
+ } else if (e.flags & _F_rel4) != 0 {
+ return isRel32(self.argv[0]) || isLabel(self.argv[0])
+ } else {
+ return true
+ }
}
func (self *Instruction) encode(m *[]byte) int {
- n := math.MaxInt64
- p := (*_Encoding)(nil)
-
- /* encode prefixes if any */
- if self.nb = len(self.prefix); m != nil {
- *m = append(*m, self.prefix...)
- }
-
- /* check for pseudo-instructions */
- if self.pseudo.kind != 0 {
- self.nb += self.pseudo.encode(m, self.pc)
- return self.nb
- }
-
- /* find the shortest encoding */
- for i := 0; i < self.len; i++ {
- if e := &self.forms[i]; self.check(e) {
- if v := e.encode(self.argv[:self.argc]); v < n {
- n = v
- p = e
- }
- }
- }
-
- /* add to buffer if needed */
- if m != nil {
- *m = append(*m, p.bytes[:n]...)
- }
-
- /* update the instruction length */
- self.nb += n
- return self.nb
+ n := math.MaxInt64
+ p := (*_Encoding)(nil)
+
+ /* encode prefixes if any */
+ if self.nb = len(self.prefix); m != nil {
+ *m = append(*m, self.prefix...)
+ }
+
+ /* check for pseudo-instructions */
+ if self.pseudo.kind != 0 {
+ self.nb += self.pseudo.encode(m, self.pc)
+ return self.nb
+ }
+
+ /* find the shortest encoding */
+ for i := 0; i < self.len; i++ {
+ if e := &self.forms[i]; self.check(e) {
+ if v := e.encode(self.argv[:self.argc]); v < n {
+ n = v
+ p = e
+ }
+ }
+ }
+
+ /* add to buffer if needed */
+ if m != nil {
+ *m = append(*m, p.bytes[:n]...)
+ }
+
+ /* update the instruction length */
+ self.nb += n
+ return self.nb
}
/** Instruction Prefixes **/
const (
- _P_cs = 0x2e
- _P_ds = 0x3e
- _P_es = 0x26
- _P_fs = 0x64
- _P_gs = 0x65
- _P_ss = 0x36
- _P_lock = 0xf0
+ _P_cs = 0x2e
+ _P_ds = 0x3e
+ _P_es = 0x26
+ _P_fs = 0x64
+ _P_gs = 0x65
+ _P_ss = 0x36
+ _P_lock = 0xf0
)
// CS overrides the memory operation of this instruction to CS.
func (self *Instruction) CS() *Instruction {
- self.prefix = append(self.prefix, _P_cs)
- return self
+ self.prefix = append(self.prefix, _P_cs)
+ return self
}
// DS overrides the memory operation of this instruction to DS,
// this is the default section for most instructions if not specified.
func (self *Instruction) DS() *Instruction {
- self.prefix = append(self.prefix, _P_ds)
- return self
+ self.prefix = append(self.prefix, _P_ds)
+ return self
}
// ES overrides the memory operation of this instruction to ES.
func (self *Instruction) ES() *Instruction {
- self.prefix = append(self.prefix, _P_es)
- return self
+ self.prefix = append(self.prefix, _P_es)
+ return self
}
// FS overrides the memory operation of this instruction to FS.
func (self *Instruction) FS() *Instruction {
- self.prefix = append(self.prefix, _P_fs)
- return self
+ self.prefix = append(self.prefix, _P_fs)
+ return self
}
// GS overrides the memory operation of this instruction to GS.
func (self *Instruction) GS() *Instruction {
- self.prefix = append(self.prefix, _P_gs)
- return self
+ self.prefix = append(self.prefix, _P_gs)
+ return self
}
// SS overrides the memory operation of this instruction to SS.
func (self *Instruction) SS() *Instruction {
- self.prefix = append(self.prefix, _P_ss)
- return self
+ self.prefix = append(self.prefix, _P_ss)
+ return self
}
// LOCK causes the processor's LOCK# signal to be asserted during execution of
@@ -287,128 +309,132 @@ func (self *Instruction) SS() *Instruction {
// In a multiprocessor environment, the LOCK# signal insures that the processor
// has exclusive use of any shared memory while the signal is asserted.
func (self *Instruction) LOCK() *Instruction {
- self.prefix = append(self.prefix, _P_lock)
- return self
+ self.prefix = append(self.prefix, _P_lock)
+ return self
}
/** Basic Instruction Properties **/
// Name returns the instruction name.
func (self *Instruction) Name() string {
- return self.name
+ return self.name
}
// Domain returns the domain of this instruction.
func (self *Instruction) Domain() InstructionDomain {
- return self.domain
+ return self.domain
}
// Operands returns the operands of this instruction.
func (self *Instruction) Operands() []interface{} {
- return self.argv[:self.argc]
+ return self.argv[:self.argc]
}
// Program represents a sequence of instructions.
type Program struct {
- arch *Arch
- head *Instruction
- tail *Instruction
+ arch *Arch
+ head *Instruction
+ tail *Instruction
}
const (
- _N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
- _N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
- _N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
+ _N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
+ _N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
+ _N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
)
func (self *Program) clear() {
- for p, q := self.head, self.head; p != nil; p = q {
- q = p.next
- p.free()
- }
+ for p, q := self.head, self.head; p != nil; p = q {
+ q = p.next
+ p.free()
+ }
}
func (self *Program) alloc(name string, argc int, argv Operands) *Instruction {
- p := self.tail
- q := newInstruction(name, argc, argv)
+ p := self.tail
+ q := newInstruction(name, argc, argv)
- /* attach to tail if any */
- if p != nil {
- p.next = q
- } else {
- self.head = q
- }
+ /* attach to tail if any */
+ if p != nil {
+ p.next = q
+ } else {
+ self.head = q
+ }
- /* set the new tail */
- self.tail = q
- return q
+ /* set the new tail */
+ self.tail = q
+ return q
}
func (self *Program) pseudo(kind _PseudoType) (p *Instruction) {
- p = self.alloc(kind.String(), 0, Operands{})
- p.domain = DomainPseudo
- p.pseudo.kind = kind
- return
+ p = self.alloc(kind.String(), 0, Operands{})
+ p.domain = DomainPseudo
+ p.pseudo.kind = kind
+ return
}
func (self *Program) require(isa ISA) {
- if !self.arch.HasISA(isa) {
- panic("ISA '" + isa.String() + "' was not enabled")
- }
+ if !self.arch.HasISA(isa) {
+ panic("ISA '" + isa.String() + "' was not enabled")
+ }
}
func (self *Program) branchSize(p *Instruction) int {
- switch p.branch {
- case _B_none : panic("p is not a branch")
- case _B_conditional : return _N_far_cond
- case _B_unconditional : return _N_far_uncond
- default : panic("invalid instruction")
- }
+ switch p.branch {
+ case _B_none:
+ panic("p is not a branch")
+ case _B_conditional:
+ return _N_far_cond
+ case _B_unconditional:
+ return _N_far_uncond
+ default:
+ panic("invalid instruction")
+ }
}
/** Pseudo-Instructions **/
// Byte is a pseudo-instruction to add raw byte to the assembled code.
func (self *Program) Byte(v *expr.Expr) (p *Instruction) {
- p = self.pseudo(_PseudoByte)
- p.pseudo.expr = v
- return
+ p = self.pseudo(_PseudoByte)
+ p.pseudo.expr = v
+ return
}
// Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code.
func (self *Program) Word(v *expr.Expr) (p *Instruction) {
- p = self.pseudo(_PseudoWord)
- p.pseudo.expr = v
- return
+ p = self.pseudo(_PseudoWord)
+ p.pseudo.expr = v
+ return
}
// Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code.
func (self *Program) Long(v *expr.Expr) (p *Instruction) {
- p = self.pseudo(_PseudoLong)
- p.pseudo.expr = v
- return
+ p = self.pseudo(_PseudoLong)
+ p.pseudo.expr = v
+ return
}
// Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code.
func (self *Program) Quad(v *expr.Expr) (p *Instruction) {
- p = self.pseudo(_PseudoQuad)
- p.pseudo.expr = v
- return
+ p = self.pseudo(_PseudoQuad)
+ p.pseudo.expr = v
+ return
}
// Data is a pseudo-instruction to add raw bytes to the assembled code.
func (self *Program) Data(v []byte) (p *Instruction) {
- p = self.pseudo(_PseudoData)
- p.pseudo.data = v
- return
+ p = self.pseudo(_PseudoData)
+ p.pseudo.data = v
+ return
}
// Align is a pseudo-instruction to ensure the PC is aligned to a certain value.
func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
- p = self.pseudo(_PseudoAlign)
- p.pseudo.uint = align
- p.pseudo.expr = padding
- return
+ p = self.pseudo(_PseudoAlign)
+ p.pseudo.uint = align
+ p.pseudo.expr = padding
+ return
}
/** Program Assembler **/
@@ -417,126 +443,126 @@ func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
// Any operation performed after Free is undefined behavior.
//
// NOTE: This also frees all the instructions, labels, memory
-// operands and expressions associated with this program.
//
+// operands and expressions associated with this program.
func (self *Program) Free() {
- self.clear()
- freeProgram(self)
+ self.clear()
+ //freeProgram(self)
}
// Link pins a label at the current position.
func (self *Program) Link(p *Label) {
- if p.Dest != nil {
- panic("lable was alreay linked")
- } else {
- p.Dest = self.pseudo(_PseudoNop)
- }
+ if p.Dest != nil {
+ panic("lable was alreay linked")
+ } else {
+ p.Dest = self.pseudo(_PseudoNop)
+ }
}
// Assemble assembles and links the entire program into machine code.
func (self *Program) Assemble(pc uintptr) (ret []byte) {
- orig := pc
- next := true
- offs := uintptr(0)
-
- /* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
- for p := self.head; p != nil; p = p.next {
- if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
- pc += uintptr(p.encode(nil))
- } else {
- pc += uintptr(self.branchSize(p))
- }
- }
-
- /* allocate space for the machine code */
- nb := int(pc - orig)
- ret = make([]byte, 0, nb)
-
- /* Pass 1: adjust all the jumps */
- for next {
- next = false
- offs = uintptr(0)
-
- /* scan all the branches */
- for p := self.head; p != nil; p = p.next {
- var ok bool
- var lb *Label
-
- /* re-calculate the alignment here */
- if nb = p.nb; p.pseudo.kind == _PseudoAlign {
- p.pc -= offs
- offs += uintptr(nb - p.encode(nil))
- continue
- }
-
- /* adjust the program counter */
- p.pc -= offs
- lb, ok = p.argv[0].(*Label)
-
- /* only care about labeled far-branches */
- if !ok || p.nb == _N_near || p.branch == _B_none {
- continue
- }
-
- /* calculate the jump offset */
- size := self.branchSize(p)
- diff := lb.offset(p.pc, size)
-
- /* too far to be a near jump */
- if diff > 127 || diff < -128 {
- p.nb = size
- continue
- }
-
- /* a far jump becomes a near jump, calculate
- * the PC adjustment value and assemble again */
- next = true
- p.nb = _N_near
- offs += uintptr(size - _N_near)
- }
- }
-
- /* Pass 3: link all the cross-references */
- for p := self.head; p != nil; p = p.next {
- for i := 0; i < p.argc; i++ {
- var ok bool
- var lb *Label
- var op *MemoryOperand
-
- /* resolve labels */
- if lb, ok = p.argv[i].(*Label); ok {
- p.argv[i] = lb.offset(p.pc, p.nb)
- continue
- }
-
- /* check for memory operands */
- if op, ok = p.argv[i].(*MemoryOperand); !ok {
- continue
- }
-
- /* check for label references */
- if op.Addr.Type != Reference {
- continue
- }
-
- /* replace the label with the real offset */
- op.Addr.Type = Offset
- op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
- }
- }
-
- /* Pass 4: actually encode all the instructions */
- for p := self.head; p != nil; p = p.next {
- p.encode(&ret)
- }
-
- /* all done */
- return ret
+ orig := pc
+ next := true
+ offs := uintptr(0)
+
+ /* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
+ for p := self.head; p != nil; p = p.next {
+ if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
+ pc += uintptr(p.encode(nil))
+ } else {
+ pc += uintptr(self.branchSize(p))
+ }
+ }
+
+ /* allocate space for the machine code */
+ nb := int(pc - orig)
+ ret = make([]byte, 0, nb)
+
+ /* Pass 1: adjust all the jumps */
+ for next {
+ next = false
+ offs = uintptr(0)
+
+ /* scan all the branches */
+ for p := self.head; p != nil; p = p.next {
+ var ok bool
+ var lb *Label
+
+ /* re-calculate the alignment here */
+ if nb = p.nb; p.pseudo.kind == _PseudoAlign {
+ p.pc -= offs
+ offs += uintptr(nb - p.encode(nil))
+ continue
+ }
+
+ /* adjust the program counter */
+ p.pc -= offs
+ lb, ok = p.argv[0].(*Label)
+
+ /* only care about labeled far-branches */
+ if !ok || p.nb == _N_near || p.branch == _B_none {
+ continue
+ }
+
+ /* calculate the jump offset */
+ size := self.branchSize(p)
+ diff := lb.offset(p.pc, size)
+
+ /* too far to be a near jump */
+ if diff > 127 || diff < -128 {
+ p.nb = size
+ continue
+ }
+
+ /* a far jump becomes a near jump, calculate
+ * the PC adjustment value and assemble again */
+ next = true
+ p.nb = _N_near
+ offs += uintptr(size - _N_near)
+ }
+ }
+
+ /* Pass 3: link all the cross-references */
+ for p := self.head; p != nil; p = p.next {
+ for i := 0; i < p.argc; i++ {
+ var ok bool
+ var lb *Label
+ var op *MemoryOperand
+
+ /* resolve labels */
+ if lb, ok = p.argv[i].(*Label); ok {
+ p.argv[i] = lb.offset(p.pc, p.nb)
+ continue
+ }
+
+ /* check for memory operands */
+ if op, ok = p.argv[i].(*MemoryOperand); !ok {
+ continue
+ }
+
+ /* check for label references */
+ if op.Addr.Type != Reference {
+ continue
+ }
+
+ /* replace the label with the real offset */
+ op.Addr.Type = Offset
+ op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
+ }
+ }
+
+ /* Pass 4: actually encode all the instructions */
+ for p := self.head; p != nil; p = p.next {
+ p.encode(&ret)
+ }
+
+ /* all done */
+ return ret
}
// AssembleAndFree is like Assemble, but it frees the Program after assembling.
func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) {
- ret = self.Assemble(pc)
- self.Free()
- return
-} \ No newline at end of file
+ ret = self.Assemble(pc)
+ self.Free()
+ return
+}