diff options
| author | 2024-03-11 10:12:06 +0000 | |
|---|---|---|
| committer | 2024-03-11 10:12:06 +0000 | |
| commit | e24efcac8b67baa9454bf27631e5e49f898a88d4 (patch) | |
| tree | d9adec2f05e1d8714edee66062a4b95a81ee2a61 /vendor/github.com/chenzhuoyu | |
| parent | [bugfix] Fix whitespace move_id issue (#2742) (diff) | |
| download | gotosocial-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.go | 733 | ||||
| -rw-r--r-- | vendor/github.com/chenzhuoyu/iasm/x86_64/pools.go | 117 | ||||
| -rw-r--r-- | vendor/github.com/chenzhuoyu/iasm/x86_64/program.go | 702 |
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 +} |
