diff options
Diffstat (limited to 'vendor/github.com/cloudwego/iasm/x86_64/operands.go')
| -rw-r--r-- | vendor/github.com/cloudwego/iasm/x86_64/operands.go | 665 |
1 files changed, 0 insertions, 665 deletions
diff --git a/vendor/github.com/cloudwego/iasm/x86_64/operands.go b/vendor/github.com/cloudwego/iasm/x86_64/operands.go deleted file mode 100644 index 61adbf83b..000000000 --- a/vendor/github.com/cloudwego/iasm/x86_64/operands.go +++ /dev/null @@ -1,665 +0,0 @@ -// -// Copyright 2024 CloudWeGo Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package x86_64 - -import ( - "errors" - "fmt" - "math" - "reflect" - "strconv" - "strings" - "sync/atomic" -) - -// RelativeOffset represents an RIP-relative offset. -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) - } -} - -// 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 - - // RD_SAE represents "Round Down". - RD_SAE - - // RU_SAE represents "Round Up". - RU_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", -} - -func (self RoundingControl) String() string { - 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 -) - -func (ExceptionControl) String() string { - 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 - - // Memory indicates the Addressable contains a memory address. - Memory - - // Offset indicates the Addressable contains an RIP-relative offset. - Offset - - // 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() -} - -// Label represents a location within the program. -type Label struct { - 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)) - } -} - -// 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) - } -} - -// 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) - } -} - -// Retain increases the reference count of a Label. -func (self *Label) Retain() *Label { - 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) - } -} - -// Addressable is a union to represent an addressable operand. -type Addressable struct { - 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)" - } -} - -// MemoryOperand represents a memory operand for an instruction. -type MemoryOperand struct { - 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) -) - -func (self *MemoryOperand) isVMX(evex bool) bool { - 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) -} - -func (self *MemoryOperand) isVMZ() bool { - 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 - } -} - -func (self *MemoryOperand) isSize(n int) bool { - return self.Size == 0 || self.Size == n -} - -func (self *MemoryOperand) isBroadcast(n int, b uint8) bool { - return self.Size == n && self.Broadcast == b -} - -func (self *MemoryOperand) formatMask() 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) - } -} - -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") - } -} - -func (self *MemoryOperand) ensureSizeValid() { - 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") - } -} - -// 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) - } -} - -// String implements the fmt.Stringer interface. -func (self *MemoryOperand) String() string { - 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 -} - -// EnsureValid checks if the memory operand is valid, if not, it panics. -func (self *MemoryOperand) EnsureValid() { - self.ensureAddrValid() - self.ensureSizeValid() - self.ensureBroadcastValid() -} - -// MemoryAddress represents a memory address. -type MemoryAddress struct { - Base Register - Index Register - Scale uint8 - Displacement int32 -} - -const ( - _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))) -} - -func (self *MemoryAddress) isVMY(evex bool) bool { - 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)) -} - -func (self *MemoryAddress) isMem() bool { - 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 -} - -// String implements the fmt.Stringer interface. -func (self *MemoryAddress) String() string { - var dp int - var sb strings.Builder - - /* 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()) - } - - /* 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))) - } - } - - /* 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") - } -} - -// 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 -} - -// Abs construct a simple memory address that represents absolute addressing. -func Abs(disp int32) *MemoryOperand { - 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) -} - -// 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 -} - -/** 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) - -func isInt(k reflect.Kind) bool { - 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 - } -} - -func inRange(v interface{}, low int64, high int64) bool { - 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 - } -} - -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 } - -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 - } -} - -func isImm8Ext(v interface{}, ext int) bool { - return isImmExt(v, ext, math.MinInt8, math.MaxInt8) -} - -func isImm32Ext(v interface{}, ext int) bool { - return isImmExt(v, ext, math.MinInt32, math.MaxInt32) -} |
