mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore]: Bump github.com/gin-contrib/gzip from 1.1.0 to 1.2.2 (#3693)
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.1.0 to 1.2.2. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.1.0...v1.2.2) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
177
vendor/github.com/cloudwego/iasm/LICENSE-APACHE
generated
vendored
177
vendor/github.com/cloudwego/iasm/LICENSE-APACHE
generated
vendored
@ -1,177 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
261
vendor/github.com/cloudwego/iasm/expr/ast.go
generated
vendored
261
vendor/github.com/cloudwego/iasm/expr/ast.go
generated
vendored
@ -1,261 +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 expr
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
)
|
||||
|
||||
// Type is tyep expression type.
|
||||
type Type int
|
||||
|
||||
const (
|
||||
// CONST indicates that the expression is a constant.
|
||||
CONST Type = iota
|
||||
|
||||
// TERM indicates that the expression is a Term reference.
|
||||
TERM
|
||||
|
||||
// EXPR indicates that the expression is a unary or binary expression.
|
||||
EXPR
|
||||
)
|
||||
|
||||
var typeNames = map[Type]string {
|
||||
EXPR : "Expr",
|
||||
TERM : "Term",
|
||||
CONST : "Const",
|
||||
}
|
||||
|
||||
// String returns the string representation of a Type.
|
||||
func (self Type) String() string {
|
||||
if v, ok := typeNames[self]; ok {
|
||||
return v
|
||||
} else {
|
||||
return fmt.Sprintf("expr.Type(%d)", self)
|
||||
}
|
||||
}
|
||||
|
||||
// Operator represents an operation to perform when Type is EXPR.
|
||||
type Operator uint8
|
||||
|
||||
const (
|
||||
// ADD performs "Add Expr.Left and Expr.Right".
|
||||
ADD Operator = iota
|
||||
|
||||
// SUB performs "Subtract Expr.Left by Expr.Right".
|
||||
SUB
|
||||
|
||||
// MUL performs "Multiply Expr.Left by Expr.Right".
|
||||
MUL
|
||||
|
||||
// DIV performs "Divide Expr.Left by Expr.Right".
|
||||
DIV
|
||||
|
||||
// MOD performs "Modulo Expr.Left by Expr.Right".
|
||||
MOD
|
||||
|
||||
// AND performs "Bitwise AND Expr.Left and Expr.Right".
|
||||
AND
|
||||
|
||||
// OR performs "Bitwise OR Expr.Left and Expr.Right".
|
||||
OR
|
||||
|
||||
// XOR performs "Bitwise XOR Expr.Left and Expr.Right".
|
||||
XOR
|
||||
|
||||
// SHL performs "Bitwise Shift Expr.Left to the Left by Expr.Right Bits".
|
||||
SHL
|
||||
|
||||
// SHR performs "Bitwise Shift Expr.Left to the Right by Expr.Right Bits".
|
||||
SHR
|
||||
|
||||
// POW performs "Raise Expr.Left to the power of Expr.Right"
|
||||
POW
|
||||
|
||||
// NOT performs "Bitwise Invert Expr.Left".
|
||||
NOT
|
||||
|
||||
// NEG performs "Negate Expr.Left".
|
||||
NEG
|
||||
)
|
||||
|
||||
var operatorNames = map[Operator]string {
|
||||
ADD : "Add",
|
||||
SUB : "Subtract",
|
||||
MUL : "Multiply",
|
||||
DIV : "Divide",
|
||||
MOD : "Modulo",
|
||||
AND : "And",
|
||||
OR : "Or",
|
||||
XOR : "ExclusiveOr",
|
||||
SHL : "ShiftLeft",
|
||||
SHR : "ShiftRight",
|
||||
POW : "Power",
|
||||
NOT : "Invert",
|
||||
NEG : "Negate",
|
||||
}
|
||||
|
||||
// String returns the string representation of a Type.
|
||||
func (self Operator) String() string {
|
||||
if v, ok := operatorNames[self]; ok {
|
||||
return v
|
||||
} else {
|
||||
return fmt.Sprintf("expr.Operator(%d)", self)
|
||||
}
|
||||
}
|
||||
|
||||
// Expr represents an expression node.
|
||||
type Expr struct {
|
||||
Type Type
|
||||
Term Term
|
||||
Op Operator
|
||||
Left *Expr
|
||||
Right *Expr
|
||||
Const int64
|
||||
}
|
||||
|
||||
// Ref creates an expression from a Term.
|
||||
func Ref(t Term) (p *Expr) {
|
||||
p = newExpression()
|
||||
p.Term = t
|
||||
p.Type = TERM
|
||||
return
|
||||
}
|
||||
|
||||
// Int creates an expression from an integer.
|
||||
func Int(v int64) (p *Expr) {
|
||||
p = newExpression()
|
||||
p.Type = CONST
|
||||
p.Const = v
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Expr) clear() {
|
||||
if self.Term != nil { self.Term.Free() }
|
||||
if self.Left != nil { self.Left.Free() }
|
||||
if self.Right != nil { self.Right.Free() }
|
||||
}
|
||||
|
||||
// Free returns the Expr into pool.
|
||||
// Any operation performed after Free is undefined behavior.
|
||||
func (self *Expr) Free() {
|
||||
self.clear()
|
||||
freeExpression(self)
|
||||
}
|
||||
|
||||
// Evaluate evaluates the expression into an integer.
|
||||
// It also implements the Term interface.
|
||||
func (self *Expr) Evaluate() (int64, error) {
|
||||
switch self.Type {
|
||||
case EXPR : return self.eval()
|
||||
case TERM : return self.Term.Evaluate()
|
||||
case CONST : return self.Const, nil
|
||||
default : panic("invalid expression type: " + self.Type.String())
|
||||
}
|
||||
}
|
||||
|
||||
/** Expression Combinator **/
|
||||
|
||||
func combine(a *Expr, op Operator, b *Expr) (r *Expr) {
|
||||
r = newExpression()
|
||||
r.Op = op
|
||||
r.Type = EXPR
|
||||
r.Left = a
|
||||
r.Right = b
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Expr) Add(v *Expr) *Expr { return combine(self, ADD, v) }
|
||||
func (self *Expr) Sub(v *Expr) *Expr { return combine(self, SUB, v) }
|
||||
func (self *Expr) Mul(v *Expr) *Expr { return combine(self, MUL, v) }
|
||||
func (self *Expr) Div(v *Expr) *Expr { return combine(self, DIV, v) }
|
||||
func (self *Expr) Mod(v *Expr) *Expr { return combine(self, MOD, v) }
|
||||
func (self *Expr) And(v *Expr) *Expr { return combine(self, AND, v) }
|
||||
func (self *Expr) Or (v *Expr) *Expr { return combine(self, OR , v) }
|
||||
func (self *Expr) Xor(v *Expr) *Expr { return combine(self, XOR, v) }
|
||||
func (self *Expr) Shl(v *Expr) *Expr { return combine(self, SHL, v) }
|
||||
func (self *Expr) Shr(v *Expr) *Expr { return combine(self, SHR, v) }
|
||||
func (self *Expr) Pow(v *Expr) *Expr { return combine(self, POW, v) }
|
||||
func (self *Expr) Not() *Expr { return combine(self, NOT, nil) }
|
||||
func (self *Expr) Neg() *Expr { return combine(self, NEG, nil) }
|
||||
|
||||
/** Expression Evaluator **/
|
||||
|
||||
var binaryEvaluators = [256]func(int64, int64) (int64, error) {
|
||||
ADD: func(a, b int64) (int64, error) { return a + b, nil },
|
||||
SUB: func(a, b int64) (int64, error) { return a - b, nil },
|
||||
MUL: func(a, b int64) (int64, error) { return a * b, nil },
|
||||
DIV: idiv,
|
||||
MOD: imod,
|
||||
AND: func(a, b int64) (int64, error) { return a & b, nil },
|
||||
OR: func(a, b int64) (int64, error) { return a | b, nil },
|
||||
XOR: func(a, b int64) (int64, error) { return a ^ b, nil },
|
||||
SHL: func(a, b int64) (int64, error) { return a << b, nil },
|
||||
SHR: func(a, b int64) (int64, error) { return a >> b, nil },
|
||||
POW: ipow,
|
||||
}
|
||||
|
||||
func (self *Expr) eval() (int64, error) {
|
||||
var lhs int64
|
||||
var rhs int64
|
||||
var err error
|
||||
var vfn func(int64, int64) (int64, error)
|
||||
|
||||
/* evaluate LHS */
|
||||
if lhs, err = self.Left.Evaluate(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
/* check for unary operators */
|
||||
switch self.Op {
|
||||
case NOT: return self.unaryNot(lhs)
|
||||
case NEG: return self.unaryNeg(lhs)
|
||||
}
|
||||
|
||||
/* check for operators */
|
||||
if vfn = binaryEvaluators[self.Op]; vfn == nil {
|
||||
panic("invalid operator: " + self.Op.String())
|
||||
}
|
||||
|
||||
/* must be a binary expression */
|
||||
if self.Right == nil {
|
||||
panic("operator " + self.Op.String() + " is a binary operator")
|
||||
}
|
||||
|
||||
/* evaluate RHS, and call the operator */
|
||||
if rhs, err = self.Right.Evaluate(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return vfn(lhs, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Expr) unaryNot(v int64) (int64, error) {
|
||||
if self.Right == nil {
|
||||
return ^v, nil
|
||||
} else {
|
||||
panic("operator Invert is an unary operator")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Expr) unaryNeg(v int64) (int64, error) {
|
||||
if self.Right == nil {
|
||||
return -v, nil
|
||||
} else {
|
||||
panic("operator Negate is an unary operator")
|
||||
}
|
||||
}
|
53
vendor/github.com/cloudwego/iasm/expr/errors.go
generated
vendored
53
vendor/github.com/cloudwego/iasm/expr/errors.go
generated
vendored
@ -1,53 +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 expr
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
)
|
||||
|
||||
// SyntaxError represents a syntax error in the expression.
|
||||
type SyntaxError struct {
|
||||
Pos int
|
||||
Reason string
|
||||
}
|
||||
|
||||
func newSyntaxError(pos int, reason string) *SyntaxError {
|
||||
return &SyntaxError {
|
||||
Pos : pos,
|
||||
Reason : reason,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SyntaxError) Error() string {
|
||||
return fmt.Sprintf("Syntax error at position %d: %s", self.Pos, self.Reason)
|
||||
}
|
||||
|
||||
// RuntimeError is an error which would occure at run time.
|
||||
type RuntimeError struct {
|
||||
Reason string
|
||||
}
|
||||
|
||||
func newRuntimeError(reason string) *RuntimeError {
|
||||
return &RuntimeError {
|
||||
Reason: reason,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *RuntimeError) Error() string {
|
||||
return "Runtime error: " + self.Reason
|
||||
}
|
67
vendor/github.com/cloudwego/iasm/expr/ops.go
generated
vendored
67
vendor/github.com/cloudwego/iasm/expr/ops.go
generated
vendored
@ -1,67 +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 expr
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
)
|
||||
|
||||
func idiv(v int64, d int64) (int64, error) {
|
||||
if d != 0 {
|
||||
return v / d, nil
|
||||
} else {
|
||||
return 0, newRuntimeError("division by zero")
|
||||
}
|
||||
}
|
||||
|
||||
func imod(v int64, d int64) (int64, error) {
|
||||
if d != 0 {
|
||||
return v % d, nil
|
||||
} else {
|
||||
return 0, newRuntimeError("division by zero")
|
||||
}
|
||||
}
|
||||
|
||||
func ipow(v int64, e int64) (int64, error) {
|
||||
mul := v
|
||||
ret := int64(1)
|
||||
|
||||
/* value must be 0 or positive */
|
||||
if v < 0 {
|
||||
return 0, newRuntimeError(fmt.Sprintf("negative base value: %d", v))
|
||||
}
|
||||
|
||||
/* exponent must be non-negative */
|
||||
if e < 0 {
|
||||
return 0, newRuntimeError(fmt.Sprintf("negative exponent: %d", e))
|
||||
}
|
||||
|
||||
/* fast power first round */
|
||||
if (e & 1) != 0 {
|
||||
ret *= mul
|
||||
}
|
||||
|
||||
/* fast power remaining rounds */
|
||||
for e >>= 1; e != 0; e >>= 1 {
|
||||
if mul *= mul; (e & 1) != 0 {
|
||||
ret *= mul
|
||||
}
|
||||
}
|
||||
|
||||
/* all done */
|
||||
return ret, nil
|
||||
}
|
329
vendor/github.com/cloudwego/iasm/expr/parser.go
generated
vendored
329
vendor/github.com/cloudwego/iasm/expr/parser.go
generated
vendored
@ -1,329 +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 expr
|
||||
|
||||
import (
|
||||
`strconv`
|
||||
`unicode`
|
||||
`unsafe`
|
||||
)
|
||||
|
||||
type _TokenKind uint8
|
||||
|
||||
const (
|
||||
_T_end _TokenKind = iota + 1
|
||||
_T_int
|
||||
_T_punc
|
||||
_T_name
|
||||
)
|
||||
|
||||
const (
|
||||
_OP2 = 0x80
|
||||
_POW = _OP2 | '*'
|
||||
_SHL = _OP2 | '<'
|
||||
_SHR = _OP2 | '>'
|
||||
)
|
||||
|
||||
type _Slice struct {
|
||||
p unsafe.Pointer
|
||||
n int
|
||||
c int
|
||||
}
|
||||
|
||||
type _Token struct {
|
||||
pos int
|
||||
ptr *rune
|
||||
u64 uint64
|
||||
tag _TokenKind
|
||||
}
|
||||
|
||||
func (self _Token) str() (v string) {
|
||||
return string(self.rbuf())
|
||||
}
|
||||
|
||||
func (self _Token) rbuf() (v []rune) {
|
||||
(*_Slice)(unsafe.Pointer(&v)).c = int(self.u64)
|
||||
(*_Slice)(unsafe.Pointer(&v)).n = int(self.u64)
|
||||
(*_Slice)(unsafe.Pointer(&v)).p = unsafe.Pointer(self.ptr)
|
||||
return
|
||||
}
|
||||
|
||||
func tokenEnd(p int) _Token {
|
||||
return _Token {
|
||||
pos: p,
|
||||
tag: _T_end,
|
||||
}
|
||||
}
|
||||
|
||||
func tokenInt(p int, v uint64) _Token {
|
||||
return _Token {
|
||||
pos: p,
|
||||
u64: v,
|
||||
tag: _T_int,
|
||||
}
|
||||
}
|
||||
|
||||
func tokenPunc(p int, v rune) _Token {
|
||||
return _Token {
|
||||
pos: p,
|
||||
tag: _T_punc,
|
||||
u64: uint64(v),
|
||||
}
|
||||
}
|
||||
|
||||
func tokenName(p int, v []rune) _Token {
|
||||
return _Token {
|
||||
pos: p,
|
||||
ptr: &v[0],
|
||||
tag: _T_name,
|
||||
u64: uint64(len(v)),
|
||||
}
|
||||
}
|
||||
|
||||
// Repository represents a repository of Term's.
|
||||
type Repository interface {
|
||||
Get(name string) (Term, error)
|
||||
}
|
||||
|
||||
// Parser parses an expression string to it's AST representation.
|
||||
type Parser struct {
|
||||
pos int
|
||||
src []rune
|
||||
}
|
||||
|
||||
var binaryOps = [...]func(*Expr, *Expr) *Expr {
|
||||
'+' : (*Expr).Add,
|
||||
'-' : (*Expr).Sub,
|
||||
'*' : (*Expr).Mul,
|
||||
'/' : (*Expr).Div,
|
||||
'%' : (*Expr).Mod,
|
||||
'&' : (*Expr).And,
|
||||
'^' : (*Expr).Xor,
|
||||
'|' : (*Expr).Or,
|
||||
_SHL : (*Expr).Shl,
|
||||
_SHR : (*Expr).Shr,
|
||||
_POW : (*Expr).Pow,
|
||||
}
|
||||
|
||||
var precedence = [...]map[int]bool {
|
||||
{_SHL: true, _SHR: true},
|
||||
{'|' : true},
|
||||
{'^' : true},
|
||||
{'&' : true},
|
||||
{'+' : true, '-': true},
|
||||
{'*' : true, '/': true, '%': true},
|
||||
{_POW: true},
|
||||
}
|
||||
|
||||
func (self *Parser) ch() rune {
|
||||
return self.src[self.pos]
|
||||
}
|
||||
|
||||
func (self *Parser) eof() bool {
|
||||
return self.pos >= len(self.src)
|
||||
}
|
||||
|
||||
func (self *Parser) rch() (v rune) {
|
||||
v, self.pos = self.src[self.pos], self.pos + 1
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Parser) hex(ss []rune) bool {
|
||||
if len(ss) == 1 && ss[0] == '0' {
|
||||
return unicode.ToLower(self.ch()) == 'x'
|
||||
} else if len(ss) <= 1 || unicode.ToLower(ss[1]) != 'x' {
|
||||
return unicode.IsDigit(self.ch())
|
||||
} else {
|
||||
return ishexdigit(self.ch())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) int(p int, ss []rune) (_Token, error) {
|
||||
var err error
|
||||
var val uint64
|
||||
|
||||
/* find all the digits */
|
||||
for !self.eof() && self.hex(ss) {
|
||||
ss = append(ss, self.rch())
|
||||
}
|
||||
|
||||
/* parse the value */
|
||||
if val, err = strconv.ParseUint(string(ss), 0, 64); err != nil {
|
||||
return _Token{}, err
|
||||
} else {
|
||||
return tokenInt(p, val), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) name(p int, ss []rune) _Token {
|
||||
for !self.eof() && isident(self.ch()) { ss = append(ss, self.rch()) }
|
||||
return tokenName(p, ss)
|
||||
}
|
||||
|
||||
func (self *Parser) read(p int, ch rune) (_Token, error) {
|
||||
if isdigit(ch) {
|
||||
return self.int(p, []rune { ch })
|
||||
} else if isident0(ch) {
|
||||
return self.name(p, []rune { ch }), nil
|
||||
} else if isop2ch(ch) && !self.eof() && self.ch() == ch {
|
||||
return tokenPunc(p, _OP2 | self.rch()), nil
|
||||
} else if isop1ch(ch) {
|
||||
return tokenPunc(p, ch), nil
|
||||
} else {
|
||||
return _Token{}, newSyntaxError(self.pos, "invalid character " + strconv.QuoteRuneToASCII(ch))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) next() (_Token, error) {
|
||||
for {
|
||||
var p int
|
||||
var c rune
|
||||
|
||||
/* check for EOF */
|
||||
if self.eof() {
|
||||
return tokenEnd(self.pos), nil
|
||||
}
|
||||
|
||||
/* read the next char */
|
||||
p = self.pos
|
||||
c = self.rch()
|
||||
|
||||
/* parse the token if not a space */
|
||||
if !unicode.IsSpace(c) {
|
||||
return self.read(p, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) grab(tk _Token, repo Repository) (*Expr, error) {
|
||||
if repo == nil {
|
||||
return nil, newSyntaxError(tk.pos, "unresolved symbol: " + tk.str())
|
||||
} else if term, err := repo.Get(tk.str()); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return Ref(term), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) nest(nest int, repo Repository) (*Expr, error) {
|
||||
var err error
|
||||
var ret *Expr
|
||||
var ntk _Token
|
||||
|
||||
/* evaluate the nested expression */
|
||||
if ret, err = self.expr(0, nest + 1, repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* must follows with a ')' */
|
||||
if ntk, err = self.next(); err != nil {
|
||||
return nil, err
|
||||
} else if ntk.tag != _T_punc || ntk.u64 != ')' {
|
||||
return nil, newSyntaxError(ntk.pos, "')' expected")
|
||||
} else {
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) unit(nest int, repo Repository) (*Expr, error) {
|
||||
if tk, err := self.next(); err != nil {
|
||||
return nil, err
|
||||
} else if tk.tag == _T_int {
|
||||
return Int(int64(tk.u64)), nil
|
||||
} else if tk.tag == _T_name {
|
||||
return self.grab(tk, repo)
|
||||
} else if tk.tag == _T_punc && tk.u64 == '(' {
|
||||
return self.nest(nest, repo)
|
||||
} else if tk.tag == _T_punc && tk.u64 == '+' {
|
||||
return self.unit(nest, repo)
|
||||
} else if tk.tag == _T_punc && tk.u64 == '-' {
|
||||
return neg2(self.unit(nest, repo))
|
||||
} else if tk.tag == _T_punc && tk.u64 == '~' {
|
||||
return not2(self.unit(nest, repo))
|
||||
} else {
|
||||
return nil, newSyntaxError(tk.pos, "integer, unary operator or nested expression expected")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) term(prec int, nest int, repo Repository) (*Expr, error) {
|
||||
var err error
|
||||
var val *Expr
|
||||
|
||||
/* parse the LHS operand */
|
||||
if val, err = self.expr(prec + 1, nest, repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* parse all the operators of the same precedence */
|
||||
for {
|
||||
var op int
|
||||
var rv *Expr
|
||||
var tk _Token
|
||||
|
||||
/* peek the next token */
|
||||
pp := self.pos
|
||||
tk, err = self.next()
|
||||
|
||||
/* check for errors */
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* encountered EOF */
|
||||
if tk.tag == _T_end {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
/* must be an operator */
|
||||
if tk.tag != _T_punc {
|
||||
return nil, newSyntaxError(tk.pos, "operators expected")
|
||||
}
|
||||
|
||||
/* check for the operator precedence */
|
||||
if op = int(tk.u64); !precedence[prec][op] {
|
||||
self.pos = pp
|
||||
return val, nil
|
||||
}
|
||||
|
||||
/* evaluate the RHS operand, and combine the value */
|
||||
if rv, err = self.expr(prec + 1, nest, repo); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
val = binaryOps[op](val, rv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Parser) expr(prec int, nest int, repo Repository) (*Expr, error) {
|
||||
if prec >= len(precedence) {
|
||||
return self.unit(nest, repo)
|
||||
} else {
|
||||
return self.term(prec, nest, repo)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse parses the expression, and returns it's AST tree.
|
||||
func (self *Parser) Parse(repo Repository) (*Expr, error) {
|
||||
return self.expr(0, 0, repo)
|
||||
}
|
||||
|
||||
// SetSource resets the expression parser and sets the expression source.
|
||||
func (self *Parser) SetSource(src string) *Parser {
|
||||
self.pos = 0
|
||||
self.src = []rune(src)
|
||||
return self
|
||||
}
|
42
vendor/github.com/cloudwego/iasm/expr/pools.go
generated
vendored
42
vendor/github.com/cloudwego/iasm/expr/pools.go
generated
vendored
@ -1,42 +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 expr
|
||||
|
||||
import (
|
||||
`sync`
|
||||
)
|
||||
|
||||
var (
|
||||
expressionPool sync.Pool
|
||||
)
|
||||
|
||||
func newExpression() *Expr {
|
||||
if v := expressionPool.Get(); v == nil {
|
||||
return new(Expr)
|
||||
} else {
|
||||
return resetExpression(v.(*Expr))
|
||||
}
|
||||
}
|
||||
|
||||
func freeExpression(p *Expr) {
|
||||
expressionPool.Put(p)
|
||||
}
|
||||
|
||||
func resetExpression(p *Expr) *Expr {
|
||||
*p = Expr{}
|
||||
return p
|
||||
}
|
23
vendor/github.com/cloudwego/iasm/expr/term.go
generated
vendored
23
vendor/github.com/cloudwego/iasm/expr/term.go
generated
vendored
@ -1,23 +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 expr
|
||||
|
||||
// Term represents a value that can Evaluate() into an integer.
|
||||
type Term interface {
|
||||
Free()
|
||||
Evaluate() (int64, error)
|
||||
}
|
77
vendor/github.com/cloudwego/iasm/expr/utils.go
generated
vendored
77
vendor/github.com/cloudwego/iasm/expr/utils.go
generated
vendored
@ -1,77 +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 expr
|
||||
|
||||
var op1ch = [...]bool {
|
||||
'+': true,
|
||||
'-': true,
|
||||
'*': true,
|
||||
'/': true,
|
||||
'%': true,
|
||||
'&': true,
|
||||
'|': true,
|
||||
'^': true,
|
||||
'~': true,
|
||||
'(': true,
|
||||
')': true,
|
||||
}
|
||||
|
||||
var op2ch = [...]bool {
|
||||
'*': true,
|
||||
'<': true,
|
||||
'>': true,
|
||||
}
|
||||
|
||||
func neg2(v *Expr, err error) (*Expr, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return v.Neg(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func not2(v *Expr, err error) (*Expr, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return v.Not(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func isop1ch(ch rune) bool {
|
||||
return ch >= 0 && int(ch) < len(op1ch) && op1ch[ch]
|
||||
}
|
||||
|
||||
func isop2ch(ch rune) bool {
|
||||
return ch >= 0 && int(ch) < len(op2ch) && op2ch[ch]
|
||||
}
|
||||
|
||||
func isdigit(ch rune) bool {
|
||||
return ch >= '0' && ch <= '9'
|
||||
}
|
||||
|
||||
func isident(ch rune) bool {
|
||||
return isdigit(ch) || isident0(ch)
|
||||
}
|
||||
|
||||
func isident0(ch rune) bool {
|
||||
return (ch == '_') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
|
||||
}
|
||||
|
||||
func ishexdigit(ch rune) bool {
|
||||
return isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
|
||||
}
|
251
vendor/github.com/cloudwego/iasm/x86_64/arch.go
generated
vendored
251
vendor/github.com/cloudwego/iasm/x86_64/arch.go
generated
vendored
@ -1,251 +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 (
|
||||
`fmt`
|
||||
)
|
||||
|
||||
// ISA represents an extension to x86-64 instruction set.
|
||||
type ISA uint64
|
||||
|
||||
const (
|
||||
ISA_CPUID ISA = 1 << iota
|
||||
ISA_RDTSC
|
||||
ISA_RDTSCP
|
||||
ISA_CMOV
|
||||
ISA_MOVBE
|
||||
ISA_POPCNT
|
||||
ISA_LZCNT
|
||||
ISA_TBM
|
||||
ISA_BMI
|
||||
ISA_BMI2
|
||||
ISA_ADX
|
||||
ISA_MMX
|
||||
ISA_MMX_PLUS
|
||||
ISA_FEMMS
|
||||
ISA_3DNOW
|
||||
ISA_3DNOW_PLUS
|
||||
ISA_SSE
|
||||
ISA_SSE2
|
||||
ISA_SSE3
|
||||
ISA_SSSE3
|
||||
ISA_SSE4A
|
||||
ISA_SSE4_1
|
||||
ISA_SSE4_2
|
||||
ISA_FMA3
|
||||
ISA_FMA4
|
||||
ISA_XOP
|
||||
ISA_F16C
|
||||
ISA_AVX
|
||||
ISA_AVX2
|
||||
ISA_AVX512F
|
||||
ISA_AVX512BW
|
||||
ISA_AVX512DQ
|
||||
ISA_AVX512VL
|
||||
ISA_AVX512PF
|
||||
ISA_AVX512ER
|
||||
ISA_AVX512CD
|
||||
ISA_AVX512VBMI
|
||||
ISA_AVX512IFMA
|
||||
ISA_AVX512VPOPCNTDQ
|
||||
ISA_AVX512_4VNNIW
|
||||
ISA_AVX512_4FMAPS
|
||||
ISA_PREFETCH
|
||||
ISA_PREFETCHW
|
||||
ISA_PREFETCHWT1
|
||||
ISA_CLFLUSH
|
||||
ISA_CLFLUSHOPT
|
||||
ISA_CLWB
|
||||
ISA_CLZERO
|
||||
ISA_RDRAND
|
||||
ISA_RDSEED
|
||||
ISA_PCLMULQDQ
|
||||
ISA_AES
|
||||
ISA_SHA
|
||||
ISA_MONITOR
|
||||
ISA_MONITORX
|
||||
ISA_ALL = ^ISA(0)
|
||||
)
|
||||
|
||||
var _ISA_NAMES = map[ISA]string {
|
||||
ISA_CPUID : "CPUID",
|
||||
ISA_RDTSC : "RDTSC",
|
||||
ISA_RDTSCP : "RDTSCP",
|
||||
ISA_CMOV : "CMOV",
|
||||
ISA_MOVBE : "MOVBE",
|
||||
ISA_POPCNT : "POPCNT",
|
||||
ISA_LZCNT : "LZCNT",
|
||||
ISA_TBM : "TBM",
|
||||
ISA_BMI : "BMI",
|
||||
ISA_BMI2 : "BMI2",
|
||||
ISA_ADX : "ADX",
|
||||
ISA_MMX : "MMX",
|
||||
ISA_MMX_PLUS : "MMX+",
|
||||
ISA_FEMMS : "FEMMS",
|
||||
ISA_3DNOW : "3dnow!",
|
||||
ISA_3DNOW_PLUS : "3dnow!+",
|
||||
ISA_SSE : "SSE",
|
||||
ISA_SSE2 : "SSE2",
|
||||
ISA_SSE3 : "SSE3",
|
||||
ISA_SSSE3 : "SSSE3",
|
||||
ISA_SSE4A : "SSE4A",
|
||||
ISA_SSE4_1 : "SSE4.1",
|
||||
ISA_SSE4_2 : "SSE4.2",
|
||||
ISA_FMA3 : "FMA3",
|
||||
ISA_FMA4 : "FMA4",
|
||||
ISA_XOP : "XOP",
|
||||
ISA_F16C : "F16C",
|
||||
ISA_AVX : "AVX",
|
||||
ISA_AVX2 : "AVX2",
|
||||
ISA_AVX512F : "AVX512F",
|
||||
ISA_AVX512BW : "AVX512BW",
|
||||
ISA_AVX512DQ : "AVX512DQ",
|
||||
ISA_AVX512VL : "AVX512VL",
|
||||
ISA_AVX512PF : "AVX512PF",
|
||||
ISA_AVX512ER : "AVX512ER",
|
||||
ISA_AVX512CD : "AVX512CD",
|
||||
ISA_AVX512VBMI : "AVX512VBMI",
|
||||
ISA_AVX512IFMA : "AVX512IFMA",
|
||||
ISA_AVX512VPOPCNTDQ : "AVX512VPOPCNTDQ",
|
||||
ISA_AVX512_4VNNIW : "AVX512_4VNNIW",
|
||||
ISA_AVX512_4FMAPS : "AVX512_4FMAPS",
|
||||
ISA_PREFETCH : "PREFETCH",
|
||||
ISA_PREFETCHW : "PREFETCHW",
|
||||
ISA_PREFETCHWT1 : "PREFETCHWT1",
|
||||
ISA_CLFLUSH : "CLFLUSH",
|
||||
ISA_CLFLUSHOPT : "CLFLUSHOPT",
|
||||
ISA_CLWB : "CLWB",
|
||||
ISA_CLZERO : "CLZERO",
|
||||
ISA_RDRAND : "RDRAND",
|
||||
ISA_RDSEED : "RDSEED",
|
||||
ISA_PCLMULQDQ : "PCLMULQDQ",
|
||||
ISA_AES : "AES",
|
||||
ISA_SHA : "SHA",
|
||||
ISA_MONITOR : "MONITOR",
|
||||
ISA_MONITORX : "MONITORX",
|
||||
}
|
||||
|
||||
var _ISA_MAPPING = map[string]ISA {
|
||||
"CPUID" : ISA_CPUID,
|
||||
"RDTSC" : ISA_RDTSC,
|
||||
"RDTSCP" : ISA_RDTSCP,
|
||||
"CMOV" : ISA_CMOV,
|
||||
"MOVBE" : ISA_MOVBE,
|
||||
"POPCNT" : ISA_POPCNT,
|
||||
"LZCNT" : ISA_LZCNT,
|
||||
"TBM" : ISA_TBM,
|
||||
"BMI" : ISA_BMI,
|
||||
"BMI2" : ISA_BMI2,
|
||||
"ADX" : ISA_ADX,
|
||||
"MMX" : ISA_MMX,
|
||||
"MMX+" : ISA_MMX_PLUS,
|
||||
"FEMMS" : ISA_FEMMS,
|
||||
"3dnow!" : ISA_3DNOW,
|
||||
"3dnow!+" : ISA_3DNOW_PLUS,
|
||||
"SSE" : ISA_SSE,
|
||||
"SSE2" : ISA_SSE2,
|
||||
"SSE3" : ISA_SSE3,
|
||||
"SSSE3" : ISA_SSSE3,
|
||||
"SSE4A" : ISA_SSE4A,
|
||||
"SSE4.1" : ISA_SSE4_1,
|
||||
"SSE4.2" : ISA_SSE4_2,
|
||||
"FMA3" : ISA_FMA3,
|
||||
"FMA4" : ISA_FMA4,
|
||||
"XOP" : ISA_XOP,
|
||||
"F16C" : ISA_F16C,
|
||||
"AVX" : ISA_AVX,
|
||||
"AVX2" : ISA_AVX2,
|
||||
"AVX512F" : ISA_AVX512F,
|
||||
"AVX512BW" : ISA_AVX512BW,
|
||||
"AVX512DQ" : ISA_AVX512DQ,
|
||||
"AVX512VL" : ISA_AVX512VL,
|
||||
"AVX512PF" : ISA_AVX512PF,
|
||||
"AVX512ER" : ISA_AVX512ER,
|
||||
"AVX512CD" : ISA_AVX512CD,
|
||||
"AVX512VBMI" : ISA_AVX512VBMI,
|
||||
"AVX512IFMA" : ISA_AVX512IFMA,
|
||||
"AVX512VPOPCNTDQ" : ISA_AVX512VPOPCNTDQ,
|
||||
"AVX512_4VNNIW" : ISA_AVX512_4VNNIW,
|
||||
"AVX512_4FMAPS" : ISA_AVX512_4FMAPS,
|
||||
"PREFETCH" : ISA_PREFETCH,
|
||||
"PREFETCHW" : ISA_PREFETCHW,
|
||||
"PREFETCHWT1" : ISA_PREFETCHWT1,
|
||||
"CLFLUSH" : ISA_CLFLUSH,
|
||||
"CLFLUSHOPT" : ISA_CLFLUSHOPT,
|
||||
"CLWB" : ISA_CLWB,
|
||||
"CLZERO" : ISA_CLZERO,
|
||||
"RDRAND" : ISA_RDRAND,
|
||||
"RDSEED" : ISA_RDSEED,
|
||||
"PCLMULQDQ" : ISA_PCLMULQDQ,
|
||||
"AES" : ISA_AES,
|
||||
"SHA" : ISA_SHA,
|
||||
"MONITOR" : ISA_MONITOR,
|
||||
"MONITORX" : ISA_MONITORX,
|
||||
}
|
||||
|
||||
func (self ISA) String() string {
|
||||
if v, ok := _ISA_NAMES[self]; ok {
|
||||
return v
|
||||
} else {
|
||||
return fmt.Sprintf("(invalid: %#x)", uint64(self))
|
||||
}
|
||||
}
|
||||
|
||||
// ParseISA parses name into ISA, it will panic if the name is invalid.
|
||||
func ParseISA(name string) ISA {
|
||||
if v, ok := _ISA_MAPPING[name]; ok {
|
||||
return v
|
||||
} else {
|
||||
panic("invalid ISA name: " + name)
|
||||
}
|
||||
}
|
||||
|
||||
// Arch represents the x86_64 architecture.
|
||||
type Arch struct {
|
||||
isa ISA
|
||||
}
|
||||
|
||||
// DefaultArch is the default architecture with all ISA enabled.
|
||||
var DefaultArch = CreateArch()
|
||||
|
||||
// CreateArch creates a new Arch with all ISA enabled.
|
||||
func CreateArch() *Arch {
|
||||
return new(Arch).EnableISA(ISA_ALL)
|
||||
}
|
||||
|
||||
// HasISA checks if a particular ISA was enabled.
|
||||
func (self *Arch) HasISA(isa ISA) bool {
|
||||
return (self.isa & isa) != 0
|
||||
}
|
||||
|
||||
// EnableISA enables a particular ISA.
|
||||
func (self *Arch) EnableISA(isa ISA) *Arch {
|
||||
self.isa |= isa
|
||||
return self
|
||||
}
|
||||
|
||||
// DisableISA disables a particular ISA.
|
||||
func (self *Arch) DisableISA(isa ISA) *Arch {
|
||||
self.isa &^= isa
|
||||
return self
|
||||
}
|
||||
|
||||
// CreateProgram creates a new empty program.
|
||||
func (self *Arch) CreateProgram() *Program {
|
||||
return newProgram(self)
|
||||
}
|
16
vendor/github.com/cloudwego/iasm/x86_64/asm.s
generated
vendored
16
vendor/github.com/cloudwego/iasm/x86_64/asm.s
generated
vendored
@ -1,16 +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.
|
||||
//
|
||||
|
1819
vendor/github.com/cloudwego/iasm/x86_64/assembler.go
generated
vendored
1819
vendor/github.com/cloudwego/iasm/x86_64/assembler.go
generated
vendored
File diff suppressed because it is too large
Load Diff
49
vendor/github.com/cloudwego/iasm/x86_64/assembler_alias.go
generated
vendored
49
vendor/github.com/cloudwego/iasm/x86_64/assembler_alias.go
generated
vendored
@ -1,49 +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
|
||||
|
||||
func alias_INT3(p *Program, vv ...interface{}) *Instruction {
|
||||
if len(vv) == 0 {
|
||||
return p.INT(3)
|
||||
} else {
|
||||
panic("instruction INT3 takes no operands")
|
||||
}
|
||||
}
|
||||
|
||||
func alias_VCMPEQPS(p *Program, vv ...interface{}) *Instruction {
|
||||
if len(vv) >= 3 {
|
||||
return p.VCMPPS(0x00, vv[0], vv[1], vv[2], vv[3:]...)
|
||||
} else {
|
||||
panic("instruction VCMPEQPS takes 3 or 4 operands")
|
||||
}
|
||||
}
|
||||
|
||||
func alias_VCMPTRUEPS(p *Program, vv ...interface{}) *Instruction {
|
||||
if len(vv) >= 3 {
|
||||
return p.VCMPPS(0x0f, vv[0], vv[1], vv[2], vv[3:]...)
|
||||
} else {
|
||||
panic("instruction VCMPTRUEPS takes 3 or 4 operands")
|
||||
}
|
||||
}
|
||||
|
||||
var _InstructionAliases = map[string]_InstructionEncoder {
|
||||
"int3" : alias_INT3,
|
||||
"retq" : Instructions["ret"],
|
||||
"movabsq" : Instructions["movq"],
|
||||
"vcmpeqps" : alias_VCMPEQPS,
|
||||
"vcmptrueps" : alias_VCMPTRUEPS,
|
||||
}
|
79
vendor/github.com/cloudwego/iasm/x86_64/eface.go
generated
vendored
79
vendor/github.com/cloudwego/iasm/x86_64/eface.go
generated
vendored
@ -1,79 +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 (
|
||||
`reflect`
|
||||
`unsafe`
|
||||
)
|
||||
|
||||
type _GoType struct {
|
||||
size uintptr
|
||||
pdata uintptr
|
||||
hash uint32
|
||||
flags uint8
|
||||
align uint8
|
||||
falign uint8
|
||||
kflags uint8
|
||||
traits unsafe.Pointer
|
||||
gcdata *byte
|
||||
str int32
|
||||
ptrx int32
|
||||
}
|
||||
|
||||
const (
|
||||
_KindMask = (1 << 5) - 1
|
||||
)
|
||||
|
||||
func (self *_GoType) kind() reflect.Kind {
|
||||
return reflect.Kind(self.kflags & _KindMask)
|
||||
}
|
||||
|
||||
type _GoSlice struct {
|
||||
ptr unsafe.Pointer
|
||||
len int
|
||||
cap int
|
||||
}
|
||||
|
||||
type _GoEface struct {
|
||||
vt *_GoType
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func (self *_GoEface) kind() reflect.Kind {
|
||||
if self.vt != nil {
|
||||
return self.vt.kind()
|
||||
} else {
|
||||
return reflect.Invalid
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_GoEface) toInt64() int64 {
|
||||
if self.vt.size == 8 {
|
||||
return *(*int64)(self.ptr)
|
||||
} else if self.vt.size == 4 {
|
||||
return int64(*(*int32)(self.ptr))
|
||||
} else if self.vt.size == 2 {
|
||||
return int64(*(*int16)(self.ptr))
|
||||
} else {
|
||||
return int64(*(*int8)(self.ptr))
|
||||
}
|
||||
}
|
||||
|
||||
func efaceOf(v interface{}) _GoEface {
|
||||
return *(*_GoEface)(unsafe.Pointer(&v))
|
||||
}
|
691
vendor/github.com/cloudwego/iasm/x86_64/encodings.go
generated
vendored
691
vendor/github.com/cloudwego/iasm/x86_64/encodings.go
generated
vendored
@ -1,691 +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 (
|
||||
`encoding/binary`
|
||||
`math`
|
||||
)
|
||||
|
||||
/** Operand Encoding Helpers **/
|
||||
|
||||
func imml(v interface{}) byte {
|
||||
return byte(toImmAny(v) & 0x0f)
|
||||
}
|
||||
|
||||
func relv(v interface{}) int64 {
|
||||
switch r := v.(type) {
|
||||
case *Label : return 0
|
||||
case RelativeOffset : return int64(r)
|
||||
default : panic("invalid relative offset")
|
||||
}
|
||||
}
|
||||
|
||||
func addr(v interface{}) interface{} {
|
||||
switch a := v.(*MemoryOperand).Addr; a.Type {
|
||||
case Memory : return a.Memory
|
||||
case Offset : return a.Offset
|
||||
case Reference : return a.Reference
|
||||
default : panic("invalid memory operand type")
|
||||
}
|
||||
}
|
||||
|
||||
func bcode(v interface{}) byte {
|
||||
if m, ok := v.(*MemoryOperand); !ok {
|
||||
panic("v is not a memory operand")
|
||||
} else if m.Broadcast == 0 {
|
||||
return 0
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func vcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case XMMRegister : return byte(r)
|
||||
case YMMRegister : return byte(r)
|
||||
case ZMMRegister : return byte(r)
|
||||
case MaskedRegister : return vcode(r.Reg)
|
||||
default : panic("v is not a vector register")
|
||||
}
|
||||
}
|
||||
|
||||
func kcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case KRegister : return byte(r)
|
||||
case XMMRegister : return 0
|
||||
case YMMRegister : return 0
|
||||
case ZMMRegister : return 0
|
||||
case RegisterMask : return byte(r.K)
|
||||
case MaskedRegister : return byte(r.Mask.K)
|
||||
case *MemoryOperand : return toKcodeMem(r)
|
||||
default : panic("v is not a maskable operand")
|
||||
}
|
||||
}
|
||||
|
||||
func zcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case KRegister : return 0
|
||||
case XMMRegister : return 0
|
||||
case YMMRegister : return 0
|
||||
case ZMMRegister : return 0
|
||||
case RegisterMask : return toZcodeRegM(r)
|
||||
case MaskedRegister : return toZcodeRegM(r.Mask)
|
||||
case *MemoryOperand : return toZcodeMem(r)
|
||||
default : panic("v is not a maskable operand")
|
||||
}
|
||||
}
|
||||
|
||||
func lcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case Register8 : return byte(r & 0x07)
|
||||
case Register16 : return byte(r & 0x07)
|
||||
case Register32 : return byte(r & 0x07)
|
||||
case Register64 : return byte(r & 0x07)
|
||||
case KRegister : return byte(r & 0x07)
|
||||
case MMRegister : return byte(r & 0x07)
|
||||
case XMMRegister : return byte(r & 0x07)
|
||||
case YMMRegister : return byte(r & 0x07)
|
||||
case ZMMRegister : return byte(r & 0x07)
|
||||
case MaskedRegister : return lcode(r.Reg)
|
||||
default : panic("v is not a register")
|
||||
}
|
||||
}
|
||||
|
||||
func hcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case Register8 : return byte(r >> 3) & 1
|
||||
case Register16 : return byte(r >> 3) & 1
|
||||
case Register32 : return byte(r >> 3) & 1
|
||||
case Register64 : return byte(r >> 3) & 1
|
||||
case KRegister : return byte(r >> 3) & 1
|
||||
case MMRegister : return byte(r >> 3) & 1
|
||||
case XMMRegister : return byte(r >> 3) & 1
|
||||
case YMMRegister : return byte(r >> 3) & 1
|
||||
case ZMMRegister : return byte(r >> 3) & 1
|
||||
case MaskedRegister : return hcode(r.Reg)
|
||||
default : panic("v is not a register")
|
||||
}
|
||||
}
|
||||
|
||||
func ecode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case Register8 : return byte(r >> 4) & 1
|
||||
case Register16 : return byte(r >> 4) & 1
|
||||
case Register32 : return byte(r >> 4) & 1
|
||||
case Register64 : return byte(r >> 4) & 1
|
||||
case KRegister : return byte(r >> 4) & 1
|
||||
case MMRegister : return byte(r >> 4) & 1
|
||||
case XMMRegister : return byte(r >> 4) & 1
|
||||
case YMMRegister : return byte(r >> 4) & 1
|
||||
case ZMMRegister : return byte(r >> 4) & 1
|
||||
case MaskedRegister : return ecode(r.Reg)
|
||||
default : panic("v is not a register")
|
||||
}
|
||||
}
|
||||
|
||||
func hlcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case Register8 : return toHLcodeReg8(r)
|
||||
case Register16 : return byte(r & 0x0f)
|
||||
case Register32 : return byte(r & 0x0f)
|
||||
case Register64 : return byte(r & 0x0f)
|
||||
case KRegister : return byte(r & 0x0f)
|
||||
case MMRegister : return byte(r & 0x0f)
|
||||
case XMMRegister : return byte(r & 0x0f)
|
||||
case YMMRegister : return byte(r & 0x0f)
|
||||
case ZMMRegister : return byte(r & 0x0f)
|
||||
case MaskedRegister : return hlcode(r.Reg)
|
||||
default : panic("v is not a register")
|
||||
}
|
||||
}
|
||||
|
||||
func ehcode(v interface{}) byte {
|
||||
switch r := v.(type) {
|
||||
case Register8 : return byte(r >> 3) & 0x03
|
||||
case Register16 : return byte(r >> 3) & 0x03
|
||||
case Register32 : return byte(r >> 3) & 0x03
|
||||
case Register64 : return byte(r >> 3) & 0x03
|
||||
case KRegister : return byte(r >> 3) & 0x03
|
||||
case MMRegister : return byte(r >> 3) & 0x03
|
||||
case XMMRegister : return byte(r >> 3) & 0x03
|
||||
case YMMRegister : return byte(r >> 3) & 0x03
|
||||
case ZMMRegister : return byte(r >> 3) & 0x03
|
||||
case MaskedRegister : return ehcode(r.Reg)
|
||||
default : panic("v is not a register")
|
||||
}
|
||||
}
|
||||
|
||||
func toImmAny(v interface{}) int64 {
|
||||
if x, ok := asInt64(v); ok {
|
||||
return x
|
||||
} else {
|
||||
panic("value is not an integer")
|
||||
}
|
||||
}
|
||||
|
||||
func toHcodeOpt(v interface{}) byte {
|
||||
if v == nil {
|
||||
return 0
|
||||
} else {
|
||||
return hcode(v)
|
||||
}
|
||||
}
|
||||
|
||||
func toEcodeVMM(v interface{}, x byte) byte {
|
||||
switch r := v.(type) {
|
||||
case XMMRegister : return ecode(r)
|
||||
case YMMRegister : return ecode(r)
|
||||
case ZMMRegister : return ecode(r)
|
||||
default : return x
|
||||
}
|
||||
}
|
||||
|
||||
func toKcodeMem(v *MemoryOperand) byte {
|
||||
if !v.Masked {
|
||||
return 0
|
||||
} else {
|
||||
return byte(v.Mask.K)
|
||||
}
|
||||
}
|
||||
|
||||
func toZcodeMem(v *MemoryOperand) byte {
|
||||
if !v.Masked || v.Mask.Z {
|
||||
return 0
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func toZcodeRegM(v RegisterMask) byte {
|
||||
if v.Z {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func toHLcodeReg8(v Register8) byte {
|
||||
switch v {
|
||||
case AH: fallthrough
|
||||
case BH: fallthrough
|
||||
case CH: fallthrough
|
||||
case DH: panic("ah/bh/ch/dh registers never use 4-bit encoding")
|
||||
default: return byte(v & 0x0f)
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruction Encoding Helpers **/
|
||||
|
||||
const (
|
||||
_N_inst = 16
|
||||
)
|
||||
|
||||
const (
|
||||
_F_rel1 = 1 << iota
|
||||
_F_rel4
|
||||
)
|
||||
|
||||
type _Encoding struct {
|
||||
len int
|
||||
flags int
|
||||
bytes [_N_inst]byte
|
||||
encoder func(m *_Encoding, v []interface{})
|
||||
}
|
||||
|
||||
// buf ensures len + n <= len(bytes).
|
||||
func (self *_Encoding) buf(n int) []byte {
|
||||
if i := self.len; i + n > _N_inst {
|
||||
panic("instruction too long")
|
||||
} else {
|
||||
return self.bytes[i:]
|
||||
}
|
||||
}
|
||||
|
||||
// emit encodes a single byte.
|
||||
func (self *_Encoding) emit(v byte) {
|
||||
self.buf(1)[0] = v
|
||||
self.len++
|
||||
}
|
||||
|
||||
// imm1 encodes a single byte immediate value.
|
||||
func (self *_Encoding) imm1(v int64) {
|
||||
self.emit(byte(v))
|
||||
}
|
||||
|
||||
// imm2 encodes a two-byte immediate value in little-endian.
|
||||
func (self *_Encoding) imm2(v int64) {
|
||||
binary.LittleEndian.PutUint16(self.buf(2), uint16(v))
|
||||
self.len += 2
|
||||
}
|
||||
|
||||
// imm4 encodes a 4-byte immediate value in little-endian.
|
||||
func (self *_Encoding) imm4(v int64) {
|
||||
binary.LittleEndian.PutUint32(self.buf(4), uint32(v))
|
||||
self.len += 4
|
||||
}
|
||||
|
||||
// imm8 encodes an 8-byte immediate value in little-endian.
|
||||
func (self *_Encoding) imm8(v int64) {
|
||||
binary.LittleEndian.PutUint64(self.buf(8), uint64(v))
|
||||
self.len += 8
|
||||
}
|
||||
|
||||
// vex2 encodes a 2-byte or 3-byte VEX prefix.
|
||||
//
|
||||
// 2-byte VEX prefix:
|
||||
// Requires: VEX.W = 0, VEX.mmmmm = 0b00001 and VEX.B = VEX.X = 0
|
||||
// +----------------+
|
||||
// Byte 0: | Bits 0-7: 0xc5 |
|
||||
// +----------------+
|
||||
//
|
||||
// +-----------+----------------+----------+--------------+
|
||||
// Byte 1: | Bit 7: ~R | Bits 3-6 ~vvvv | Bit 2: L | Bits 0-1: pp |
|
||||
// +-----------+----------------+----------+--------------+
|
||||
//
|
||||
// 3-byte VEX prefix:
|
||||
// +----------------+
|
||||
// Byte 0: | Bits 0-7: 0xc4 |
|
||||
// +----------------+
|
||||
//
|
||||
// +-----------+-----------+-----------+-------------------+
|
||||
// Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: 0b00001 |
|
||||
// +-----------+-----------+-----------+-------------------+
|
||||
//
|
||||
// +----------+-----------------+----------+--------------+
|
||||
// Byte 2: | Bit 7: 0 | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp |
|
||||
// +----------+-----------------+----------+--------------+
|
||||
//
|
||||
func (self *_Encoding) vex2(lpp byte, r byte, rm interface{}, vvvv byte) {
|
||||
var b byte
|
||||
var x byte
|
||||
|
||||
/* VEX.R must be a single-bit mask */
|
||||
if r > 1 {
|
||||
panic("VEX.R must be a 1-bit mask")
|
||||
}
|
||||
|
||||
/* VEX.Lpp must be a 3-bit mask */
|
||||
if lpp &^ 0b111 != 0 {
|
||||
panic("VEX.Lpp must be a 3-bit mask")
|
||||
}
|
||||
|
||||
/* VEX.vvvv must be a 4-bit mask */
|
||||
if vvvv &^ 0b1111 != 0 {
|
||||
panic("VEX.vvvv must be a 4-bit mask")
|
||||
}
|
||||
|
||||
/* encode the RM bits if any */
|
||||
if rm != nil {
|
||||
switch v := rm.(type) {
|
||||
case *Label : break
|
||||
case Register : b = hcode(v)
|
||||
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
|
||||
case RelativeOffset : break
|
||||
default : panic("rm is expected to be a register or a memory address")
|
||||
}
|
||||
}
|
||||
|
||||
/* if VEX.B and VEX.X are zeroes, 2-byte VEX prefix can be used */
|
||||
if x == 0 && b == 0 {
|
||||
self.emit(0xc5)
|
||||
self.emit(0xf8 ^ (r << 7) ^ (vvvv << 3) ^ lpp)
|
||||
} else {
|
||||
self.emit(0xc4)
|
||||
self.emit(0xe1 ^ (r << 7) ^ (x << 6) ^ (b << 5))
|
||||
self.emit(0x78 ^ (vvvv << 3) ^ lpp)
|
||||
}
|
||||
}
|
||||
|
||||
// vex3 encodes a 3-byte VEX or XOP prefix.
|
||||
//
|
||||
// 3-byte VEX/XOP prefix
|
||||
// +-----------------------------------+
|
||||
// Byte 0: | Bits 0-7: 0xc4 (VEX) / 0x8f (XOP) |
|
||||
// +-----------------------------------+
|
||||
//
|
||||
// +-----------+-----------+-----------+-----------------+
|
||||
// Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: mmmmm |
|
||||
// +-----------+-----------+-----------+-----------------+
|
||||
//
|
||||
// +----------+-----------------+----------+--------------+
|
||||
// Byte 2: | Bit 7: W | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp |
|
||||
// +----------+-----------------+----------+--------------+
|
||||
//
|
||||
func (self *_Encoding) vex3(esc byte, mmmmm byte, wlpp byte, r byte, rm interface{}, vvvv byte) {
|
||||
var b byte
|
||||
var x byte
|
||||
|
||||
/* VEX.R must be a single-bit mask */
|
||||
if r > 1 {
|
||||
panic("VEX.R must be a 1-bit mask")
|
||||
}
|
||||
|
||||
/* VEX.vvvv must be a 4-bit mask */
|
||||
if vvvv &^ 0b1111 != 0 {
|
||||
panic("VEX.vvvv must be a 4-bit mask")
|
||||
}
|
||||
|
||||
/* escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix */
|
||||
if esc != 0xc4 && esc != 0x8f {
|
||||
panic("escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix")
|
||||
}
|
||||
|
||||
/* VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7 */
|
||||
if wlpp &^ 0b10000111 != 0 {
|
||||
panic("VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7")
|
||||
}
|
||||
|
||||
/* VEX.m-mmmm is expected to be a 5-bit mask */
|
||||
if mmmmm &^ 0b11111 != 0 {
|
||||
panic("VEX.m-mmmm is expected to be a 5-bit mask")
|
||||
}
|
||||
|
||||
/* encode the RM bits */
|
||||
switch v := rm.(type) {
|
||||
case *Label : break
|
||||
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
|
||||
case RelativeOffset : break
|
||||
default : panic("rm is expected to be a register or a memory address")
|
||||
}
|
||||
|
||||
/* encode the 3-byte VEX or XOP prefix */
|
||||
self.emit(esc)
|
||||
self.emit(0xe0 ^ (r << 7) ^ (x << 6) ^ (b << 5) ^ mmmmm)
|
||||
self.emit(0x78 ^ (vvvv << 3) ^ wlpp)
|
||||
}
|
||||
|
||||
// evex encodes a 4-byte EVEX prefix.
|
||||
func (self *_Encoding) evex(mm byte, w1pp byte, ll byte, rr byte, rm interface{}, vvvvv byte, aaa byte, zz byte, bb byte) {
|
||||
var b byte
|
||||
var x byte
|
||||
|
||||
/* EVEX.b must be a single-bit mask */
|
||||
if bb > 1 {
|
||||
panic("EVEX.b must be a 1-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.z must be a single-bit mask */
|
||||
if zz > 1 {
|
||||
panic("EVEX.z must be a 1-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.mm must be a 2-bit mask */
|
||||
if mm &^ 0b11 != 0 {
|
||||
panic("EVEX.mm must be a 2-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.L'L must be a 2-bit mask */
|
||||
if ll &^ 0b11 != 0 {
|
||||
panic("EVEX.L'L must be a 2-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.R'R must be a 2-bit mask */
|
||||
if rr &^ 0b11 != 0 {
|
||||
panic("EVEX.R'R must be a 2-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.aaa must be a 3-bit mask */
|
||||
if aaa &^ 0b111 != 0 {
|
||||
panic("EVEX.aaa must be a 3-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.v'vvvv must be a 5-bit mask */
|
||||
if vvvvv &^ 0b11111 != 0 {
|
||||
panic("EVEX.v'vvvv must be a 5-bit mask")
|
||||
}
|
||||
|
||||
/* EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7 */
|
||||
if w1pp &^ 0b10000011 != 0b100 {
|
||||
panic("EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7")
|
||||
}
|
||||
|
||||
/* extract bits from EVEX.R'R and EVEX.v'vvvv */
|
||||
r1, r0 := rr >> 1, rr & 1
|
||||
v1, v0 := vvvvv >> 4, vvvvv & 0b1111
|
||||
|
||||
/* encode the RM bits if any */
|
||||
if rm != nil {
|
||||
switch m := rm.(type) {
|
||||
case *Label : break
|
||||
case Register : b, x = hcode(m), ecode(m)
|
||||
case MemoryAddress : b, x, v1 = toHcodeOpt(m.Base), toHcodeOpt(m.Index), toEcodeVMM(m.Index, v1)
|
||||
case RelativeOffset : break
|
||||
default : panic("rm is expected to be a register or a memory address")
|
||||
}
|
||||
}
|
||||
|
||||
/* EVEX prefix bytes */
|
||||
p0 := (r0 << 7) | (x << 6) | (b << 5) | (r1 << 4) | mm
|
||||
p1 := (v0 << 3) | w1pp
|
||||
p2 := (zz << 7) | (ll << 5) | (b << 4) | (v1 << 3) | aaa
|
||||
|
||||
/* p0: invert RXBR' (bits 4-7)
|
||||
* p1: invert vvvv (bits 3-6)
|
||||
* p2: invert V' (bit 3) */
|
||||
self.emit(0x62)
|
||||
self.emit(p0 ^ 0xf0)
|
||||
self.emit(p1 ^ 0x78)
|
||||
self.emit(p2 ^ 0x08)
|
||||
}
|
||||
|
||||
// rexm encodes a mandatory REX prefix.
|
||||
func (self *_Encoding) rexm(w byte, r byte, rm interface{}) {
|
||||
var b byte
|
||||
var x byte
|
||||
|
||||
/* REX.R must be 0 or 1 */
|
||||
if r != 0 && r != 1 {
|
||||
panic("REX.R must be 0 or 1")
|
||||
}
|
||||
|
||||
/* REX.W must be 0 or 1 */
|
||||
if w != 0 && w != 1 {
|
||||
panic("REX.W must be 0 or 1")
|
||||
}
|
||||
|
||||
/* encode the RM bits */
|
||||
switch v := rm.(type) {
|
||||
case *Label : break
|
||||
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
|
||||
case RelativeOffset : break
|
||||
default : panic("rm is expected to be a register or a memory address")
|
||||
}
|
||||
|
||||
/* encode the REX prefix */
|
||||
self.emit(0x40 | (w << 3) | (r << 2) | (x << 1) | b)
|
||||
}
|
||||
|
||||
// rexo encodes an optional REX prefix.
|
||||
func (self *_Encoding) rexo(r byte, rm interface{}, force bool) {
|
||||
var b byte
|
||||
var x byte
|
||||
|
||||
/* REX.R must be 0 or 1 */
|
||||
if r != 0 && r != 1 {
|
||||
panic("REX.R must be 0 or 1")
|
||||
}
|
||||
|
||||
/* encode the RM bits */
|
||||
switch v := rm.(type) {
|
||||
case *Label : break
|
||||
case Register : b = hcode(v)
|
||||
case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
|
||||
case RelativeOffset : break
|
||||
default : panic("rm is expected to be a register or a memory address")
|
||||
}
|
||||
|
||||
/* if REX.R, REX.X, and REX.B are all zeroes, REX prefix can be omitted */
|
||||
if force || r != 0 || x != 0 || b != 0 {
|
||||
self.emit(0x40 | (r << 2) | (x << 1) | b)
|
||||
}
|
||||
}
|
||||
|
||||
// mrsd encodes ModR/M, SIB and Displacement.
|
||||
//
|
||||
// ModR/M byte
|
||||
// +----------------+---------------+---------------+
|
||||
// | Bits 6-7: Mode | Bits 3-5: Reg | Bits 0-2: R/M |
|
||||
// +----------------+---------------+---------------+
|
||||
//
|
||||
// SIB byte
|
||||
// +-----------------+-----------------+----------------+
|
||||
// | Bits 6-7: Scale | Bits 3-5: Index | Bits 0-2: Base |
|
||||
// +-----------------+-----------------+----------------+
|
||||
//
|
||||
func (self *_Encoding) mrsd(reg byte, rm interface{}, disp8v int32) {
|
||||
var ok bool
|
||||
var mm MemoryAddress
|
||||
var ro RelativeOffset
|
||||
|
||||
/* ModRM encodes the lower 3-bit of the register */
|
||||
if reg > 7 {
|
||||
panic("invalid register bits")
|
||||
}
|
||||
|
||||
/* check the displacement scale */
|
||||
switch disp8v {
|
||||
case 1: break
|
||||
case 2: break
|
||||
case 4: break
|
||||
case 8: break
|
||||
case 16: break
|
||||
case 32: break
|
||||
case 64: break
|
||||
default: panic("invalid displacement size")
|
||||
}
|
||||
|
||||
/* special case: unresolved labels, assuming a zero offset */
|
||||
if _, ok = rm.(*Label); ok {
|
||||
self.emit(0x05 | (reg << 3))
|
||||
self.imm4(0)
|
||||
return
|
||||
}
|
||||
|
||||
/* special case: RIP-relative offset
|
||||
* ModRM.Mode == 0 and ModeRM.R/M == 5 indicates (rip + disp32) addressing */
|
||||
if ro, ok = rm.(RelativeOffset); ok {
|
||||
self.emit(0x05 | (reg << 3))
|
||||
self.imm4(int64(ro))
|
||||
return
|
||||
}
|
||||
|
||||
/* must be a generic memory address */
|
||||
if mm, ok = rm.(MemoryAddress); !ok {
|
||||
panic("rm must be a memory address")
|
||||
}
|
||||
|
||||
/* absolute addressing, encoded as disp(%rbp,%rsp,1) */
|
||||
if mm.Base == nil && mm.Index == nil {
|
||||
self.emit(0x04 | (reg << 3))
|
||||
self.emit(0x25)
|
||||
self.imm4(int64(mm.Displacement))
|
||||
return
|
||||
}
|
||||
|
||||
/* no SIB byte */
|
||||
if mm.Index == nil && lcode(mm.Base) != 0b100 {
|
||||
cc := lcode(mm.Base)
|
||||
dv := mm.Displacement
|
||||
|
||||
/* ModRM.Mode == 0 (no displacement) */
|
||||
if dv == 0 && mm.Base != RBP && mm.Base != R13 {
|
||||
if cc == 0b101 {
|
||||
panic("rbp/r13 is not encodable as a base register (interpreted as disp32 address)")
|
||||
} else {
|
||||
self.emit((reg << 3) | cc)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* ModRM.Mode == 1 (8-bit displacement) */
|
||||
if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
|
||||
self.emit(0x40 | (reg << 3) | cc)
|
||||
self.imm1(int64(dq))
|
||||
return
|
||||
}
|
||||
|
||||
/* ModRM.Mode == 2 (32-bit displacement) */
|
||||
self.emit(0x80 | (reg << 3) | cc)
|
||||
self.imm4(int64(mm.Displacement))
|
||||
return
|
||||
}
|
||||
|
||||
/* all encodings below use ModRM.R/M = 4 (0b100) to indicate the presence of SIB */
|
||||
if mm.Index == RSP {
|
||||
panic("rsp is not encodable as an index register (interpreted as no index)")
|
||||
}
|
||||
|
||||
/* index = 4 (0b100) denotes no-index encoding */
|
||||
var scale byte
|
||||
var index byte = 0x04
|
||||
|
||||
/* encode the scale byte */
|
||||
if mm.Scale != 0 {
|
||||
switch mm.Scale {
|
||||
case 1 : scale = 0
|
||||
case 2 : scale = 1
|
||||
case 4 : scale = 2
|
||||
case 8 : scale = 3
|
||||
default : panic("invalid scale value")
|
||||
}
|
||||
}
|
||||
|
||||
/* encode the index byte */
|
||||
if mm.Index != nil {
|
||||
index = lcode(mm.Index)
|
||||
}
|
||||
|
||||
/* SIB.Base = 5 (0b101) and ModRM.Mode = 0 indicates no-base encoding with disp32 */
|
||||
if mm.Base == nil {
|
||||
self.emit((reg << 3) | 0b100)
|
||||
self.emit((scale << 6) | (index << 3) | 0b101)
|
||||
self.imm4(int64(mm.Displacement))
|
||||
return
|
||||
}
|
||||
|
||||
/* base L-code & displacement value */
|
||||
cc := lcode(mm.Base)
|
||||
dv := mm.Displacement
|
||||
|
||||
/* ModRM.Mode == 0 (no displacement) */
|
||||
if dv == 0 && cc != 0b101 {
|
||||
self.emit((reg << 3) | 0b100)
|
||||
self.emit((scale << 6) | (index << 3) | cc)
|
||||
return
|
||||
}
|
||||
|
||||
/* ModRM.Mode == 1 (8-bit displacement) */
|
||||
if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
|
||||
self.emit(0x44 | (reg << 3))
|
||||
self.emit((scale << 6) | (index << 3) | cc)
|
||||
self.imm1(int64(dq))
|
||||
return
|
||||
}
|
||||
|
||||
/* ModRM.Mode == 2 (32-bit displacement) */
|
||||
self.emit(0x84 | (reg << 3))
|
||||
self.emit((scale << 6) | (index << 3) | cc)
|
||||
self.imm4(int64(mm.Displacement))
|
||||
}
|
||||
|
||||
// encode invokes the encoder to encode this instruction.
|
||||
func (self *_Encoding) encode(v []interface{}) int {
|
||||
self.len = 0
|
||||
self.encoder(self, v)
|
||||
return self.len
|
||||
}
|
97210
vendor/github.com/cloudwego/iasm/x86_64/instructions.go
generated
vendored
97210
vendor/github.com/cloudwego/iasm/x86_64/instructions.go
generated
vendored
File diff suppressed because it is too large
Load Diff
12307
vendor/github.com/cloudwego/iasm/x86_64/instructions_table.go
generated
vendored
12307
vendor/github.com/cloudwego/iasm/x86_64/instructions_table.go
generated
vendored
File diff suppressed because it is too large
Load Diff
665
vendor/github.com/cloudwego/iasm/x86_64/operands.go
generated
vendored
665
vendor/github.com/cloudwego/iasm/x86_64/operands.go
generated
vendored
@ -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)
|
||||
}
|
54
vendor/github.com/cloudwego/iasm/x86_64/pools.go
generated
vendored
54
vendor/github.com/cloudwego/iasm/x86_64/pools.go
generated
vendored
@ -1,54 +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
|
||||
|
||||
// CreateLabel creates a new Label, it may allocate a new one or grab one from a pool.
|
||||
func CreateLabel(name string) *Label {
|
||||
p := new(Label)
|
||||
|
||||
/* initialize the label */
|
||||
p.refs = 1
|
||||
p.Name = name
|
||||
return p
|
||||
}
|
||||
|
||||
func newProgram(arch *Arch) *Program {
|
||||
p := new(Program)
|
||||
|
||||
/* initialize the program */
|
||||
p.arch = arch
|
||||
return p
|
||||
}
|
||||
|
||||
func newInstruction(name string, argc int, argv Operands) *Instruction {
|
||||
p := new(Instruction)
|
||||
|
||||
/* 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 {
|
||||
p := new(MemoryOperand)
|
||||
|
||||
/* initialize the memory operand */
|
||||
p.refs = 1
|
||||
return p
|
||||
}
|
584
vendor/github.com/cloudwego/iasm/x86_64/program.go
generated
vendored
584
vendor/github.com/cloudwego/iasm/x86_64/program.go
generated
vendored
@ -1,584 +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 (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
|
||||
"github.com/cloudwego/iasm/expr"
|
||||
)
|
||||
|
||||
type (
|
||||
_PseudoType int
|
||||
_InstructionEncoder func(*Program, ...interface{}) *Instruction
|
||||
)
|
||||
|
||||
const (
|
||||
_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")
|
||||
}
|
||||
}
|
||||
|
||||
type _Pseudo struct {
|
||||
kind _PseudoType
|
||||
data []byte
|
||||
uint uint64
|
||||
expr *expr.Expr
|
||||
}
|
||||
|
||||
func (self *_Pseudo) 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")
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeData(m *[]byte) {
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeWord(m *[]byte) {
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeQuad(m *[]byte) {
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Operands represents a sequence of operand required by an instruction.
|
||||
type Operands [_N_args]interface{}
|
||||
|
||||
// InstructionDomain represents the domain of an instruction.
|
||||
type InstructionDomain uint8
|
||||
|
||||
const (
|
||||
DomainGeneric InstructionDomain = iota
|
||||
DomainMMXSSE
|
||||
DomainAVX
|
||||
DomainFMA
|
||||
DomainCrypto
|
||||
DomainMask
|
||||
DomainAMDSpecific
|
||||
DomainMisc
|
||||
DomainPseudo
|
||||
)
|
||||
|
||||
type (
|
||||
_BranchType uint8
|
||||
)
|
||||
|
||||
const (
|
||||
_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
|
||||
}
|
||||
|
||||
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++
|
||||
}
|
||||
|
||||
func (self *Instruction) free() {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/** Instruction Prefixes **/
|
||||
|
||||
const (
|
||||
_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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// ES overrides the memory operation of this instruction to ES.
|
||||
func (self *Instruction) ES() *Instruction {
|
||||
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
|
||||
}
|
||||
|
||||
// GS overrides the memory operation of this instruction to GS.
|
||||
func (self *Instruction) GS() *Instruction {
|
||||
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
|
||||
}
|
||||
|
||||
// LOCK causes the processor's LOCK# signal to be asserted during execution of
|
||||
// the accompanying instruction (turns the instruction into an atomic 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
|
||||
}
|
||||
|
||||
/** Basic Instruction Properties **/
|
||||
|
||||
// Name returns the instruction name.
|
||||
func (self *Instruction) Name() string {
|
||||
return self.name
|
||||
}
|
||||
|
||||
// Domain returns the domain of this instruction.
|
||||
func (self *Instruction) Domain() InstructionDomain {
|
||||
return self.domain
|
||||
}
|
||||
|
||||
// Operands returns the operands of this instruction.
|
||||
func (self *Instruction) Operands() []interface{} {
|
||||
return self.argv[:self.argc]
|
||||
}
|
||||
|
||||
// Program represents a sequence of instructions.
|
||||
type Program struct {
|
||||
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
|
||||
)
|
||||
|
||||
func (self *Program) clear() {
|
||||
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)
|
||||
|
||||
/* attach to tail if any */
|
||||
if p != nil {
|
||||
p.next = q
|
||||
} else {
|
||||
self.head = 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
|
||||
}
|
||||
|
||||
func (self *Program) require(isa ISA) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
/** 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
/** Program Assembler **/
|
||||
|
||||
// Free returns the Program object into pool.
|
||||
// Any operation performed after Free is undefined behavior.
|
||||
//
|
||||
// NOTE: This also frees all the instructions, labels, memory
|
||||
//
|
||||
// operands and expressions associated with this program.
|
||||
func (self *Program) Free() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
693
vendor/github.com/cloudwego/iasm/x86_64/registers.go
generated
vendored
693
vendor/github.com/cloudwego/iasm/x86_64/registers.go
generated
vendored
@ -1,693 +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 (
|
||||
`fmt`
|
||||
)
|
||||
|
||||
// Register represents a hardware register.
|
||||
type Register interface {
|
||||
fmt.Stringer
|
||||
implRegister()
|
||||
}
|
||||
|
||||
type (
|
||||
Register8 byte
|
||||
Register16 byte
|
||||
Register32 byte
|
||||
Register64 byte
|
||||
)
|
||||
|
||||
type (
|
||||
KRegister byte
|
||||
MMRegister byte
|
||||
XMMRegister byte
|
||||
YMMRegister byte
|
||||
ZMMRegister byte
|
||||
)
|
||||
|
||||
// RegisterMask is a KRegister used to mask another register.
|
||||
type RegisterMask struct {
|
||||
Z bool
|
||||
K KRegister
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (self RegisterMask) String() string {
|
||||
if !self.Z {
|
||||
return fmt.Sprintf("{%%%s}", self.K)
|
||||
} else {
|
||||
return fmt.Sprintf("{%%%s}{z}", self.K)
|
||||
}
|
||||
}
|
||||
|
||||
// MaskedRegister is a Register masked by a RegisterMask.
|
||||
type MaskedRegister struct {
|
||||
Reg Register
|
||||
Mask RegisterMask
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (self MaskedRegister) String() string {
|
||||
return self.Reg.String() + self.Mask.String()
|
||||
}
|
||||
|
||||
const (
|
||||
AL Register8 = iota
|
||||
CL
|
||||
DL
|
||||
BL
|
||||
SPL
|
||||
BPL
|
||||
SIL
|
||||
DIL
|
||||
R8b
|
||||
R9b
|
||||
R10b
|
||||
R11b
|
||||
R12b
|
||||
R13b
|
||||
R14b
|
||||
R15b
|
||||
)
|
||||
|
||||
const (
|
||||
AH = SPL | 0x80
|
||||
CH = BPL | 0x80
|
||||
DH = SIL | 0x80
|
||||
BH = DIL | 0x80
|
||||
)
|
||||
|
||||
const (
|
||||
AX Register16 = iota
|
||||
CX
|
||||
DX
|
||||
BX
|
||||
SP
|
||||
BP
|
||||
SI
|
||||
DI
|
||||
R8w
|
||||
R9w
|
||||
R10w
|
||||
R11w
|
||||
R12w
|
||||
R13w
|
||||
R14w
|
||||
R15w
|
||||
)
|
||||
|
||||
const (
|
||||
EAX Register32 = iota
|
||||
ECX
|
||||
EDX
|
||||
EBX
|
||||
ESP
|
||||
EBP
|
||||
ESI
|
||||
EDI
|
||||
R8d
|
||||
R9d
|
||||
R10d
|
||||
R11d
|
||||
R12d
|
||||
R13d
|
||||
R14d
|
||||
R15d
|
||||
)
|
||||
|
||||
const (
|
||||
RAX Register64 = iota
|
||||
RCX
|
||||
RDX
|
||||
RBX
|
||||
RSP
|
||||
RBP
|
||||
RSI
|
||||
RDI
|
||||
R8
|
||||
R9
|
||||
R10
|
||||
R11
|
||||
R12
|
||||
R13
|
||||
R14
|
||||
R15
|
||||
)
|
||||
|
||||
const (
|
||||
K0 KRegister = iota
|
||||
K1
|
||||
K2
|
||||
K3
|
||||
K4
|
||||
K5
|
||||
K6
|
||||
K7
|
||||
)
|
||||
|
||||
const (
|
||||
MM0 MMRegister = iota
|
||||
MM1
|
||||
MM2
|
||||
MM3
|
||||
MM4
|
||||
MM5
|
||||
MM6
|
||||
MM7
|
||||
)
|
||||
|
||||
const (
|
||||
XMM0 XMMRegister = iota
|
||||
XMM1
|
||||
XMM2
|
||||
XMM3
|
||||
XMM4
|
||||
XMM5
|
||||
XMM6
|
||||
XMM7
|
||||
XMM8
|
||||
XMM9
|
||||
XMM10
|
||||
XMM11
|
||||
XMM12
|
||||
XMM13
|
||||
XMM14
|
||||
XMM15
|
||||
XMM16
|
||||
XMM17
|
||||
XMM18
|
||||
XMM19
|
||||
XMM20
|
||||
XMM21
|
||||
XMM22
|
||||
XMM23
|
||||
XMM24
|
||||
XMM25
|
||||
XMM26
|
||||
XMM27
|
||||
XMM28
|
||||
XMM29
|
||||
XMM30
|
||||
XMM31
|
||||
)
|
||||
|
||||
const (
|
||||
YMM0 YMMRegister = iota
|
||||
YMM1
|
||||
YMM2
|
||||
YMM3
|
||||
YMM4
|
||||
YMM5
|
||||
YMM6
|
||||
YMM7
|
||||
YMM8
|
||||
YMM9
|
||||
YMM10
|
||||
YMM11
|
||||
YMM12
|
||||
YMM13
|
||||
YMM14
|
||||
YMM15
|
||||
YMM16
|
||||
YMM17
|
||||
YMM18
|
||||
YMM19
|
||||
YMM20
|
||||
YMM21
|
||||
YMM22
|
||||
YMM23
|
||||
YMM24
|
||||
YMM25
|
||||
YMM26
|
||||
YMM27
|
||||
YMM28
|
||||
YMM29
|
||||
YMM30
|
||||
YMM31
|
||||
)
|
||||
|
||||
const (
|
||||
ZMM0 ZMMRegister = iota
|
||||
ZMM1
|
||||
ZMM2
|
||||
ZMM3
|
||||
ZMM4
|
||||
ZMM5
|
||||
ZMM6
|
||||
ZMM7
|
||||
ZMM8
|
||||
ZMM9
|
||||
ZMM10
|
||||
ZMM11
|
||||
ZMM12
|
||||
ZMM13
|
||||
ZMM14
|
||||
ZMM15
|
||||
ZMM16
|
||||
ZMM17
|
||||
ZMM18
|
||||
ZMM19
|
||||
ZMM20
|
||||
ZMM21
|
||||
ZMM22
|
||||
ZMM23
|
||||
ZMM24
|
||||
ZMM25
|
||||
ZMM26
|
||||
ZMM27
|
||||
ZMM28
|
||||
ZMM29
|
||||
ZMM30
|
||||
ZMM31
|
||||
)
|
||||
|
||||
func (self Register8) implRegister() {}
|
||||
func (self Register16) implRegister() {}
|
||||
func (self Register32) implRegister() {}
|
||||
func (self Register64) implRegister() {}
|
||||
|
||||
func (self KRegister) implRegister() {}
|
||||
func (self MMRegister) implRegister() {}
|
||||
func (self XMMRegister) implRegister() {}
|
||||
func (self YMMRegister) implRegister() {}
|
||||
func (self ZMMRegister) implRegister() {}
|
||||
|
||||
func (self Register8) String() string { if int(self) >= len(r8names) { return "???" } else { return r8names[self] } }
|
||||
func (self Register16) String() string { if int(self) >= len(r16names) { return "???" } else { return r16names[self] } }
|
||||
func (self Register32) String() string { if int(self) >= len(r32names) { return "???" } else { return r32names[self] } }
|
||||
func (self Register64) String() string { if int(self) >= len(r64names) { return "???" } else { return r64names[self] } }
|
||||
|
||||
func (self KRegister) String() string { if int(self) >= len(knames) { return "???" } else { return knames[self] } }
|
||||
func (self MMRegister) String() string { if int(self) >= len(mmnames) { return "???" } else { return mmnames[self] } }
|
||||
func (self XMMRegister) String() string { if int(self) >= len(xmmnames) { return "???" } else { return xmmnames[self] } }
|
||||
func (self YMMRegister) String() string { if int(self) >= len(ymmnames) { return "???" } else { return ymmnames[self] } }
|
||||
func (self ZMMRegister) String() string { if int(self) >= len(zmmnames) { return "???" } else { return zmmnames[self] } }
|
||||
|
||||
// Registers maps register name into Register instances.
|
||||
var Registers = map[string]Register {
|
||||
"al" : AL,
|
||||
"cl" : CL,
|
||||
"dl" : DL,
|
||||
"bl" : BL,
|
||||
"spl" : SPL,
|
||||
"bpl" : BPL,
|
||||
"sil" : SIL,
|
||||
"dil" : DIL,
|
||||
"r8b" : R8b,
|
||||
"r9b" : R9b,
|
||||
"r10b" : R10b,
|
||||
"r11b" : R11b,
|
||||
"r12b" : R12b,
|
||||
"r13b" : R13b,
|
||||
"r14b" : R14b,
|
||||
"r15b" : R15b,
|
||||
"ah" : AH,
|
||||
"ch" : CH,
|
||||
"dh" : DH,
|
||||
"bh" : BH,
|
||||
"ax" : AX,
|
||||
"cx" : CX,
|
||||
"dx" : DX,
|
||||
"bx" : BX,
|
||||
"sp" : SP,
|
||||
"bp" : BP,
|
||||
"si" : SI,
|
||||
"di" : DI,
|
||||
"r8w" : R8w,
|
||||
"r9w" : R9w,
|
||||
"r10w" : R10w,
|
||||
"r11w" : R11w,
|
||||
"r12w" : R12w,
|
||||
"r13w" : R13w,
|
||||
"r14w" : R14w,
|
||||
"r15w" : R15w,
|
||||
"eax" : EAX,
|
||||
"ecx" : ECX,
|
||||
"edx" : EDX,
|
||||
"ebx" : EBX,
|
||||
"esp" : ESP,
|
||||
"ebp" : EBP,
|
||||
"esi" : ESI,
|
||||
"edi" : EDI,
|
||||
"r8d" : R8d,
|
||||
"r9d" : R9d,
|
||||
"r10d" : R10d,
|
||||
"r11d" : R11d,
|
||||
"r12d" : R12d,
|
||||
"r13d" : R13d,
|
||||
"r14d" : R14d,
|
||||
"r15d" : R15d,
|
||||
"rax" : RAX,
|
||||
"rcx" : RCX,
|
||||
"rdx" : RDX,
|
||||
"rbx" : RBX,
|
||||
"rsp" : RSP,
|
||||
"rbp" : RBP,
|
||||
"rsi" : RSI,
|
||||
"rdi" : RDI,
|
||||
"r8" : R8,
|
||||
"r9" : R9,
|
||||
"r10" : R10,
|
||||
"r11" : R11,
|
||||
"r12" : R12,
|
||||
"r13" : R13,
|
||||
"r14" : R14,
|
||||
"r15" : R15,
|
||||
"k0" : K0,
|
||||
"k1" : K1,
|
||||
"k2" : K2,
|
||||
"k3" : K3,
|
||||
"k4" : K4,
|
||||
"k5" : K5,
|
||||
"k6" : K6,
|
||||
"k7" : K7,
|
||||
"mm0" : MM0,
|
||||
"mm1" : MM1,
|
||||
"mm2" : MM2,
|
||||
"mm3" : MM3,
|
||||
"mm4" : MM4,
|
||||
"mm5" : MM5,
|
||||
"mm6" : MM6,
|
||||
"mm7" : MM7,
|
||||
"xmm0" : XMM0,
|
||||
"xmm1" : XMM1,
|
||||
"xmm2" : XMM2,
|
||||
"xmm3" : XMM3,
|
||||
"xmm4" : XMM4,
|
||||
"xmm5" : XMM5,
|
||||
"xmm6" : XMM6,
|
||||
"xmm7" : XMM7,
|
||||
"xmm8" : XMM8,
|
||||
"xmm9" : XMM9,
|
||||
"xmm10" : XMM10,
|
||||
"xmm11" : XMM11,
|
||||
"xmm12" : XMM12,
|
||||
"xmm13" : XMM13,
|
||||
"xmm14" : XMM14,
|
||||
"xmm15" : XMM15,
|
||||
"xmm16" : XMM16,
|
||||
"xmm17" : XMM17,
|
||||
"xmm18" : XMM18,
|
||||
"xmm19" : XMM19,
|
||||
"xmm20" : XMM20,
|
||||
"xmm21" : XMM21,
|
||||
"xmm22" : XMM22,
|
||||
"xmm23" : XMM23,
|
||||
"xmm24" : XMM24,
|
||||
"xmm25" : XMM25,
|
||||
"xmm26" : XMM26,
|
||||
"xmm27" : XMM27,
|
||||
"xmm28" : XMM28,
|
||||
"xmm29" : XMM29,
|
||||
"xmm30" : XMM30,
|
||||
"xmm31" : XMM31,
|
||||
"ymm0" : YMM0,
|
||||
"ymm1" : YMM1,
|
||||
"ymm2" : YMM2,
|
||||
"ymm3" : YMM3,
|
||||
"ymm4" : YMM4,
|
||||
"ymm5" : YMM5,
|
||||
"ymm6" : YMM6,
|
||||
"ymm7" : YMM7,
|
||||
"ymm8" : YMM8,
|
||||
"ymm9" : YMM9,
|
||||
"ymm10" : YMM10,
|
||||
"ymm11" : YMM11,
|
||||
"ymm12" : YMM12,
|
||||
"ymm13" : YMM13,
|
||||
"ymm14" : YMM14,
|
||||
"ymm15" : YMM15,
|
||||
"ymm16" : YMM16,
|
||||
"ymm17" : YMM17,
|
||||
"ymm18" : YMM18,
|
||||
"ymm19" : YMM19,
|
||||
"ymm20" : YMM20,
|
||||
"ymm21" : YMM21,
|
||||
"ymm22" : YMM22,
|
||||
"ymm23" : YMM23,
|
||||
"ymm24" : YMM24,
|
||||
"ymm25" : YMM25,
|
||||
"ymm26" : YMM26,
|
||||
"ymm27" : YMM27,
|
||||
"ymm28" : YMM28,
|
||||
"ymm29" : YMM29,
|
||||
"ymm30" : YMM30,
|
||||
"ymm31" : YMM31,
|
||||
"zmm0" : ZMM0,
|
||||
"zmm1" : ZMM1,
|
||||
"zmm2" : ZMM2,
|
||||
"zmm3" : ZMM3,
|
||||
"zmm4" : ZMM4,
|
||||
"zmm5" : ZMM5,
|
||||
"zmm6" : ZMM6,
|
||||
"zmm7" : ZMM7,
|
||||
"zmm8" : ZMM8,
|
||||
"zmm9" : ZMM9,
|
||||
"zmm10" : ZMM10,
|
||||
"zmm11" : ZMM11,
|
||||
"zmm12" : ZMM12,
|
||||
"zmm13" : ZMM13,
|
||||
"zmm14" : ZMM14,
|
||||
"zmm15" : ZMM15,
|
||||
"zmm16" : ZMM16,
|
||||
"zmm17" : ZMM17,
|
||||
"zmm18" : ZMM18,
|
||||
"zmm19" : ZMM19,
|
||||
"zmm20" : ZMM20,
|
||||
"zmm21" : ZMM21,
|
||||
"zmm22" : ZMM22,
|
||||
"zmm23" : ZMM23,
|
||||
"zmm24" : ZMM24,
|
||||
"zmm25" : ZMM25,
|
||||
"zmm26" : ZMM26,
|
||||
"zmm27" : ZMM27,
|
||||
"zmm28" : ZMM28,
|
||||
"zmm29" : ZMM29,
|
||||
"zmm30" : ZMM30,
|
||||
"zmm31" : ZMM31,
|
||||
}
|
||||
|
||||
/** Register Name Tables **/
|
||||
|
||||
var r8names = [...]string {
|
||||
AL : "al",
|
||||
CL : "cl",
|
||||
DL : "dl",
|
||||
BL : "bl",
|
||||
SPL : "spl",
|
||||
BPL : "bpl",
|
||||
SIL : "sil",
|
||||
DIL : "dil",
|
||||
R8b : "r8b",
|
||||
R9b : "r9b",
|
||||
R10b : "r10b",
|
||||
R11b : "r11b",
|
||||
R12b : "r12b",
|
||||
R13b : "r13b",
|
||||
R14b : "r14b",
|
||||
R15b : "r15b",
|
||||
AH : "ah",
|
||||
CH : "ch",
|
||||
DH : "dh",
|
||||
BH : "bh",
|
||||
}
|
||||
|
||||
var r16names = [...]string {
|
||||
AX : "ax",
|
||||
CX : "cx",
|
||||
DX : "dx",
|
||||
BX : "bx",
|
||||
SP : "sp",
|
||||
BP : "bp",
|
||||
SI : "si",
|
||||
DI : "di",
|
||||
R8w : "r8w",
|
||||
R9w : "r9w",
|
||||
R10w : "r10w",
|
||||
R11w : "r11w",
|
||||
R12w : "r12w",
|
||||
R13w : "r13w",
|
||||
R14w : "r14w",
|
||||
R15w : "r15w",
|
||||
}
|
||||
|
||||
var r32names = [...]string {
|
||||
EAX : "eax",
|
||||
ECX : "ecx",
|
||||
EDX : "edx",
|
||||
EBX : "ebx",
|
||||
ESP : "esp",
|
||||
EBP : "ebp",
|
||||
ESI : "esi",
|
||||
EDI : "edi",
|
||||
R8d : "r8d",
|
||||
R9d : "r9d",
|
||||
R10d : "r10d",
|
||||
R11d : "r11d",
|
||||
R12d : "r12d",
|
||||
R13d : "r13d",
|
||||
R14d : "r14d",
|
||||
R15d : "r15d",
|
||||
}
|
||||
|
||||
var r64names = [...]string {
|
||||
RAX : "rax",
|
||||
RCX : "rcx",
|
||||
RDX : "rdx",
|
||||
RBX : "rbx",
|
||||
RSP : "rsp",
|
||||
RBP : "rbp",
|
||||
RSI : "rsi",
|
||||
RDI : "rdi",
|
||||
R8 : "r8",
|
||||
R9 : "r9",
|
||||
R10 : "r10",
|
||||
R11 : "r11",
|
||||
R12 : "r12",
|
||||
R13 : "r13",
|
||||
R14 : "r14",
|
||||
R15 : "r15",
|
||||
}
|
||||
|
||||
var knames = [...]string {
|
||||
K0: "k0",
|
||||
K1: "k1",
|
||||
K2: "k2",
|
||||
K3: "k3",
|
||||
K4: "k4",
|
||||
K5: "k5",
|
||||
K6: "k6",
|
||||
K7: "k7",
|
||||
}
|
||||
|
||||
var mmnames = [...]string {
|
||||
MM0: "mm0",
|
||||
MM1: "mm1",
|
||||
MM2: "mm2",
|
||||
MM3: "mm3",
|
||||
MM4: "mm4",
|
||||
MM5: "mm5",
|
||||
MM6: "mm6",
|
||||
MM7: "mm7",
|
||||
}
|
||||
|
||||
var xmmnames = [...]string {
|
||||
XMM0 : "xmm0",
|
||||
XMM1 : "xmm1",
|
||||
XMM2 : "xmm2",
|
||||
XMM3 : "xmm3",
|
||||
XMM4 : "xmm4",
|
||||
XMM5 : "xmm5",
|
||||
XMM6 : "xmm6",
|
||||
XMM7 : "xmm7",
|
||||
XMM8 : "xmm8",
|
||||
XMM9 : "xmm9",
|
||||
XMM10 : "xmm10",
|
||||
XMM11 : "xmm11",
|
||||
XMM12 : "xmm12",
|
||||
XMM13 : "xmm13",
|
||||
XMM14 : "xmm14",
|
||||
XMM15 : "xmm15",
|
||||
XMM16 : "xmm16",
|
||||
XMM17 : "xmm17",
|
||||
XMM18 : "xmm18",
|
||||
XMM19 : "xmm19",
|
||||
XMM20 : "xmm20",
|
||||
XMM21 : "xmm21",
|
||||
XMM22 : "xmm22",
|
||||
XMM23 : "xmm23",
|
||||
XMM24 : "xmm24",
|
||||
XMM25 : "xmm25",
|
||||
XMM26 : "xmm26",
|
||||
XMM27 : "xmm27",
|
||||
XMM28 : "xmm28",
|
||||
XMM29 : "xmm29",
|
||||
XMM30 : "xmm30",
|
||||
XMM31 : "xmm31",
|
||||
}
|
||||
|
||||
var ymmnames = [...]string {
|
||||
YMM0 : "ymm0",
|
||||
YMM1 : "ymm1",
|
||||
YMM2 : "ymm2",
|
||||
YMM3 : "ymm3",
|
||||
YMM4 : "ymm4",
|
||||
YMM5 : "ymm5",
|
||||
YMM6 : "ymm6",
|
||||
YMM7 : "ymm7",
|
||||
YMM8 : "ymm8",
|
||||
YMM9 : "ymm9",
|
||||
YMM10 : "ymm10",
|
||||
YMM11 : "ymm11",
|
||||
YMM12 : "ymm12",
|
||||
YMM13 : "ymm13",
|
||||
YMM14 : "ymm14",
|
||||
YMM15 : "ymm15",
|
||||
YMM16 : "ymm16",
|
||||
YMM17 : "ymm17",
|
||||
YMM18 : "ymm18",
|
||||
YMM19 : "ymm19",
|
||||
YMM20 : "ymm20",
|
||||
YMM21 : "ymm21",
|
||||
YMM22 : "ymm22",
|
||||
YMM23 : "ymm23",
|
||||
YMM24 : "ymm24",
|
||||
YMM25 : "ymm25",
|
||||
YMM26 : "ymm26",
|
||||
YMM27 : "ymm27",
|
||||
YMM28 : "ymm28",
|
||||
YMM29 : "ymm29",
|
||||
YMM30 : "ymm30",
|
||||
YMM31 : "ymm31",
|
||||
}
|
||||
|
||||
var zmmnames = [...]string {
|
||||
ZMM0 : "zmm0",
|
||||
ZMM1 : "zmm1",
|
||||
ZMM2 : "zmm2",
|
||||
ZMM3 : "zmm3",
|
||||
ZMM4 : "zmm4",
|
||||
ZMM5 : "zmm5",
|
||||
ZMM6 : "zmm6",
|
||||
ZMM7 : "zmm7",
|
||||
ZMM8 : "zmm8",
|
||||
ZMM9 : "zmm9",
|
||||
ZMM10 : "zmm10",
|
||||
ZMM11 : "zmm11",
|
||||
ZMM12 : "zmm12",
|
||||
ZMM13 : "zmm13",
|
||||
ZMM14 : "zmm14",
|
||||
ZMM15 : "zmm15",
|
||||
ZMM16 : "zmm16",
|
||||
ZMM17 : "zmm17",
|
||||
ZMM18 : "zmm18",
|
||||
ZMM19 : "zmm19",
|
||||
ZMM20 : "zmm20",
|
||||
ZMM21 : "zmm21",
|
||||
ZMM22 : "zmm22",
|
||||
ZMM23 : "zmm23",
|
||||
ZMM24 : "zmm24",
|
||||
ZMM25 : "zmm25",
|
||||
ZMM26 : "zmm26",
|
||||
ZMM27 : "zmm27",
|
||||
ZMM28 : "zmm28",
|
||||
ZMM29 : "zmm29",
|
||||
ZMM30 : "zmm30",
|
||||
ZMM31 : "zmm31",
|
||||
}
|
147
vendor/github.com/cloudwego/iasm/x86_64/utils.go
generated
vendored
147
vendor/github.com/cloudwego/iasm/x86_64/utils.go
generated
vendored
@ -1,147 +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 (
|
||||
`encoding/binary`
|
||||
`errors`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`unicode/utf8`
|
||||
`unsafe`
|
||||
)
|
||||
|
||||
const (
|
||||
_CC_digit = 1 << iota
|
||||
_CC_ident
|
||||
_CC_ident0
|
||||
_CC_number
|
||||
)
|
||||
|
||||
func ispow2(v uint64) bool {
|
||||
return (v & (v - 1)) == 0
|
||||
}
|
||||
|
||||
func isdigit(cc rune) bool {
|
||||
return '0' <= cc && cc <= '9'
|
||||
}
|
||||
|
||||
func isalpha(cc rune) bool {
|
||||
return (cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')
|
||||
}
|
||||
|
||||
func isident(cc rune) bool {
|
||||
return cc == '_' || isalpha(cc) || isdigit(cc)
|
||||
}
|
||||
|
||||
func isident0(cc rune) bool {
|
||||
return cc == '_' || isalpha(cc)
|
||||
}
|
||||
|
||||
func isnumber(cc rune) bool {
|
||||
return (cc == 'b' || cc == 'B') ||
|
||||
(cc == 'o' || cc == 'O') ||
|
||||
(cc == 'x' || cc == 'X') ||
|
||||
(cc >= '0' && cc <= '9') ||
|
||||
(cc >= 'a' && cc <= 'f') ||
|
||||
(cc >= 'A' && cc <= 'F')
|
||||
}
|
||||
|
||||
func align(v int, n int) int {
|
||||
return (((v - 1) >> n) + 1) << n
|
||||
}
|
||||
|
||||
func append8(m *[]byte, v byte) {
|
||||
*m = append(*m, v)
|
||||
}
|
||||
|
||||
func append16(m *[]byte, v uint16) {
|
||||
p := len(*m)
|
||||
*m = append(*m, 0, 0)
|
||||
binary.LittleEndian.PutUint16((*m)[p:], v)
|
||||
}
|
||||
|
||||
func append32(m *[]byte, v uint32) {
|
||||
p := len(*m)
|
||||
*m = append(*m, 0, 0, 0, 0)
|
||||
binary.LittleEndian.PutUint32((*m)[p:], v)
|
||||
}
|
||||
|
||||
func append64(m *[]byte, v uint64) {
|
||||
p := len(*m)
|
||||
*m = append(*m, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
binary.LittleEndian.PutUint64((*m)[p:], v)
|
||||
}
|
||||
|
||||
func expandmm(m *[]byte, n int, v byte) {
|
||||
sl := (*_GoSlice)(unsafe.Pointer(m))
|
||||
nb := sl.len + n
|
||||
|
||||
/* grow as needed */
|
||||
if nb > cap(*m) {
|
||||
*m = growslice(byteType, *m, nb)
|
||||
}
|
||||
|
||||
/* fill the new area */
|
||||
memset(unsafe.Pointer(uintptr(sl.ptr) + uintptr(sl.len)), v, uintptr(n))
|
||||
sl.len = nb
|
||||
}
|
||||
|
||||
func memset(p unsafe.Pointer, c byte, n uintptr) {
|
||||
if c != 0 {
|
||||
memsetv(p, c, n)
|
||||
} else {
|
||||
memclrNoHeapPointers(p, n)
|
||||
}
|
||||
}
|
||||
|
||||
func memsetv(p unsafe.Pointer, c byte, n uintptr) {
|
||||
for i := uintptr(0); i < n; i++ {
|
||||
*(*byte)(unsafe.Pointer(uintptr(p) + i)) = c
|
||||
}
|
||||
}
|
||||
|
||||
func literal64(v string) (uint64, error) {
|
||||
var nb int
|
||||
var ch rune
|
||||
var ex error
|
||||
var mm [12]byte
|
||||
|
||||
/* unquote the runes */
|
||||
for v != "" {
|
||||
if ch, _, v, ex = strconv.UnquoteChar(v, '\''); ex != nil {
|
||||
return 0, ex
|
||||
} else if nb += utf8.EncodeRune(mm[nb:], ch); nb > 8 {
|
||||
return 0, errors.New("multi-char constant too large")
|
||||
}
|
||||
}
|
||||
|
||||
/* convert to uint64 */
|
||||
return *(*uint64)(unsafe.Pointer(&mm)), nil
|
||||
}
|
||||
|
||||
var (
|
||||
byteWrap = reflect.TypeOf(byte(0))
|
||||
byteType = (*_GoType)(efaceOf(byteWrap).ptr)
|
||||
)
|
||||
|
||||
//go:linkname growslice runtime.growslice
|
||||
func growslice(_ *_GoType, _ []byte, _ int) []byte
|
||||
|
||||
//go:noescape
|
||||
//go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
|
||||
func memclrNoHeapPointers(_ unsafe.Pointer, _ uintptr)
|
Reference in New Issue
Block a user