mirror of
https://github.com/yuzu-mirror/oaknut.git
synced 2026-03-03 08:53:50 +01:00
First commit
This commit is contained in:
commit
ff3eb7a796
218
.clang-format
Normal file
218
.clang-format
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: AlignAfterOperator
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
# EmptyLineAfterAccessModifier: Leave
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<mach/'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<windows.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '(^<signal.h>)|(^<sys/ucontext.h>)|(^<ucontext.h>)'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<([^\.])*>$'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 4
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: NoIndent
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
# InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
NamespaceMacros:
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
# ShortNamespaceLines: 5
|
||||
SortIncludes: true
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
# SpacesInLineCommentPrefix: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
TypenameMacros:
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
- FCODE
|
||||
- ICODE
|
||||
...
|
||||
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.DS_Store
|
||||
a.out
|
||||
*work*/
|
||||
*build*/
|
||||
398
include/oaknut/impl/arm64_mnemonics.inc
Normal file
398
include/oaknut/impl/arm64_mnemonics.inc
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
void ADC(WReg wd, WReg wn, WReg wm) { emit<"00011010000mmmmm000000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void ADC(XReg xd, XReg xn, XReg xm) { emit<"10011010000mmmmm000000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void ADCS(WReg wd, WReg wn, WReg wm) { emit<"00111010000mmmmm000000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void ADCS(XReg xd, XReg xn, XReg xm) { emit<"10111010000mmmmm000000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void ADD(WRegWsp wd, WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wd); emit<"00001011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(wd, wn, wm, ext, shift_amount); }
|
||||
void ADD(XRegSp xd, XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xd); emit<"10001011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(xd, xn, rm, ext, shift_amount); }
|
||||
void ADD(WRegWsp wd, WRegWsp wn, AddSubImm imm) { emit<"000100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(wd, wn, imm); }
|
||||
void ADD(XRegSp xd, XRegSp xn, AddSubImm imm) { emit<"100100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(xd, xn, imm); }
|
||||
void ADD(WReg wd, WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"00001011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void ADD(XReg xd, XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"10001011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ADDS(WReg wd, WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wd); emit<"00101011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(wd, wn, wm, ext, shift_amount); }
|
||||
void ADDS(XReg xd, XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xd); emit<"10101011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(xd, xn, rm, ext, shift_amount); }
|
||||
void ADDS(WReg wd, WRegWsp wn, AddSubImm imm) { emit<"001100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(wd, wn, imm); }
|
||||
void ADDS(XReg xd, XRegSp xn, AddSubImm imm) { emit<"101100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(xd, xn, imm); }
|
||||
void ADDS(WReg wd, WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"00101011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void ADDS(XReg xd, XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"10101011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ADR(XReg xd, AddrOffset<21, 0> label) { emit<"0ii10000iiiiiiiiiiiiiiiiiiiddddd", "d", "i">(xd, label); }
|
||||
void ADRP(XReg xd, PageOffset<21> label) { emit<"1ii10000iiiiiiiiiiiiiiiiiiiddddd", "d", "i">(xd, label); }
|
||||
void AND(WRegWsp wd, WReg wn, BitImm32 imm) { emit<"0001001000rrrrrrssssssnnnnnddddd", "d", "n", "rs">(wd, wn, imm); }
|
||||
void AND(XRegSp xd, XReg xn, BitImm64 imm) { emit<"100100100Nrrrrrrssssssnnnnnddddd", "d", "n", "Nrs">(xd, xn, imm); }
|
||||
void AND(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"00001010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void AND(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"10001010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ANDS(WReg wd, WReg wn, BitImm32 imm) { emit<"0111001000rrrrrrssssssnnnnnddddd", "d", "n", "rs">(wd, wn, imm); }
|
||||
void ANDS(XReg xd, XReg xn, BitImm64 imm) { emit<"111100100Nrrrrrrssssssnnnnnddddd", "d", "n", "Nrs">(xd, xn, imm); }
|
||||
void ANDS(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"01101010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void ANDS(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"11101010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ASR(WReg wd, WReg wn, Imm<5> shift_amount) { emit<"0001001100rrrrrr011111nnnnnddddd", "d", "n", "r">(wd, wn, shift_amount); }
|
||||
void ASR(XReg xd, XReg xn, Imm<6> shift_amount) { emit<"1001001101rrrrrr111111nnnnnddddd", "d", "n", "r">(xd, xn, shift_amount); }
|
||||
void ASR(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001010nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void ASR(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001010nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void ASRV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001010nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void ASRV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001010nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void AT(AtOp op, XReg xt) { emit<"1101010100001ooo0111100Mooottttt", "oMo", "t">(op, xt); }
|
||||
void B(AddrOffset<28, 2> label) { emit<"000101iiiiiiiiiiiiiiiiiiiiiiiiii", "i">(label); }
|
||||
void B(Cond cond, AddrOffset<21, 2> label) { emit<"01010100iiiiiiiiiiiiiiiiiii0cccc", "c", "i">(cond, label); }
|
||||
void BFI(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void BFI(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void BFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) { emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, immr, imms); }
|
||||
void BFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms) { emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, immr, imms); }
|
||||
void BFXIL(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void BFXIL(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void BIC(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"00001010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void BIC(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"10001010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void BICS(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"01101010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void BICS(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"11101010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void BL(AddrOffset<28, 2> label) { emit<"100101iiiiiiiiiiiiiiiiiiiiiiiiii", "i">(label); }
|
||||
void BLR(XReg xn) { emit<"1101011000111111000000nnnnn00000", "n">(xn); }
|
||||
void BR(XReg xn) { emit<"1101011000011111000000nnnnn00000", "n">(xn); }
|
||||
void BRK(Imm<16> imm) { emit<"11010100001iiiiiiiiiiiiiiii00000", "i">(imm); }
|
||||
void CBNZ(WReg wt, AddrOffset<21, 2> label) { emit<"00110101iiiiiiiiiiiiiiiiiiittttt", "t", "i">(wt, label); }
|
||||
void CBNZ(XReg xt, AddrOffset<21, 2> label) { emit<"10110101iiiiiiiiiiiiiiiiiiittttt", "t", "i">(xt, label); }
|
||||
void CBZ(WReg wt, AddrOffset<21, 2> label) { emit<"00110100iiiiiiiiiiiiiiiiiiittttt", "t", "i">(wt, label); }
|
||||
void CBZ(XReg xt, AddrOffset<21, 2> label) { emit<"10110100iiiiiiiiiiiiiiiiiiittttt", "t", "i">(xt, label); }
|
||||
void CCMN(WReg wn, Imm<5> imm, Imm<4> nzcv, Cond cond) { emit<"00111010010iiiiicccc10nnnnn0ffff", "n", "i", "f", "c">(wn, imm, nzcv, cond); }
|
||||
void CCMN(XReg xn, Imm<5> imm, Imm<4> nzcv, Cond cond) { emit<"10111010010iiiiicccc10nnnnn0ffff", "n", "i", "f", "c">(xn, imm, nzcv, cond); }
|
||||
void CCMN(WReg wn, WReg wm, Imm<4> nzcv, Cond cond) { emit<"00111010010mmmmmcccc00nnnnn0ffff", "n", "m", "f", "c">(wn, wm, nzcv, cond); }
|
||||
void CCMN(XReg xn, XReg xm, Imm<4> nzcv, Cond cond) { emit<"10111010010mmmmmcccc00nnnnn0ffff", "n", "m", "f", "c">(xn, xm, nzcv, cond); }
|
||||
void CCMP(WReg wn, Imm<5> imm, Imm<4> nzcv, Cond cond) { emit<"01111010010iiiiicccc10nnnnn0ffff", "n", "i", "f", "c">(wn, imm, nzcv, cond); }
|
||||
void CCMP(XReg xn, Imm<5> imm, Imm<4> nzcv, Cond cond) { emit<"11111010010iiiiicccc10nnnnn0ffff", "n", "i", "f", "c">(xn, imm, nzcv, cond); }
|
||||
void CCMP(WReg wn, WReg wm, Imm<4> nzcv, Cond cond) { emit<"01111010010mmmmmcccc00nnnnn0ffff", "n", "m", "f", "c">(wn, wm, nzcv, cond); }
|
||||
void CCMP(XReg xn, XReg xm, Imm<4> nzcv, Cond cond) { emit<"11111010010mmmmmcccc00nnnnn0ffff", "n", "m", "f", "c">(xn, xm, nzcv, cond); }
|
||||
void CINC(WReg wd, WReg wn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"00011010100mmmmmcccc01nnnnnddddd", "d", "n", "c">(wd, wn, invert(cond)); }
|
||||
void CINC(XReg xd, XReg xn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"10011010100mmmmmcccc01nnnnnddddd", "d", "n", "c">(xd, xn, invert(cond)); }
|
||||
void CINV(WReg wd, WReg wn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"01011010100mmmmmcccc00nnnnnddddd", "d", "n", "c">(wd, wn, invert(cond)); }
|
||||
void CINV(XReg xd, XReg xn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"11011010100mmmmmcccc00nnnnnddddd", "d", "n", "c">(xd, xn, invert(cond)); }
|
||||
void CLREX(Imm<4> imm = 15) { emit<"11010101000000110011MMMM01011111", "M">(imm); }
|
||||
void CLS(WReg wd, WReg wn) { emit<"0101101011000000000101nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void CLS(XReg xd, XReg xn) { emit<"1101101011000000000101nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void CLZ(WReg wd, WReg wn) { emit<"0101101011000000000100nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void CLZ(XReg xd, XReg xn) { emit<"1101101011000000000100nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void CMN(WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wn); emit<"00101011001mmmmmxxxiiinnnnn11111", "n", "m", "x", "i">(wn, wm, ext, shift_amount); }
|
||||
void CMN(XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xn); emit<"10101011001mmmmmxxxiiinnnnn11111", "n", "m", "x", "i">(xn, rm, ext, shift_amount); }
|
||||
void CMN(WRegWsp wn, AddSubImm imm) { emit<"001100010siiiiiiiiiiiinnnnn11111", "n", "si">(wn, imm); }
|
||||
void CMN(XRegSp xn, AddSubImm imm) { emit<"101100010siiiiiiiiiiiinnnnn11111", "n", "si">(xn, imm); }
|
||||
void CMN(WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"00101011ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(wn, wm, shift, shift_amount); }
|
||||
void CMN(XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"10101011ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(xn, xm, shift, shift_amount); }
|
||||
void CMP(WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wn); emit<"01101011001mmmmmxxxiiinnnnn11111", "n", "m", "x", "i">(wn, wm, ext, shift_amount); }
|
||||
void CMP(XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xn); emit<"11101011001mmmmmxxxiiinnnnn11111", "n", "m", "x", "i">(xn, rm, ext, shift_amount); }
|
||||
void CMP(WRegWsp wn, AddSubImm imm) { emit<"011100010siiiiiiiiiiiinnnnn11111", "n", "si">(wn, imm); }
|
||||
void CMP(XRegSp xn, AddSubImm imm) { emit<"111100010siiiiiiiiiiiinnnnn11111", "n", "si">(xn, imm); }
|
||||
void CMP(WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"01101011ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(wn, wm, shift, shift_amount); }
|
||||
void CMP(XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"11101011ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(xn, xm, shift, shift_amount); }
|
||||
void CNEG(WReg wd, WReg wn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"01011010100mmmmmcccc01nnnnnddddd", "d", "n", "c">(wd, wn, invert(cond)); }
|
||||
void CNEG(XReg xd, XReg xn, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"11011010100mmmmmcccc01nnnnnddddd", "d", "n", "c">(xd, xn, invert(cond)); }
|
||||
void CRC32B(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32H(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010001nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32W(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010010nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32X(WReg wd, WReg wn, XReg xm) { emit<"10011010110mmmmm010011nnnnnddddd", "d", "n", "m">(wd, wn, xm); }
|
||||
void CRC32CB(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010100nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32CH(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010101nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32CW(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm010110nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void CRC32CX(WReg wd, WReg wn, XReg xm) { emit<"10011010110mmmmm010111nnnnnddddd", "d", "n", "m">(wd, wn, xm); }
|
||||
void CSDB() { emit<"11010101000000110010001010011111">(); }
|
||||
void CSEL(WReg wd, WReg wn, WReg wm, Cond cond) { emit<"00011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(wd, wn, wm, cond); }
|
||||
void CSEL(XReg xd, XReg xn, XReg xm, Cond cond) { emit<"10011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(xd, xn, xm, cond); }
|
||||
void CSET(WReg wd, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"0001101010011111cccc0111111ddddd", "d", "c">(wd, invert(cond)); }
|
||||
void CSET(XReg xd, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"1001101010011111cccc0111111ddddd", "d", "c">(xd, invert(cond)); }
|
||||
void CSETM(WReg wd, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"0101101010011111cccc0011111ddddd", "d", "c">(wd, invert(cond)); }
|
||||
void CSETM(XReg xd, Cond cond) { if (cond != Cond::AL && cond != Cond::NV) throw "invalid Cond"; emit<"1101101010011111cccc0011111ddddd", "d", "c">(xd, invert(cond)); }
|
||||
void CSINC(WReg wd, WReg wn, WReg wm, Cond cond) { emit<"00011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wm, cond); }
|
||||
void CSINC(XReg xd, XReg xn, XReg xm, Cond cond) { emit<"10011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xm, cond); }
|
||||
void CSINV(WReg wd, WReg wn, WReg wm, Cond cond) { emit<"01011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(wd, wn, wm, cond); }
|
||||
void CSINV(XReg xd, XReg xn, XReg xm, Cond cond) { emit<"11011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(xd, xn, xm, cond); }
|
||||
void CSNEG(WReg wd, WReg wn, WReg wm, Cond cond) { emit<"01011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wm, cond); }
|
||||
void CSNEG(XReg xd, XReg xn, XReg xm, Cond cond) { emit<"11011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xm, cond); }
|
||||
void DC(DcOp op, XReg xt) { emit<"1101010100001ooo0111MMMMooottttt", "oMo", "t">(op, xt); }
|
||||
void DCPS1(Imm<16> imm = 0) { emit<"11010100101iiiiiiiiiiiiiiii00001", "i">(imm); }
|
||||
void DCPS2(Imm<16> imm = 0) { emit<"11010100101iiiiiiiiiiiiiiii00010", "i">(imm); }
|
||||
void DMB(BarrierOp imm) { emit<"11010101000000110011MMMM10111111", "M">(imm); }
|
||||
void DRPS() { emit<"11010110101111110000001111100000">(); }
|
||||
void DSB(BarrierOp imm) { emit<"11010101000000110011MMMM10011111", "M">(imm); }
|
||||
void EON(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"01001010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void EON(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"11001010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void EOR(WRegWsp wd, WReg wn, BitImm32 imm) { emit<"0101001000rrrrrrssssssnnnnnddddd", "d", "n", "rs">(wd, wn, imm); }
|
||||
void EOR(XRegSp xd, XReg xn, BitImm64 imm) { emit<"110100100Nrrrrrrssssssnnnnnddddd", "d", "n", "Nrs">(xd, xn, imm); }
|
||||
void EOR(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"01001010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void EOR(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"11001010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ERET() { emit<"11010110100111110000001111100000">(); }
|
||||
void EXTR(WReg wd, WReg wn, WReg wm, Imm<5> imms) { emit<"00010011100mmmmm0sssssnnnnnddddd", "d", "n", "m", "s">(wd, wn, wm, imms); }
|
||||
void EXTR(XReg xd, XReg xn, XReg xm, Imm<6> imms) { emit<"10010011110mmmmmssssssnnnnnddddd", "d", "n", "m", "s">(xd, xn, xm, imms); }
|
||||
void HINT(Imm<7> imm) { emit<"11010101000000110010MMMMooo11111", "Mo">(imm); }
|
||||
void HLT(Imm<16> imm) { emit<"11010100010iiiiiiiiiiiiiiii00000", "i">(imm); }
|
||||
void HVC(Imm<16> imm) { emit<"11010100000iiiiiiiiiiiiiiii00010", "i">(imm); }
|
||||
void IC(IcOp op, XReg xt) { emit<"1101010100001ooo0111MMMMooottttt", "oMo", "t">(op, xt); }
|
||||
void ISB(BarrierOp imm = BarrierOp::SY) { emit<"11010101000000110011MMMM11011111", "M">(imm); }
|
||||
void LDAR(WReg wt, XRegSp xn) { emit<"1000100011011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDAR(XReg xt, XRegSp xn) { emit<"1100100011011111111111nnnnnttttt", "t", "n">(xt, xn); }
|
||||
void LDARB(WReg wt, XRegSp xn) { emit<"0000100011011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDARH(WReg wt, XRegSp xn) { emit<"0100100011011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDAXP(WReg wt1, WReg wt2, XRegSp xn) { emit<"10001000011111111uuuuunnnnnttttt", "t", "u", "n">(wt1, wt2, xn); }
|
||||
void LDAXP(XReg xt1, XReg xt2, XRegSp xn) { emit<"11001000011111111uuuuunnnnnttttt", "t", "u", "n">(xt1, xt2, xn); }
|
||||
void LDAXR(WReg wt, XRegSp xn) { emit<"1000100001011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDAXR(XReg xt, XRegSp xn) { emit<"1100100001011111111111nnnnnttttt", "t", "n">(xt, xn); }
|
||||
void LDAXRB(WReg wt, XRegSp xn) { emit<"0000100001011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDAXRH(WReg wt, XRegSp xn) { emit<"0100100001011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDNP(WReg wt1, WReg wt2, XRegSp xn, SOffset<9, 2> imm = 0) { emit<"0010100001iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void LDNP(XReg xt1, XReg xt2, XRegSp xn, SOffset<10, 3> imm = 0) { emit<"1010100001iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDP(WReg wt1, WReg wt2, XRegSp xn, PostIndexed, SOffset<9, 2> imm) { emit<"0010100011iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void LDP(XReg xt1, XReg xt2, XRegSp xn, PostIndexed, SOffset<10, 3> imm) { emit<"1010100011iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDP(WReg wt1, WReg wt2, XRegSp xn, PreIndexed, SOffset<9, 2> imm) { emit<"0010100111iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void LDP(XReg xt1, XReg xt2, XRegSp xn, PreIndexed, SOffset<10, 3> imm) { emit<"1010100111iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDP(WReg wt1, WReg wt2, XRegSp xn, SOffset<9, 2> imm = 0) { emit<"0010100101iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void LDP(XReg xt1, XReg xt2, XRegSp xn, SOffset<10, 3> imm = 0) { emit<"1010100101iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDPSW(XReg xt1, XReg xt2, XRegSp xn, PostIndexed, SOffset<9, 2> imm) { emit<"0110100011iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDPSW(XReg xt1, XReg xt2, XRegSp xn, PreIndexed, SOffset<9, 2> imm) { emit<"0110100111iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDPSW(XReg xt1, XReg xt2, XRegSp xn, SOffset<9, 2> imm = 0) { emit<"0110100101iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void LDR(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"10111000010iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDR(XReg xt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"11111000010iiiiiiiii01nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDR(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"10111000010iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDR(XReg xt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"11111000010iiiiiiiii11nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDR(WReg wt, XRegSp xn, POffset<14, 2> pimm = 0) { emit<"1011100101iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void LDR(XReg xt, XRegSp xn, POffset<15, 3> pimm = 0) { emit<"1111100101iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(xt, xn, pimm); }
|
||||
void LDR(WReg wt, AddrOffset<21, 2> label) { emit<"00011000iiiiiiiiiiiiiiiiiiittttt", "t", "i">(wt, label); }
|
||||
void LDR(XReg xt, AddrOffset<21, 2> label) { emit<"01011000iiiiiiiiiiiiiiiiiiittttt", "t", "i">(xt, label); }
|
||||
void LDR(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 2> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"10111000011mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void LDR(XReg xt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 3> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"11111000011mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(xt, xn, rm, ext, amount); }
|
||||
void LDRB(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"00111000010iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRB(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"00111000010iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRB(WReg wt, XRegSp xn, POffset<12, 0> pimm = 0) { emit<"0011100101iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void LDRB(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 0> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"00111000011mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void LDRH(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"01111000010iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRH(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"01111000010iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRH(WReg wt, XRegSp xn, POffset<13, 1> pimm = 0) { emit<"0111100101iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void LDRH(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 1> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"01111000011mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void LDRSB(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"00111000110iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRSB(XReg xt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"00111000100iiiiiiiii01nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSB(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"00111000110iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRSB(XReg xt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"00111000100iiiiiiiii11nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSB(WReg wt, XRegSp xn, POffset<12, 0> pimm = 0) { emit<"0011100111iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void LDRSB(XReg xt, XRegSp xn, POffset<12, 0> pimm = 0) { emit<"0011100110iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(xt, xn, pimm); }
|
||||
void LDRSB(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 0> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"00111000111mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void LDRSB(WReg wt, XRegSp xn, XReg xm, ImmChoice<0, 0> amount = 0) { emit<"00111000111mmmmm011S10nnnnnttttt", "t", "n", "m", "S">(wt, xn, xm, amount); }
|
||||
void LDRSB(XReg xt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 0> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"00111000101mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(xt, xn, rm, ext, amount); }
|
||||
void LDRSB(XReg xt, XRegSp xn, XReg xm, ImmChoice<0, 0> amount = 0) { emit<"00111000101mmmmm011S10nnnnnttttt", "t", "n", "m", "S">(xt, xn, xm, amount); }
|
||||
void LDRSH(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"01111000110iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRSH(XReg xt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"01111000100iiiiiiiii01nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSH(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"01111000110iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDRSH(XReg xt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"01111000100iiiiiiiii11nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSH(WReg wt, XRegSp xn, POffset<13, 1> pimm = 0) { emit<"0111100111iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void LDRSH(XReg xt, XRegSp xn, POffset<13, 1> pimm = 0) { emit<"0111100110iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(xt, xn, pimm); }
|
||||
void LDRSH(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 1> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"01111000111mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void LDRSH(XReg xt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 1> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"01111000101mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(xt, xn, rm, ext, amount); }
|
||||
void LDRSW(XReg xt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"10111000100iiiiiiiii01nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSW(XReg xt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"10111000100iiiiiiiii11nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDRSW(XReg xt, XRegSp xn, POffset<14, 2> pimm = 0) { emit<"1011100110iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(xt, xn, pimm); }
|
||||
void LDRSW(XReg xt, AddrOffset<21, 2> label) { emit<"10011000iiiiiiiiiiiiiiiiiiittttt", "t", "i">(xt, label); }
|
||||
void LDRSW(XReg xt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 2> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"10111000101mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(xt, xn, rm, ext, amount); }
|
||||
void LDTR(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000010iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDTR(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"11111000010iiiiiiiii10nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDTRB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000010iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDTRH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000010iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDTRSB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000110iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDTRSB(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000100iiiiiiiii10nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDTRSH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000110iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDTRSH(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000100iiiiiiiii10nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDTRSW(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000100iiiiiiiii10nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDUR(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000010iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDUR(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"11111000010iiiiiiiii00nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDURB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000010iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDURH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000010iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDURSB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000110iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDURSB(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000100iiiiiiiii00nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDURSH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000110iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void LDURSH(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000100iiiiiiiii00nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDURSW(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000100iiiiiiiii00nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void LDXP(WReg wt1, WReg wt2, XRegSp xn) { emit<"10001000011111110uuuuunnnnnttttt", "t", "u", "n">(wt1, wt2, xn); }
|
||||
void LDXP(XReg xt1, XReg xt2, XRegSp xn) { emit<"11001000011111110uuuuunnnnnttttt", "t", "u", "n">(xt1, xt2, xn); }
|
||||
void LDXR(WReg wt, XRegSp xn) { emit<"1000100001011111011111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDXR(XReg xt, XRegSp xn) { emit<"1100100001011111011111nnnnnttttt", "t", "n">(xt, xn); }
|
||||
void LDXRB(WReg wt, XRegSp xn) { emit<"0000100001011111011111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LDXRH(WReg wt, XRegSp xn) { emit<"0100100001011111011111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void LSL(WReg wd, WReg wn, LslShift<32> shift_amount) { emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "rs">(wd, wn, shift_amount); }
|
||||
void LSL(XReg xd, XReg xn, LslShift<64> shift_amount) { emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "rs">(xd, xn, shift_amount); }
|
||||
void LSL(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void LSL(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void LSLV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void LSLV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void LSR(WReg wd, WReg wn, Imm<5> shift_amount) { emit<"0101001100rrrrrr011111nnnnnddddd", "d", "n", "r">(wd, wn, shift_amount); }
|
||||
void LSR(XReg xd, XReg xn, Imm<6> shift_amount) { emit<"1101001101rrrrrr111111nnnnnddddd", "d", "n", "r">(xd, xn, shift_amount); }
|
||||
void LSR(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001001nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void LSR(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001001nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void LSRV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001001nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void LSRV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001001nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void MADD(WReg wd, WReg wn, WReg wm, WReg wa) { emit<"00011011000mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(wd, wn, wm, wa); }
|
||||
void MADD(XReg xd, XReg xn, XReg xm, XReg xa) { emit<"10011011000mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(xd, xn, xm, xa); }
|
||||
void MNEG(WReg wd, WReg wn, WReg wm) { emit<"00011011000mmmmm111111nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void MNEG(XReg xd, XReg xn, XReg xm) { emit<"10011011000mmmmm111111nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void MOV(WReg wd, WReg wm) { emit<"00101010000mmmmm00000011111ddddd", "d", "m">(wd, wm); }
|
||||
void MOV(XReg xd, XReg xm) { emit<"10101010000mmmmm00000011111ddddd", "d", "m">(xd, xm); }
|
||||
void MOV(WRegWsp wd, WRegWsp wn) { emit<"0001000100000000000000nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void MOV(XRegSp xd, XRegSp xn) { emit<"1001000100000000000000nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void MOVK(WReg wd, MovImm16 imm) { emit<"0111001010hiiiiiiiiiiiiiiiiddddd", "d", "hi">(wd, imm); }
|
||||
void MOVK(XReg xd, MovImm16 imm) { emit<"111100101hhiiiiiiiiiiiiiiiiddddd", "d", "hi">(xd, imm); }
|
||||
void MOVN(WReg wd, MovImm16 imm) { emit<"0001001010hiiiiiiiiiiiiiiiiddddd", "d", "hi">(wd, imm); }
|
||||
void MOVN(XReg xd, MovImm16 imm) { emit<"100100101hhiiiiiiiiiiiiiiiiddddd", "d", "hi">(xd, imm); }
|
||||
void MOVZ(WReg wd, MovImm16 imm) { emit<"0101001010hiiiiiiiiiiiiiiiiddddd", "d", "hi">(wd, imm); }
|
||||
void MOVZ(XReg xd, MovImm16 imm) { emit<"110100101hhiiiiiiiiiiiiiiiiddddd", "d", "hi">(xd, imm); }
|
||||
void MRS(XReg xt, SystemReg systemreg) { emit<"110101010011ooooNNNNMMMMooottttt", "t", "oNMo">(xt, systemreg); }
|
||||
void MSR(PstateField pstatefield, Imm<4> imm) { emit<"1101010100000ooo0100MMMMooo11111", "o", "M">(pstatefield, imm); }
|
||||
void MSR(SystemReg systemreg, XReg xt) { emit<"110101010001ooooNNNNMMMMooottttt", "oNMo", "t">(systemreg, xt); }
|
||||
void MSUB(WReg wd, WReg wn, WReg wm, WReg wa) { emit<"00011011000mmmmm1aaaaannnnnddddd", "d", "n", "m", "a">(wd, wn, wm, wa); }
|
||||
void MSUB(XReg xd, XReg xn, XReg xm, XReg xa) { emit<"10011011000mmmmm1aaaaannnnnddddd", "d", "n", "m", "a">(xd, xn, xm, xa); }
|
||||
void MUL(WReg wd, WReg wn, WReg wm) { emit<"00011011000mmmmm011111nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void MUL(XReg xd, XReg xn, XReg xm) { emit<"10011011000mmmmm011111nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void MVN(WReg wd, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"00101010ss1mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(wd, wm, shift, shift_amount); }
|
||||
void MVN(XReg xd, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"10101010ss1mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(xd, xm, shift, shift_amount); }
|
||||
void NEG(WReg wd, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"01001011ss0mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(wd, wm, shift, shift_amount); }
|
||||
void NEG(XReg xd, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"11001011ss0mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(xd, xm, shift, shift_amount); }
|
||||
void NEGS(WReg wd, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"01101011ss0mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(wd, wm, shift, shift_amount); }
|
||||
void NEGS(XReg xd, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"11101011ss0mmmmmiiiiii11111ddddd", "d", "m", "s", "i">(xd, xm, shift, shift_amount); }
|
||||
void NGC(WReg wd, WReg wm) { emit<"01011010000mmmmm00000011111ddddd", "d", "m">(wd, wm); }
|
||||
void NGC(XReg xd, XReg xm) { emit<"11011010000mmmmm00000011111ddddd", "d", "m">(xd, xm); }
|
||||
void NGCS(WReg wd, WReg wm) { emit<"01111010000mmmmm00000011111ddddd", "d", "m">(wd, wm); }
|
||||
void NGCS(XReg xd, XReg xm) { emit<"11111010000mmmmm00000011111ddddd", "d", "m">(xd, xm); }
|
||||
void NOP() { emit<"11010101000000110010000000011111">(); }
|
||||
void ORN(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"00101010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void ORN(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"10101010ss1mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void ORR(WRegWsp wd, WReg wn, BitImm32 imm) { emit<"0011001000rrrrrrssssssnnnnnddddd", "d", "n", "rs">(wd, wn, imm); }
|
||||
void ORR(XRegSp xd, XReg xn, BitImm64 imm) { emit<"101100100Nrrrrrrssssssnnnnnddddd", "d", "n", "Nrs">(xd, xn, imm); }
|
||||
void ORR(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"00101010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void ORR(XReg xd, XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"10101010ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void PRFM(PrfOp prfop, XRegSp xn, POffset<15, 3> pimm = 0) { emit<"1111100110iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(prfop, xn, pimm); }
|
||||
void PRFM(PrfOp prfop, AddrOffset<21, 2> label) { emit<"11011000iiiiiiiiiiiiiiiiiiittttt", "t", "i">(prfop, label); }
|
||||
void PRFM(PrfOp prfop, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 3> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"11111000101mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(prfop, xn, rm, ext, amount); }
|
||||
void PRFUM(PrfOp prfop, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"11111000100iiiiiiiii00nnnnnttttt", "t", "n", "i">(prfop, xn, simm); }
|
||||
void PSSBB() { emit<"11010101000000110011010010011111">(); }
|
||||
void RBIT(WReg wd, WReg wn) { emit<"0101101011000000000000nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void RBIT(XReg xd, XReg xn) { emit<"1101101011000000000000nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void RET(XReg xn) { emit<"1101011001011111000000nnnnn00000", "n">(xn); }
|
||||
void REV(WReg wd, WReg wn) { emit<"0101101011000000000010nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void REV(XReg xd, XReg xn) { emit<"1101101011000000000011nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void REV16(WReg wd, WReg wn) { emit<"0101101011000000000001nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void REV16(XReg xd, XReg xn) { emit<"1101101011000000000001nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void REV32(XReg xd, XReg xn) { emit<"1101101011000000000010nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void REV64(XReg xd, XReg xn) { emit<"1101101011000000000011nnnnnddddd", "d", "n">(xd, xn); }
|
||||
void ROR(WReg wd, WReg ws, Imm<5> shift_amount) { emit<"00010011100mmmmm0sssssnnnnnddddd", "d", "n", "m", "s">(wd, ws, ws, shift_amount); }
|
||||
void ROR(XReg xd, XReg xs, Imm<6> shift_amount) { emit<"10010011110mmmmmssssssnnnnnddddd", "d", "n", "m", "s">(xd, xs, xs, shift_amount); }
|
||||
void ROR(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001011nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void ROR(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001011nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void RORV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm001011nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void RORV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm001011nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void SB() { emit<"11010101000000110011000011111111">(); }
|
||||
void SBC(WReg wd, WReg wn, WReg wm) { emit<"01011010000mmmmm000000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void SBC(XReg xd, XReg xn, XReg xm) { emit<"11011010000mmmmm000000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void SBCS(WReg wd, WReg wn, WReg wm) { emit<"01111010000mmmmm000000nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void SBCS(XReg xd, XReg xn, XReg xm) { emit<"11111010000mmmmm000000nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void SBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void SBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void SBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) { emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, immr, imms); }
|
||||
void SBFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms) { emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, immr, imms); }
|
||||
void SBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void SBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void SDIV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm000011nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void SDIV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm000011nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void SEV() { emit<"11010101000000110010000010011111">(); }
|
||||
void SEVL() { emit<"11010101000000110010000010111111">(); }
|
||||
void SMADDL(XReg xd, WReg wn, WReg wm, XReg xa) { emit<"10011011001mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(xd, wn, wm, xa); }
|
||||
void SMNEGL(XReg xd, WReg wn, WReg wm) { emit<"10011011001mmmmm111111nnnnnddddd", "d", "n", "m">(xd, wn, wm); }
|
||||
void SMSUBL(XReg xd, WReg wn, WReg wm, XReg xa) { emit<"10011011001mmmmm1aaaaannnnnddddd", "d", "n", "m", "a">(xd, wn, wm, xa); }
|
||||
void SMULH(XReg xd, XReg xn, XReg xm) { emit<"10011011010mmmmm011111nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void SMULL(XReg xd, WReg wn, WReg wm) { emit<"10011011001mmmmm011111nnnnnddddd", "d", "n", "m">(xd, wn, wm); }
|
||||
void SSBB() { emit<"11010101000000110011000010011111">(); }
|
||||
void STLR(WReg wt, XRegSp xn) { emit<"1000100010011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void STLR(XReg xt, XRegSp xn) { emit<"1100100010011111111111nnnnnttttt", "t", "n">(xt, xn); }
|
||||
void STLRB(WReg wt, XRegSp xn) { emit<"0000100010011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void STLRH(WReg wt, XRegSp xn) { emit<"0100100010011111111111nnnnnttttt", "t", "n">(wt, xn); }
|
||||
void STLXP(WReg ws, WReg wt1, WReg wt2, XRegSp xn) { emit<"10001000001sssss1uuuuunnnnnttttt", "s", "t", "u", "n">(ws, wt1, wt2, xn); }
|
||||
void STLXP(WReg ws, XReg xt1, XReg xt2, XRegSp xn) { emit<"11001000001sssss1uuuuunnnnnttttt", "s", "t", "u", "n">(ws, xt1, xt2, xn); }
|
||||
void STLXR(WReg ws, WReg wt, XRegSp xn) { emit<"10001000000sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void STLXR(WReg ws, XReg xt, XRegSp xn) { emit<"11001000000sssss111111nnnnnttttt", "s", "t", "n">(ws, xt, xn); }
|
||||
void STLXRB(WReg ws, WReg wt, XRegSp xn) { emit<"00001000000sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void STLXRH(WReg ws, WReg wt, XRegSp xn) { emit<"01001000000sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void STNP(WReg wt1, WReg wt2, XRegSp xn, SOffset<9, 2> imm = 0) { emit<"0010100000iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void STNP(XReg xt1, XReg xt2, XRegSp xn, SOffset<10, 3> imm = 0) { emit<"1010100000iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void STP(WReg wt1, WReg wt2, XRegSp xn, PostIndexed, SOffset<9, 2> imm) { emit<"0010100010iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void STP(XReg xt1, XReg xt2, XRegSp xn, PostIndexed, SOffset<10, 3> imm) { emit<"1010100010iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void STP(WReg wt1, WReg wt2, XRegSp xn, PreIndexed, SOffset<9, 2> imm) { emit<"0010100110iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void STP(XReg xt1, XReg xt2, XRegSp xn, PreIndexed, SOffset<10, 3> imm) { emit<"1010100110iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void STP(WReg wt1, WReg wt2, XRegSp xn, SOffset<9, 2> imm = 0) { emit<"0010100100iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(wt1, wt2, xn, imm); }
|
||||
void STP(XReg xt1, XReg xt2, XRegSp xn, SOffset<10, 3> imm = 0) { emit<"1010100100iiiiiiiuuuuunnnnnttttt", "t", "u", "n", "i">(xt1, xt2, xn, imm); }
|
||||
void STR(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"10111000000iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STR(XReg xt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"11111000000iiiiiiiii01nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void STR(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"10111000000iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STR(XReg xt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"11111000000iiiiiiiii11nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void STR(WReg wt, XRegSp xn, POffset<14, 2> pimm = 0) { emit<"1011100100iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void STR(XReg xt, XRegSp xn, POffset<15, 3> pimm = 0) { emit<"1111100100iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(xt, xn, pimm); }
|
||||
void STR(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 2> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"10111000001mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void STR(XReg xt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 3> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"11111000001mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(xt, xn, rm, ext, amount); }
|
||||
void STRB(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"00111000000iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STRB(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"00111000000iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STRB(WReg wt, XRegSp xn, POffset<12, 0> pimm = 0) { emit<"0011100100iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void STRB(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 0> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"00111000001mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void STRB(WReg wt, XRegSp xn, XReg xm, ImmChoice<0, 0> amount = 0) { emit<"00111000001mmmmm011S10nnnnnttttt", "t", "n", "m", "S">(wt, xn, xm, amount); }
|
||||
void STRH(WReg wt, XRegSp xn, PostIndexed, SOffset<9, 0> simm) { emit<"01111000000iiiiiiiii01nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STRH(WReg wt, XRegSp xn, PreIndexed, SOffset<9, 0> simm) { emit<"01111000000iiiiiiiii11nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STRH(WReg wt, XRegSp xn, POffset<13, 1> pimm = 0) { emit<"0111100100iiiiiiiiiiiinnnnnttttt", "t", "n", "i">(wt, xn, pimm); }
|
||||
void STRH(WReg wt, XRegSp xn, RReg rm, IndexExt ext = IndexExt::LSL, ImmChoice<0, 1> amount = 0) { indexext_verify_reg_size(ext, rm); emit<"01111000001mmmmmxxxS10nnnnnttttt", "t", "n", "m", "x", "S">(wt, xn, rm, ext, amount); }
|
||||
void STTR(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000000iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STTR(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"11111000000iiiiiiiii10nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void STTRB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000000iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STTRH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000000iiiiiiiii10nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STUR(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"10111000000iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STUR(XReg xt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"11111000000iiiiiiiii00nnnnnttttt", "t", "n", "i">(xt, xn, simm); }
|
||||
void STURB(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"00111000000iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STURH(WReg wt, XRegSp xn, SOffset<9, 0> simm = 0) { emit<"01111000000iiiiiiiii00nnnnnttttt", "t", "n", "i">(wt, xn, simm); }
|
||||
void STXP(WReg ws, WReg wt1, WReg wt2, XRegSp xn) { emit<"10001000001sssss0uuuuunnnnnttttt", "s", "t", "u", "n">(ws, wt1, wt2, xn); }
|
||||
void STXP(WReg ws, XReg xt1, XReg xt2, XRegSp xn) { emit<"11001000001sssss0uuuuunnnnnttttt", "s", "t", "u", "n">(ws, xt1, xt2, xn); }
|
||||
void STXR(WReg ws, WReg wt, XRegSp xn) { emit<"10001000000sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void STXR(WReg ws, XReg xt, XRegSp xn) { emit<"11001000000sssss011111nnnnnttttt", "s", "t", "n">(ws, xt, xn); }
|
||||
void STXRB(WReg ws, WReg wt, XRegSp xn) { emit<"00001000000sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void STXRH(WReg ws, WReg wt, XRegSp xn) { emit<"01001000000sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); }
|
||||
void SUB(WRegWsp wd, WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wd); emit<"01001011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(wd, wn, wm, ext, shift_amount); }
|
||||
void SUB(XRegSp xd, XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xd); emit<"11001011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(xd, xn, rm, ext, shift_amount); }
|
||||
void SUB(WRegWsp wd, WRegWsp wn, AddSubImm imm) { emit<"010100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(wd, wn, imm); }
|
||||
void SUB(XRegSp xd, XRegSp xn, AddSubImm imm) { emit<"110100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(xd, xn, imm); }
|
||||
void SUB(WReg wd, WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"01001011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void SUB(XReg xd, XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"11001011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void SUBS(WReg wd, WRegWsp wn, WReg wm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_lsl_correction(ext, wd); emit<"01101011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(wd, wn, wm, ext, shift_amount); }
|
||||
void SUBS(XReg xd, XRegSp xn, RReg rm, AddSubExt ext = AddSubExt::LSL, Imm<3> shift_amount = 0) { addsubext_verify_reg_size(ext, rm); addsubext_lsl_correction(ext, xd); emit<"11101011001mmmmmxxxiiinnnnnddddd", "d", "n", "m", "x", "i">(xd, xn, rm, ext, shift_amount); }
|
||||
void SUBS(WReg wd, WRegWsp wn, AddSubImm imm) { emit<"011100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(wd, wn, imm); }
|
||||
void SUBS(XReg xd, XRegSp xn, AddSubImm imm) { emit<"111100010siiiiiiiiiiiinnnnnddddd", "d", "n", "si">(xd, xn, imm); }
|
||||
void SUBS(WReg wd, WReg wn, WReg wm, AddSubShift shift = AddSubShift::LSL, Imm<5> shift_amount = 0) { emit<"01101011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(wd, wn, wm, shift, shift_amount); }
|
||||
void SUBS(XReg xd, XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_amount = 0) { emit<"11101011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); }
|
||||
void SVC(Imm<16> imm) { emit<"11010100000iiiiiiiiiiiiiiii00001", "i">(imm); }
|
||||
void SXTB(WReg wd, WReg wn) { emit<"0001001100000000000111nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void SXTB(XReg xd, WReg wn) { emit<"1001001101000000000111nnnnnddddd", "d", "n">(xd, wn); }
|
||||
void SXTH(WReg wd, WReg wn) { emit<"0001001100000000001111nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void SXTH(XReg xd, WReg wn) { emit<"1001001101000000001111nnnnnddddd", "d", "n">(xd, wn); }
|
||||
void SXTW(XReg xd, WReg wn) { emit<"1001001101000000011111nnnnnddddd", "d", "n">(xd, wn); }
|
||||
void TBNZ(RReg rt, Imm<6> imm, AddrOffset<16, 2> label) { tbz_verify_reg_size(rt, imm); emit<"b0110111bbbbbiiiiiiiiiiiiiittttt", "t", "b", "i">(rt, imm, label); }
|
||||
void TBZ(RReg rt, Imm<6> imm, AddrOffset<16, 2> label) { tbz_verify_reg_size(rt, imm); emit<"b0110110bbbbbiiiiiiiiiiiiiittttt", "t", "b", "i">(rt, imm, label); }
|
||||
void TLBI(TlbiOp op, XReg xt) { emit<"1101010100001ooo1000MMMMooottttt", "oMo", "t">(op, xt); }
|
||||
void TST(WReg wn, BitImm32 imm) { emit<"0111001000rrrrrrssssssnnnnn11111", "n", "rs">(wn, imm); }
|
||||
void TST(XReg xn, BitImm64 imm) { emit<"111100100Nrrrrrrssssssnnnnn11111", "n", "Nrs">(xn, imm); }
|
||||
void TST(WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) { emit<"01101010ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(wn, wm, shift, shift_amount); }
|
||||
void TST(XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount = 0) { emit<"11101010ss0mmmmmiiiiiinnnnn11111", "n", "m", "s", "i">(xn, xm, shift, shift_amount); }
|
||||
void UBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void UBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void UBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) { emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, immr, imms); }
|
||||
void UBFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms) { emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, immr, imms); }
|
||||
void UBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) { if (width.value() == 0 || width.value() > (32 - lsb.value())) throw "invalid width"; emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); }
|
||||
void UBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) { if (width.value() == 0 || width.value() > (64 - lsb.value())) throw "invalid width"; emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); }
|
||||
void UDF(Imm<16> imm) { emit<"0000000000000000iiiiiiiiiiiiiiii", "i">(imm); }
|
||||
void UDIV(WReg wd, WReg wn, WReg wm) { emit<"00011010110mmmmm000010nnnnnddddd", "d", "n", "m">(wd, wn, wm); }
|
||||
void UDIV(XReg xd, XReg xn, XReg xm) { emit<"10011010110mmmmm000010nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void UMADDL(XReg xd, WReg wn, WReg wm, XReg xa) { emit<"10011011101mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(xd, wn, wm, xa); }
|
||||
void UMNEGL(XReg xd, WReg wn, WReg wm) { emit<"10011011101mmmmm111111nnnnnddddd", "d", "n", "m">(xd, wn, wm); }
|
||||
void UMSUBL(XReg xd, WReg wn, WReg wm, XReg xa) { emit<"10011011101mmmmm1aaaaannnnnddddd", "d", "n", "m", "a">(xd, wn, wm, xa); }
|
||||
void UMULH(XReg xd, XReg xn, XReg xm) { emit<"10011011110mmmmm011111nnnnnddddd", "d", "n", "m">(xd, xn, xm); }
|
||||
void UMULL(XReg xd, WReg wn, WReg wm) { emit<"10011011101mmmmm011111nnnnnddddd", "d", "n", "m">(xd, wn, wm); }
|
||||
void UXTB(WReg wd, WReg wn) { emit<"0101001100000000000111nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void UXTH(WReg wd, WReg wn) { emit<"0101001100000000001111nnnnnddddd", "d", "n">(wd, wn); }
|
||||
void WFE() { emit<"11010101000000110010000001011111">(); }
|
||||
void WFI() { emit<"11010101000000110010000001111111">(); }
|
||||
void YIELD() { emit<"11010101000000110010000000111111">(); }
|
||||
234
include/oaknut/impl/enum.hpp
Normal file
234
include/oaknut/impl/enum.hpp
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
struct PostIndexed {};
|
||||
|
||||
struct PreIndexed {};
|
||||
|
||||
enum class Cond {
|
||||
EQ,
|
||||
NE,
|
||||
CS,
|
||||
CC,
|
||||
MI,
|
||||
PL,
|
||||
VS,
|
||||
VC,
|
||||
HI,
|
||||
LS,
|
||||
GE,
|
||||
LT,
|
||||
GT,
|
||||
LE,
|
||||
AL,
|
||||
NV,
|
||||
HS = CS,
|
||||
LO = CC,
|
||||
};
|
||||
|
||||
Cond invert(Cond c)
|
||||
{
|
||||
return static_cast<Cond>(static_cast<unsigned>(c) ^ 1);
|
||||
}
|
||||
|
||||
enum class AddSubExt {
|
||||
UXTB,
|
||||
UXTH,
|
||||
UXTW,
|
||||
UXTX,
|
||||
SXTB,
|
||||
SXTH,
|
||||
SXTW,
|
||||
SXTX,
|
||||
LSL, // UXTW (32-bit) or UXTX (64-bit)
|
||||
};
|
||||
|
||||
enum class IndexExt {
|
||||
UXTW = 0b010,
|
||||
LSL = 0b011,
|
||||
SXTW = 0b110,
|
||||
SXTX = 0b111,
|
||||
};
|
||||
|
||||
enum class AddSubShift {
|
||||
LSL,
|
||||
LSR,
|
||||
ASR,
|
||||
};
|
||||
|
||||
enum class LogShift {
|
||||
LSL,
|
||||
LSR,
|
||||
ASR,
|
||||
ROR,
|
||||
};
|
||||
|
||||
enum class PstateField {
|
||||
UAO = 0b000'011, // ARMv8.2-UAO
|
||||
PAN = 0b000'100, // ARMv8.1-PAN
|
||||
SPSel = 0b000'101,
|
||||
DIT = 0b011'010, // ARMv8.4-DIT
|
||||
DAIFSet = 0b011'110,
|
||||
DAIFClr = 0b011'111,
|
||||
};
|
||||
|
||||
enum class SystemReg {
|
||||
};
|
||||
|
||||
enum class AtOp {
|
||||
S1E1R = 0b000'0'000,
|
||||
S1E1W = 0b000'0'001,
|
||||
S1E0R = 0b000'0'010,
|
||||
S1E0W = 0b000'0'011,
|
||||
S1E1RP = 0b000'1'000, // ARMv8.2-ATS1E1
|
||||
S1E1WP = 0b000'1'001, // ARMv8.2-ATS1E1
|
||||
S1E2R = 0b100'0'000,
|
||||
S1E2W = 0b100'0'001,
|
||||
S12E1R = 0b100'0'100,
|
||||
S12E1W = 0b100'0'101,
|
||||
S12E0R = 0b100'0'110,
|
||||
S12E0W = 0b100'0'111,
|
||||
S1E3R = 0b110'0'000,
|
||||
S1E3W = 0b110'0'001,
|
||||
};
|
||||
|
||||
enum class BarrierOp {
|
||||
SY = 0b1111,
|
||||
ST = 0b1110,
|
||||
LD = 0b1101,
|
||||
ISH = 0b1011,
|
||||
ISHST = 0b1010,
|
||||
ISHLD = 0b1001,
|
||||
NSH = 0b0111,
|
||||
NSHST = 0b0110,
|
||||
NSHLD = 0b0101,
|
||||
OSH = 0b0011,
|
||||
OSHST = 0b0010,
|
||||
OSHLD = 0b0001,
|
||||
};
|
||||
|
||||
enum class DcOp {
|
||||
IVAC = 0b000'0110'001,
|
||||
ISW = 0b000'0110'010,
|
||||
CSW = 0b000'1010'010,
|
||||
CISW = 0b000'1110'010,
|
||||
ZVA = 0b011'0100'001,
|
||||
CVAC = 0b011'1010'001,
|
||||
CVAU = 0b011'1011'001,
|
||||
CVAP = 0b011'1100'001, // ARMv8.2-DCPoP
|
||||
CIVAC = 0b011'1110'001,
|
||||
};
|
||||
|
||||
enum class IcOp {
|
||||
IALLUIS = 0b000'0001'000,
|
||||
IALLU = 0b000'0101'000,
|
||||
IVAU = 0b011'0101'001,
|
||||
};
|
||||
|
||||
enum class PrfOp {
|
||||
PLDL1KEEP = 0b00'00'0,
|
||||
PLDL1STRM = 0b00'00'1,
|
||||
PLDL2KEEP = 0b00'01'0,
|
||||
PLDL2STRM = 0b00'01'1,
|
||||
PLDL3KEEP = 0b00'10'0,
|
||||
PLDL3STRM = 0b00'10'1,
|
||||
PLIL1KEEP = 0b01'00'0,
|
||||
PLIL1STRM = 0b01'00'1,
|
||||
PLIL2KEEP = 0b01'01'0,
|
||||
PLIL2STRM = 0b01'01'1,
|
||||
PLIL3KEEP = 0b01'10'0,
|
||||
PLIL3STRM = 0b01'10'1,
|
||||
PSTL1KEEP = 0b10'00'0,
|
||||
PSTL1STRM = 0b10'00'1,
|
||||
PSTL2KEEP = 0b10'01'0,
|
||||
PSTL2STRM = 0b10'01'1,
|
||||
PSTL3KEEP = 0b10'10'0,
|
||||
PSTL3STRM = 0b10'10'1,
|
||||
};
|
||||
|
||||
enum class TlbiOp {
|
||||
VMALLE1OS = 0b000'0001'000, // ARMv8.4-TLBI
|
||||
VAE1OS = 0b000'0001'001, // ARMv8.4-TLBI
|
||||
ASIDE1OS = 0b000'0001'010, // ARMv8.4-TLBI
|
||||
VAAE1OS = 0b000'0001'011, // ARMv8.4-TLBI
|
||||
VALE1OS = 0b000'0001'101, // ARMv8.4-TLBI
|
||||
VAALE1OS = 0b000'0001'111, // ARMv8.4-TLBI
|
||||
RVAE1IS = 0b000'0010'001, // ARMv8.4-TLBI
|
||||
RVAAE1IS = 0b000'0010'011, // ARMv8.4-TLBI
|
||||
RVALE1IS = 0b000'0010'101, // ARMv8.4-TLBI
|
||||
RVAALE1IS = 0b000'0010'111, // ARMv8.4-TLBI
|
||||
VMALLE1IS = 0b000'0011'000,
|
||||
VAE1IS = 0b000'0011'001,
|
||||
ASIDE1IS = 0b000'0011'010,
|
||||
VAAE1IS = 0b000'0011'011,
|
||||
VALE1IS = 0b000'0011'101,
|
||||
VAALE1IS = 0b000'0011'111,
|
||||
RVAE1OS = 0b000'0101'001, // ARMv8.4-TLBI
|
||||
RVAAE1OS = 0b000'0101'011, // ARMv8.4-TLBI
|
||||
RVALE1OS = 0b000'0101'101, // ARMv8.4-TLBI
|
||||
RVAALE1OS = 0b000'0101'111, // ARMv8.4-TLBI
|
||||
RVAE1 = 0b000'0110'001, // ARMv8.4-TLBI
|
||||
RVAAE1 = 0b000'0110'011, // ARMv8.4-TLBI
|
||||
RVALE1 = 0b000'0110'101, // ARMv8.4-TLBI
|
||||
RVAALE1 = 0b000'0110'111, // ARMv8.4-TLBI
|
||||
VMALLE1 = 0b000'0111'000,
|
||||
VAE1 = 0b000'0111'001,
|
||||
ASIDE1 = 0b000'0111'010,
|
||||
VAAE1 = 0b000'0111'011,
|
||||
VALE1 = 0b000'0111'101,
|
||||
VAALE1 = 0b000'0111'111,
|
||||
IPAS2E1IS = 0b100'0000'001,
|
||||
RIPAS2E1IS = 0b100'0000'010, // ARMv8.4-TLBI
|
||||
IPAS2LE1IS = 0b100'0000'101,
|
||||
RIPAS2LE1IS = 0b100'0000'110, // ARMv8.4-TLBI
|
||||
ALLE2OS = 0b100'0001'000, // ARMv8.4-TLBI
|
||||
VAE2OS = 0b100'0001'001, // ARMv8.4-TLBI
|
||||
ALLE1OS = 0b100'0001'100, // ARMv8.4-TLBI
|
||||
VALE2OS = 0b100'0001'101, // ARMv8.4-TLBI
|
||||
VMALLS12E1OS = 0b100'0001'110, // ARMv8.4-TLBI
|
||||
RVAE2IS = 0b100'0010'001, // ARMv8.4-TLBI
|
||||
RVALE2IS = 0b100'0010'101, // ARMv8.4-TLBI
|
||||
ALLE2IS = 0b100'0011'000,
|
||||
VAE2IS = 0b100'0011'001,
|
||||
ALLE1IS = 0b100'0011'100,
|
||||
VALE2IS = 0b100'0011'101,
|
||||
VMALLS12E1IS = 0b100'0011'110,
|
||||
IPAS2E1OS = 0b100'0100'000, // ARMv8.4-TLBI
|
||||
IPAS2E1 = 0b100'0100'001,
|
||||
RIPAS2E1 = 0b100'0100'010, // ARMv8.4-TLBI
|
||||
RIPAS2E1OS = 0b100'0100'011, // ARMv8.4-TLBI
|
||||
IPAS2LE1OS = 0b100'0100'100, // ARMv8.4-TLBI
|
||||
IPAS2LE1 = 0b100'0100'101,
|
||||
RIPAS2LE1 = 0b100'0100'110, // ARMv8.4-TLBI
|
||||
RIPAS2LE1OS = 0b100'0100'111, // ARMv8.4-TLBI
|
||||
RVAE2OS = 0b100'0101'001, // ARMv8.4-TLBI
|
||||
RVALE2OS = 0b100'0101'101, // ARMv8.4-TLBI
|
||||
RVAE2 = 0b100'0110'001, // ARMv8.4-TLBI
|
||||
RVALE2 = 0b100'0110'101, // ARMv8.4-TLBI
|
||||
ALLE2 = 0b100'0111'000,
|
||||
VAE2 = 0b100'0111'001,
|
||||
ALLE1 = 0b100'0111'100,
|
||||
VALE2 = 0b100'0111'101,
|
||||
VMALLS12E1 = 0b100'0111'110,
|
||||
ALLE3OS = 0b110'0001'000, // ARMv8.4-TLBI
|
||||
VAE3OS = 0b110'0001'001, // ARMv8.4-TLBI
|
||||
VALE3OS = 0b110'0001'101, // ARMv8.4-TLBI
|
||||
RVAE3IS = 0b110'0010'001, // ARMv8.4-TLBI
|
||||
RVALE3IS = 0b110'0010'101, // ARMv8.4-TLBI
|
||||
ALLE3IS = 0b110'0011'000,
|
||||
VAE3IS = 0b110'0011'001,
|
||||
VALE3IS = 0b110'0011'101,
|
||||
RVAE3OS = 0b110'0101'001, // ARMv8.4-TLBI
|
||||
RVALE3OS = 0b110'0101'101, // ARMv8.4-TLBI
|
||||
RVAE3 = 0b110'0110'001, // ARMv8.4-TLBI
|
||||
RVALE3 = 0b110'0110'101, // ARMv8.4-TLBI
|
||||
ALLE3 = 0b110'0111'000,
|
||||
VAE3 = 0b110'0111'001,
|
||||
VALE3 = 0b110'0111'101,
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
245
include/oaknut/impl/imm.hpp
Normal file
245
include/oaknut/impl/imm.hpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <bit>
|
||||
#include <compare>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
template<std::size_t bit_size_>
|
||||
struct Imm {
|
||||
public:
|
||||
static_assert(bit_size_ != 0 && bit_size_ <= 32, "Invalid bit_size");
|
||||
static constexpr std::size_t bit_size = bit_size_;
|
||||
static constexpr std::uint32_t mask = (1 << bit_size) - 1;
|
||||
|
||||
constexpr /* implicit */ Imm(std::uint32_t value_)
|
||||
: m_value(value_)
|
||||
{
|
||||
if (!is_valid(value_))
|
||||
throw "outsized Imm value";
|
||||
}
|
||||
|
||||
constexpr auto operator<=>(const Imm& other) const { return m_value <=> other.m_value; }
|
||||
constexpr auto operator<=>(std::uint32_t other) const { return operator<=>(Imm{other}); }
|
||||
|
||||
constexpr std::uint32_t value() const { return m_value; }
|
||||
|
||||
static bool is_valid(std::uint32_t value_)
|
||||
{
|
||||
return ((value_ & mask) != value_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_value;
|
||||
};
|
||||
|
||||
enum class AddSubImmShift {
|
||||
SHL_0,
|
||||
SHL_12,
|
||||
};
|
||||
|
||||
struct AddSubImm {
|
||||
public:
|
||||
constexpr AddSubImm(std::uint16_t value_, AddSubImmShift shift_)
|
||||
: m_encoded(value_ | ((shift_ == AddSubImmShift::SHL_12) ? 1 << 12 : 0))
|
||||
{
|
||||
if ((value_ & 0xFFF) != value_)
|
||||
throw "invalid AddSubImm";
|
||||
}
|
||||
|
||||
constexpr /* implicit */ AddSubImm(std::uint64_t value_)
|
||||
{
|
||||
if ((value_ & 0xFFF) == value_) {
|
||||
m_encoded = value_;
|
||||
} else if ((value_ & 0xFFF000) == value_) {
|
||||
m_encoded = (value_ >> 12) | (1 << 12);
|
||||
} else {
|
||||
throw "invalid AddSubImm";
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool is_valid(std::uint64_t value_)
|
||||
{
|
||||
return ((value_ & 0xFFF) == value_) || ((value_ & 0xFFF000) == value_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
enum class MovImm16Shift {
|
||||
SHL_0,
|
||||
SHL_16,
|
||||
SHL_32,
|
||||
SHL_48,
|
||||
};
|
||||
|
||||
struct MovImm16 {
|
||||
public:
|
||||
MovImm16(std::uint16_t value_, MovImm16Shift shift_)
|
||||
: m_encoded(static_cast<std::uint32_t>(value_) | (static_cast<std::uint32_t>(shift_) << 16))
|
||||
{}
|
||||
|
||||
constexpr /* implict */ MovImm16(std::uint64_t value_)
|
||||
{
|
||||
std::uint32_t shift = 0;
|
||||
while (value_ != 0) {
|
||||
const std::uint32_t lsw = static_cast<std::uint16_t>(value_ & 0xFFFF);
|
||||
if (value_ == lsw) {
|
||||
m_encoded = lsw | (shift << 16);
|
||||
return;
|
||||
} else if (lsw != 0) {
|
||||
throw "invalid MovImm16";
|
||||
}
|
||||
value_ >>= 16;
|
||||
shift++;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool is_valid(std::uint64_t value_)
|
||||
{
|
||||
return ((value_ & 0xFFFF) == value_) || ((value_ & 0xFFFF0000) == value_) || ((value_ & 0xFFFF00000000) == value_) || ((value_ & 0xFFFF000000000000) == value_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr std::uint64_t mask_from_esize(std::size_t esize)
|
||||
{
|
||||
return (~std::uint64_t{0}) >> (64 - esize);
|
||||
}
|
||||
|
||||
constexpr std::optional<std::uint32_t> encode_bit_imm(std::uint32_t value)
|
||||
{
|
||||
const std::uint64_t value_u64 = (static_cast<std::uint64_t>(value) << 32) | static_cast<std::uint64_t>(value);
|
||||
const auto result = encode_bit_imm(value_u64);
|
||||
if (result && (*result & 0x3FF) != *result)
|
||||
return std::nullopt;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr std::uint64_t inverse_mask_from_trailing_ones(std::uint64_t value)
|
||||
{
|
||||
return ~value | (value + 1);
|
||||
}
|
||||
|
||||
constexpr std::uint64_t is_contiguous_mask_from_lsb(std::uint64_t value)
|
||||
{
|
||||
return value && ((value + 1) & value) == 0;
|
||||
}
|
||||
|
||||
constexpr std::optional<std::uint32_t> encode_bit_imm(std::uint64_t value)
|
||||
{
|
||||
if (value == 0 || (~value) == 0)
|
||||
return std::nullopt;
|
||||
|
||||
const std::size_t esize = [value] {
|
||||
for (std::size_t esize = 64; esize > 1; esize /= 2) {
|
||||
if (value != std::rotr(value, esize / 2)) {
|
||||
return esize;
|
||||
}
|
||||
}
|
||||
return std::size_t{0};
|
||||
}();
|
||||
|
||||
if (esize == 0)
|
||||
return std::nullopt;
|
||||
|
||||
const std::size_t rotation = std::countr_zero(value & inverse_mask_from_trailing_ones(value));
|
||||
const std::uint64_t emask = mask_from_esize(esize);
|
||||
const std::uint64_t rot_element = std::rotr(value, rotation) & emask;
|
||||
|
||||
if (!is_contiguous_mask_from_lsb(rot_element))
|
||||
return std::nullopt;
|
||||
|
||||
const std::uint32_t S = std::popcount(rot_element) - 1;
|
||||
const std::uint32_t R = rotation & (esize - 1);
|
||||
|
||||
return static_cast<std::uint32_t>(((((-esize) << 7) | (S << 6) | R) ^ 0x1000) & 0x1fff);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
struct BitImm32 {
|
||||
public:
|
||||
constexpr BitImm32(Imm<6> imms, Imm<6> immr)
|
||||
: m_encoded((imms.value() << 6) | immr.value())
|
||||
{}
|
||||
|
||||
constexpr /* implicit */ BitImm32(std::uint32_t value)
|
||||
{
|
||||
const auto encoded = detail::encode_bit_imm(value);
|
||||
if (!encoded || (*encoded & 0x1000) != 0)
|
||||
throw "invalid BitImm32";
|
||||
m_encoded = *encoded;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
struct BitImm64 {
|
||||
public:
|
||||
constexpr BitImm64(bool N, Imm<6> imms, Imm<6> immr)
|
||||
: m_encoded((N ? 1 << 12 : 0) | (imms.value() << 6) | immr.value())
|
||||
{}
|
||||
|
||||
constexpr /* implicit */ BitImm64(std::uint64_t value)
|
||||
{
|
||||
const auto encoded = detail::encode_bit_imm(value);
|
||||
if (!encoded)
|
||||
throw "invalid BitImm64";
|
||||
m_encoded = *encoded;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
template<int A, int B>
|
||||
struct ImmChoice {
|
||||
constexpr /* implicit */ ImmChoice(int value)
|
||||
{
|
||||
if (value == A) {
|
||||
m_encoded = 0;
|
||||
} else if (value == B) {
|
||||
m_encoded = 1;
|
||||
} else {
|
||||
throw "invalid ImmChoice";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
template<std::size_t max_value>
|
||||
struct LslShift {
|
||||
constexpr /* implicit */ LslShift(std::size_t amount)
|
||||
: m_amount(amount)
|
||||
{
|
||||
if (amount >= max_value)
|
||||
throw "LslShift out of range";
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::size_t m_amount;
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
19
include/oaknut/impl/multi_typed_name.hpp
Normal file
19
include/oaknut/impl/multi_typed_name.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
template<auto... Vs>
|
||||
struct MultiTypedName;
|
||||
|
||||
template<>
|
||||
struct MultiTypedName<> {};
|
||||
|
||||
template<auto V, auto... Vs>
|
||||
struct MultiTypedName<V, Vs...> : public MultiTypedName<Vs...> {
|
||||
constexpr operator decltype(V)() const { return V; }
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
98
include/oaknut/impl/offset.hpp
Normal file
98
include/oaknut/impl/offset.hpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr std::uint64_t inverse_mask_from_size(std::size_t size)
|
||||
{
|
||||
return (~std::uint64_t{0}) << size;
|
||||
}
|
||||
|
||||
constexpr std::uint64_t mask_from_size(std::size_t size)
|
||||
{
|
||||
return (~std::uint64_t{0}) >> (64 - size);
|
||||
}
|
||||
|
||||
template<std::size_t bit_count>
|
||||
constexpr std::uint64_t sign_extend(std::uint64_t value)
|
||||
{
|
||||
static_assert(bit_count != 0, "cannot sign-extend zero-sized value");
|
||||
constexpr size_t shift_amount = 64 - bit_count;
|
||||
return static_cast<std::uint64_t>(static_cast<std::int64_t>(value << shift_amount) >> shift_amount);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<std::size_t bitsize, std::size_t alignment>
|
||||
struct AddrOffset {
|
||||
AddrOffset(std::ptrdiff_t diff)
|
||||
{
|
||||
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(diff);
|
||||
if (detail::sign_extend<bitsize>(diff_u64) != diff_u64)
|
||||
throw "out of range";
|
||||
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
|
||||
throw "misalignment";
|
||||
|
||||
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
template<std::size_t bitsize>
|
||||
struct PageOffset {
|
||||
PageOffset(void* ptr)
|
||||
: m_ptr(ptr)
|
||||
{}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
void* m_ptr;
|
||||
};
|
||||
|
||||
template<std::size_t bitsize, std::size_t alignment>
|
||||
struct SOffset {
|
||||
SOffset(std::int64_t offset)
|
||||
{
|
||||
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset);
|
||||
if (detail::sign_extend<bitsize>(diff_u64) != diff_u64)
|
||||
throw "out of range";
|
||||
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
|
||||
throw "misalignment";
|
||||
|
||||
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
template<std::size_t bitsize, std::size_t alignment>
|
||||
struct POffset {
|
||||
POffset(std::int64_t offset)
|
||||
{
|
||||
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset);
|
||||
if (diff_u64 > detail::mask_from_size(bitsize))
|
||||
throw "out of range";
|
||||
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
|
||||
throw "misalignment";
|
||||
|
||||
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class CodeGenerator;
|
||||
std::uint32_t m_encoded;
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
138
include/oaknut/impl/reg.hpp
Normal file
138
include/oaknut/impl/reg.hpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
struct Reg;
|
||||
struct RReg;
|
||||
struct ZrReg;
|
||||
struct WzrReg;
|
||||
struct XReg;
|
||||
struct WReg;
|
||||
struct SpReg;
|
||||
struct WspReg;
|
||||
struct XRegSp;
|
||||
struct XRegWsp;
|
||||
|
||||
struct Reg {
|
||||
constexpr explicit Reg(bool is_vector_, unsigned bitsize_, int index_)
|
||||
: m_index(index_)
|
||||
, m_bitsize(bitsize_)
|
||||
, m_is_vector(is_vector_)
|
||||
{
|
||||
assert(index_ >= -1 && index_ <= 31);
|
||||
assert(bitsize_ != 0 && (bitsize_ & (bitsize_ - 1)) == 0 && "Bitsize must be a power of two");
|
||||
}
|
||||
|
||||
constexpr int index() const { return m_index; }
|
||||
constexpr unsigned bitsize() const { return m_bitsize; }
|
||||
constexpr bool is_vector() const { return m_is_vector; }
|
||||
|
||||
private:
|
||||
int m_index : 8;
|
||||
unsigned m_bitsize : 8;
|
||||
bool m_is_vector;
|
||||
};
|
||||
|
||||
struct RReg : public Reg {
|
||||
constexpr explicit RReg(unsigned bitsize_, int index_)
|
||||
: Reg(false, bitsize_, index_)
|
||||
{
|
||||
assert(bitsize_ == 32 || bitsize_ == 64);
|
||||
}
|
||||
|
||||
XReg toX() const;
|
||||
WReg toW() const;
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
struct ZrReg : public RReg {
|
||||
constexpr explicit ZrReg()
|
||||
: RReg(64, 31) {}
|
||||
};
|
||||
|
||||
struct WzrReg : public RReg {
|
||||
constexpr explicit WzrReg()
|
||||
: RReg(32, 31) {}
|
||||
};
|
||||
|
||||
struct XReg : public RReg {
|
||||
constexpr explicit XReg(int index_)
|
||||
: RReg(64, index_) {}
|
||||
|
||||
constexpr /* implicit */ XReg(ZrReg)
|
||||
: RReg(64, 31) {}
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
struct WReg : public RReg {
|
||||
constexpr explicit WReg(int index_)
|
||||
: RReg(32, index_) {}
|
||||
|
||||
constexpr /* implicit */ WReg(WzrReg)
|
||||
: RReg(32, 31) {}
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
XReg RReg::toX() const
|
||||
{
|
||||
if (index() == -1)
|
||||
throw "cannot convert SP/WSP to XReg";
|
||||
return XReg{index()};
|
||||
}
|
||||
|
||||
WReg RReg::toW() const
|
||||
{
|
||||
if (index() == -1)
|
||||
throw "cannot convert SP/WSP to WReg";
|
||||
return WReg{index()};
|
||||
}
|
||||
|
||||
struct SpReg : public RReg {
|
||||
constexpr explicit SpReg()
|
||||
: RReg(64, -1) {}
|
||||
};
|
||||
|
||||
struct WspReg : public RReg {
|
||||
constexpr explicit WspReg()
|
||||
: RReg(64, -1) {}
|
||||
};
|
||||
|
||||
struct XRegSp : public RReg {
|
||||
constexpr /* implict */ XRegSp(SpReg)
|
||||
: RReg(64, -1) {}
|
||||
|
||||
constexpr /* implict */ XRegSp(XReg xr)
|
||||
: RReg(64, xr.index())
|
||||
{
|
||||
if (xr.index() == 31)
|
||||
throw "unexpected ZR passed into an XRegSp";
|
||||
}
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
struct WRegWsp : public RReg {
|
||||
constexpr /* implict */ WRegWsp(WspReg)
|
||||
: RReg(32, -1) {}
|
||||
|
||||
constexpr /* implict */ WRegWsp(WReg wr)
|
||||
: RReg(32, wr.index())
|
||||
{
|
||||
if (wr.index() == 31)
|
||||
throw "unexpected WZR passed into an WRegWsp";
|
||||
}
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
24
include/oaknut/impl/string_literal.hpp
Normal file
24
include/oaknut/impl/string_literal.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
template<size_t N>
|
||||
struct StringLiteral {
|
||||
constexpr StringLiteral(const char (&str)[N])
|
||||
{
|
||||
std::copy_n(str, N, value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t strlen = N - 1;
|
||||
static constexpr std::size_t size = N;
|
||||
|
||||
char value[N];
|
||||
};
|
||||
|
||||
} // namespace oaknut
|
||||
248
include/oaknut/oaknut.hpp
Normal file
248
include/oaknut/oaknut.hpp
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
// SPDX-FileCopyrightText: 2022 merryhime
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "oaknut/impl/enum.hpp"
|
||||
#include "oaknut/impl/imm.hpp"
|
||||
#include "oaknut/impl/multi_typed_name.hpp"
|
||||
#include "oaknut/impl/offset.hpp"
|
||||
#include "oaknut/impl/reg.hpp"
|
||||
#include "oaknut/impl/string_literal.hpp"
|
||||
|
||||
namespace oaknut {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<StringLiteral bs, StringLiteral barg>
|
||||
constexpr std::uint32_t get_bits()
|
||||
{
|
||||
std::uint32_t result = 0;
|
||||
for (std::size_t i = 0; i < 32; i++) {
|
||||
for (std::size_t a = 0; a < barg.strlen; a++) {
|
||||
if (bs.value[i] == barg.value[a]) {
|
||||
result |= 1 << (31 - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr std::uint32_t pdep(std::uint32_t val, std::uint32_t mask)
|
||||
{
|
||||
std::uint32_t res = 0;
|
||||
for (std::uint32_t bb = 1; mask; bb += bb) {
|
||||
if (val & bb)
|
||||
res |= mask & -mask;
|
||||
mask &= mask - 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class CodeGenerator {
|
||||
public:
|
||||
explicit CodeGenerator(std::uint32_t* ptr)
|
||||
: m_ptr(ptr)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
T ptr()
|
||||
{
|
||||
static_assert(std::is_pointer_v<T>);
|
||||
return reinterpret_cast<T>(m_ptr);
|
||||
}
|
||||
|
||||
void set_ptr(std::uint32_t* ptr)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
}
|
||||
|
||||
#include "oaknut/impl/arm64_mnemonics.inc"
|
||||
|
||||
private:
|
||||
template<StringLiteral bs, StringLiteral... bargs, typename... Ts>
|
||||
void emit(Ts... args)
|
||||
{
|
||||
std::uint32_t encoding = detail::get_bits<bs, "1">();
|
||||
encoding |= (0 | ... | encode<detail::get_bits<bs, bargs>()>(std::forward<Ts>(args)));
|
||||
|
||||
*m_ptr = encoding;
|
||||
m_ptr++;
|
||||
}
|
||||
|
||||
#define OAKNUT_STD_ENCODE(TYPE, ACCESS, SIZE) \
|
||||
template<std::uint32_t splat> \
|
||||
std::uint32_t encode(TYPE v) \
|
||||
{ \
|
||||
static_assert(std::popcount(splat) == SIZE); \
|
||||
return detail::pdep(static_cast<std::uint32_t>(ACCESS), splat); \
|
||||
}
|
||||
|
||||
OAKNUT_STD_ENCODE(RReg, v.index() & 31, 5)
|
||||
OAKNUT_STD_ENCODE(XReg, v.index() & 31, 5)
|
||||
OAKNUT_STD_ENCODE(WReg, v.index() & 31, 5)
|
||||
OAKNUT_STD_ENCODE(XRegSp, v.index() & 31, 5)
|
||||
OAKNUT_STD_ENCODE(WRegWsp, v.index() & 31, 5)
|
||||
|
||||
OAKNUT_STD_ENCODE(AddSubImm, v.m_encoded, 13)
|
||||
OAKNUT_STD_ENCODE(BitImm32, v.m_encoded, 12)
|
||||
OAKNUT_STD_ENCODE(BitImm64, v.m_encoded, 13)
|
||||
OAKNUT_STD_ENCODE(LslShift<32>, v.m_amount, 12)
|
||||
OAKNUT_STD_ENCODE(LslShift<64>, v.m_amount, 12)
|
||||
|
||||
OAKNUT_STD_ENCODE(Cond, v, 4)
|
||||
OAKNUT_STD_ENCODE(AddSubExt, v, 3)
|
||||
OAKNUT_STD_ENCODE(IndexExt, v, 3)
|
||||
OAKNUT_STD_ENCODE(AddSubShift, v, 2)
|
||||
OAKNUT_STD_ENCODE(LogShift, v, 2)
|
||||
OAKNUT_STD_ENCODE(PstateField, v, 6)
|
||||
OAKNUT_STD_ENCODE(SystemReg, v, 15)
|
||||
OAKNUT_STD_ENCODE(AtOp, v, 7)
|
||||
OAKNUT_STD_ENCODE(BarrierOp, v, 4)
|
||||
OAKNUT_STD_ENCODE(DcOp, v, 10)
|
||||
OAKNUT_STD_ENCODE(IcOp, v, 10)
|
||||
OAKNUT_STD_ENCODE(PrfOp, v, 5)
|
||||
OAKNUT_STD_ENCODE(TlbiOp, v, 10)
|
||||
|
||||
template<std::uint32_t splat>
|
||||
std::uint32_t encode(MovImm16 v)
|
||||
{
|
||||
static_assert(std::popcount(splat) == 17 || std::popcount(splat) == 18);
|
||||
constexpr std::uint32_t mask = (1 << std::popcount(splat)) - 1;
|
||||
if ((v.m_encoded & mask) != v.m_encoded)
|
||||
throw "invalid MovImm16";
|
||||
return detail::pdep(v.m_encoded, splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, std::size_t imm_size>
|
||||
std::uint32_t encode(Imm<imm_size> v)
|
||||
{
|
||||
static_assert(std::popcount(splat) >= imm_size);
|
||||
return detail::pdep(v.value(), splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, int A, int B>
|
||||
std::uint32_t encode(ImmChoice<A, B> v)
|
||||
{
|
||||
static_assert(std::popcount(splat) == 1);
|
||||
return detail::pdep(v.m_encoded, splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, std::size_t size, std::size_t align>
|
||||
std::uint32_t encode(AddrOffset<size, align> v)
|
||||
{
|
||||
static_assert(std::popcount(splat) == size - align);
|
||||
return detail::pdep(v.m_encoded, splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, std::size_t size>
|
||||
std::uint32_t encode(PageOffset<size> v)
|
||||
{
|
||||
throw "to be implemented";
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, std::size_t size, std::size_t align>
|
||||
std::uint32_t encode(SOffset<size, align> v)
|
||||
{
|
||||
static_assert(std::popcount(splat) == size - align);
|
||||
return detail::pdep(v.m_encoded, splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat, std::size_t size, std::size_t align>
|
||||
std::uint32_t encode(POffset<size, align> v)
|
||||
{
|
||||
static_assert(std::popcount(splat) == size - align);
|
||||
return detail::pdep(v.m_encoded, splat);
|
||||
}
|
||||
|
||||
template<std::uint32_t splat>
|
||||
std::uint32_t encode(std::uint32_t v)
|
||||
{
|
||||
return detail::pdep(v, splat);
|
||||
}
|
||||
|
||||
#undef OAKNUT_STD_ENCODE
|
||||
|
||||
void addsubext_lsl_correction(AddSubExt& ext, XRegSp)
|
||||
{
|
||||
if (ext == AddSubExt::LSL)
|
||||
ext = AddSubExt::UXTX;
|
||||
}
|
||||
void addsubext_lsl_correction(AddSubExt& ext, WRegWsp)
|
||||
{
|
||||
if (ext == AddSubExt::LSL)
|
||||
ext = AddSubExt::UXTW;
|
||||
}
|
||||
void addsubext_lsl_correction(AddSubExt& ext, XReg)
|
||||
{
|
||||
if (ext == AddSubExt::LSL)
|
||||
ext = AddSubExt::UXTX;
|
||||
}
|
||||
void addsubext_lsl_correction(AddSubExt& ext, WReg)
|
||||
{
|
||||
if (ext == AddSubExt::LSL)
|
||||
ext = AddSubExt::UXTW;
|
||||
}
|
||||
|
||||
void addsubext_verify_reg_size(AddSubExt ext, RReg rm)
|
||||
{
|
||||
if (rm.bitsize() == 32 && (static_cast<int>(ext) & 0b011) != 0b011)
|
||||
return;
|
||||
if (rm.bitsize() == 64 && (static_cast<int>(ext) & 0b011) == 0b011)
|
||||
return;
|
||||
throw "invalid AddSubExt choice for rm size";
|
||||
}
|
||||
|
||||
void indexext_verify_reg_size(IndexExt ext, RReg rm)
|
||||
{
|
||||
if (rm.bitsize() == 32 && (static_cast<int>(ext) & 1) == 0)
|
||||
return;
|
||||
if (rm.bitsize() == 64 && (static_cast<int>(ext) & 1) == 1)
|
||||
return;
|
||||
throw "invalid IndexExt choice for rm size";
|
||||
}
|
||||
|
||||
void tbz_verify_reg_size(RReg rt, Imm<6> imm)
|
||||
{
|
||||
if (rt.bitsize() == 32 && imm.value() >= 32)
|
||||
throw "invalid imm choice for rt size";
|
||||
}
|
||||
|
||||
std::uint32_t* m_ptr;
|
||||
};
|
||||
|
||||
namespace util {
|
||||
|
||||
inline constexpr WReg W0{0}, W1{1}, W2{2}, W3{3}, W4{4}, W5{5}, W6{6}, W7{7}, W8{8}, W9{9}, W10{10}, W11{11}, W12{12}, W13{13}, W14{14}, W15{15}, W16{16}, W17{17}, W18{18}, W19{19}, W20{20}, W21{21}, W22{22}, W23{23}, W24{24}, W25{25}, W26{26}, W27{27}, W28{28}, W29{29}, W30{30};
|
||||
inline constexpr XReg X0{0}, X1{1}, X2{2}, X3{3}, X4{4}, X5{5}, X6{6}, X7{7}, X8{8}, X9{9}, X10{10}, X11{11}, X12{12}, X13{13}, X14{14}, X15{15}, X16{16}, X17{17}, X18{18}, X19{19}, X20{20}, X21{21}, X22{22}, X23{23}, X24{24}, X25{25}, X26{26}, X27{27}, X28{28}, X29{29}, X30{30};
|
||||
inline constexpr ZrReg ZR{};
|
||||
inline constexpr WzrReg WZR{};
|
||||
inline constexpr SpReg SP{};
|
||||
inline constexpr WspReg WSP{};
|
||||
|
||||
inline constexpr Cond EQ{Cond::EQ}, NE{Cond::NE}, CS{Cond::CS}, CC{Cond::CC}, MI{Cond::MI}, PL{Cond::PL}, VS{Cond::VS}, VC{Cond::VC}, HI{Cond::HI}, LS{Cond::LS}, GE{Cond::GE}, LT{Cond::LT}, GT{Cond::GT}, LE{Cond::LE}, AL{Cond::AL}, NV{Cond::NV}, HS{Cond::HS}, LO{Cond::LO};
|
||||
|
||||
inline constexpr auto UXTB{MultiTypedName<AddSubExt::UXTB>{}};
|
||||
inline constexpr auto UXTH{MultiTypedName<AddSubExt::UXTH>{}};
|
||||
inline constexpr auto UXTW{MultiTypedName<AddSubExt::UXTW, IndexExt::UXTW>{}};
|
||||
inline constexpr auto UXTX{MultiTypedName<AddSubExt::UXTX>{}};
|
||||
inline constexpr auto SXTB{MultiTypedName<AddSubExt::SXTB>{}};
|
||||
inline constexpr auto SXTH{MultiTypedName<AddSubExt::SXTH>{}};
|
||||
inline constexpr auto SXTW{MultiTypedName<AddSubExt::SXTW, IndexExt::SXTW>{}};
|
||||
inline constexpr auto SXTX{MultiTypedName<AddSubExt::SXTX, IndexExt::SXTX>{}};
|
||||
inline constexpr auto LSL{MultiTypedName<AddSubExt::LSL, IndexExt::LSL, AddSubShift::LSL, LogShift::LSL>{}};
|
||||
inline constexpr auto LSR{MultiTypedName<AddSubShift::LSR, LogShift::LSR>{}};
|
||||
inline constexpr auto ASR{MultiTypedName<AddSubShift::ASR, LogShift::ASR>{}};
|
||||
inline constexpr auto ROR{MultiTypedName<LogShift::ROR>{}};
|
||||
|
||||
inline constexpr PostIndexed POST_INDEXED{};
|
||||
inline constexpr PreIndexed PRE_INDEXED{};
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace oaknut
|
||||
33
test.cpp
Normal file
33
test.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "oaknut/oaknut.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
const size_t page_size = getpagesize();
|
||||
std::printf("page size: %zu\n", page_size);
|
||||
|
||||
std::uint32_t* mem = (std::uint32_t*)mmap(nullptr, page_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_JIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
|
||||
pthread_jit_write_protect_np(false);
|
||||
|
||||
using namespace oaknut;
|
||||
using namespace oaknut::util;
|
||||
|
||||
CodeGenerator code{mem};
|
||||
code.MOVZ(W0, 42);
|
||||
code.RET(X30);
|
||||
|
||||
pthread_jit_write_protect_np(true);
|
||||
sys_icache_invalidate(mem, page_size);
|
||||
|
||||
std::printf("%i\n", ((int (*)())mem)());
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue