delocate: support Aarch64
Add Aarch64 support to delocate. Since it's a modern ISA, it's actually
not too bad once I understood the behaviour of the assembler.
Change-Id: I105fede43b5196b7ff7bdbf1ee71c6cfa2fc1aab
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44848
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/util/fipstools/delocate/delocate.go b/util/fipstools/delocate/delocate.go
index 95e0be5..dc34c68 100644
--- a/util/fipstools/delocate/delocate.go
+++ b/util/fipstools/delocate/delocate.go
@@ -157,6 +157,8 @@
statement, err = d.processIntelInstruction(statement, node.up)
case ppc64le:
statement, err = d.processPPCInstruction(statement, node.up)
+ case aarch64:
+ statement, err = d.processAarch64Instruction(statement, node.up)
default:
panic("unknown processor")
}
@@ -348,6 +350,276 @@
return argNodes
}
+// Aarch64 support
+
+// gotHelperName returns the name of a synthesised function that returns an
+// address from the GOT.
+func gotHelperName(symbol string) string {
+ return ".Lboringssl_loadgot_" + symbol
+}
+
+// loadAarch64Address emits instructions to put the address of |symbol|
+// (optionally adjusted by |offsetStr|) into |targetReg|.
+func (d *delocation) loadAarch64Address(statement *node32, targetReg string, symbol string, offsetStr string) (*node32, error) {
+ // There are two paths here: either the symbol is known to be local in which
+ // case adr is used to get the address (within 1MiB), or a GOT reference is
+ // really needed in which case the code needs to jump to a helper function.
+ //
+ // A helper function is needed because using code appears to be the only way
+ // to load a GOT value. On other platforms we have ".quad foo@GOT" outside of
+ // the module, but on Aarch64 that results in a "COPY" relocation and linker
+ // comments suggest it's a weird hack. So, for each GOT symbol needed, we emit
+ // a function outside of the module that returns the address from the GOT in
+ // x0.
+
+ d.writeCommentedNode(statement)
+
+ _, isKnown := d.symbols[symbol]
+ isLocal := strings.HasPrefix(symbol, ".L")
+ if isKnown || isLocal || isSynthesized(symbol) {
+ if isLocal {
+ symbol = d.mapLocalSymbol(symbol)
+ } else if isKnown {
+ symbol = localTargetName(symbol)
+ }
+
+ d.output.WriteString("\tadr " + targetReg + ", " + symbol + offsetStr + "\n")
+
+ return statement, nil
+ }
+
+ if len(offsetStr) != 0 {
+ panic("non-zero offset for helper-based reference")
+ }
+
+ var helperFunc string
+ if symbol == "OPENSSL_armcap_P" {
+ helperFunc = ".LOPENSSL_armcap_P_addr"
+ } else {
+ // GOT helpers also dereference the GOT entry, thus the subsequent ldr
+ // instruction, which would normally do the dereferencing, needs to be
+ // dropped. GOT helpers have to include the dereference because the
+ // assembler doesn't support ":got_lo12:foo" offsets except in an ldr
+ // instruction.
+ d.gotExternalsNeeded[symbol] = struct{}{}
+ helperFunc = gotHelperName(symbol)
+ }
+
+ // Clear the red-zone. I can't find a definitive answer about whether Linux
+ // Aarch64 includes a red-zone, but Microsoft has a 16-byte one and Apple a
+ // 128-byte one. Thus conservatively clear a 128-byte red-zone.
+ d.output.WriteString("\tsub sp, sp, 128\n")
+
+ // Save x0 (which will be stomped by the return value) and the link register
+ // to the stack. Then save the program counter into the link register and
+ // jump to the helper function.
+ d.output.WriteString("\tstp x0, lr, [sp, #-16]!\n")
+ d.output.WriteString("\tbl " + helperFunc + "\n")
+
+ if targetReg == "x0" {
+ // If the target happens to be x0 then restore the link register from the
+ // stack and send the saved value of x0 to the zero register.
+ d.output.WriteString("\tldp xzr, lr, [sp], #16\n")
+ } else {
+ // Otherwise move the result into place and restore registers.
+ d.output.WriteString("\tmov " + targetReg + ", x0\n")
+ d.output.WriteString("\tldp x0, lr, [sp], #16\n")
+ }
+
+ // Revert the red-zone adjustment.
+ d.output.WriteString("\tadd sp, sp, 128\n")
+
+ return statement, nil
+}
+
+func (d *delocation) processAarch64Instruction(statement, instruction *node32) (*node32, error) {
+ assertNodeType(instruction, ruleInstructionName)
+ instructionName := d.contents(instruction)
+
+ argNodes := instructionArgs(instruction.next)
+
+ switch instructionName {
+ case "cset", "csel", "csetm", "cneg", "csinv", "cinc", "csinc", "csneg":
+ // These functions are special because they take a condition-code name as
+ // an argument and that looks like a symbol reference.
+ d.writeNode(statement)
+ return statement, nil
+
+ case "mrs":
+ // Functions that take special register names also look like a symbol
+ // reference to the parser.
+ d.writeNode(statement)
+ return statement, nil
+
+ case "adrp":
+ // adrp always generates a relocation, even when the target symbol is in the
+ // same segment, because the page-offset of the code isn't known until link
+ // time. Thus adrp instructions are turned into either adr instructions
+ // (limiting the module to 1MiB offsets) or calls to helper functions, both of
+ // which load the full address. Later instructions, which add the low 12 bits
+ // of offset, are tweaked to remove the offset since it's already included.
+ // Loads of GOT symbols are slightly more complex because it's not possible to
+ // avoid dereferencing a GOT entry with Clang's assembler. Thus the later ldr
+ // instruction, which would normally do the dereferencing, is dropped
+ // completely. (Or turned into a mov if it targets a different register.)
+ assertNodeType(argNodes[0], ruleRegisterOrConstant)
+ targetReg := d.contents(argNodes[0])
+ if !strings.HasPrefix(targetReg, "x") {
+ panic("adrp targetting register " + targetReg + ", which has the wrong size")
+ }
+
+ var symbol, offset string
+ switch argNodes[1].pegRule {
+ case ruleGOTSymbolOffset:
+ symbol = d.contents(argNodes[1].up)
+ case ruleMemoryRef:
+ assertNodeType(argNodes[1].up, ruleSymbolRef)
+ node, empty := d.gatherOffsets(argNodes[1].up.up, "")
+ if len(empty) != 0 {
+ panic("prefix offsets found for adrp")
+ }
+ symbol = d.contents(node)
+ _, offset = d.gatherOffsets(node.next, "")
+ default:
+ panic("Unhandled adrp argument type " + rul3s[argNodes[1].pegRule])
+ }
+
+ return d.loadAarch64Address(statement, targetReg, symbol, offset)
+ }
+
+ var args []string
+ changed := false
+
+ for _, arg := range argNodes {
+ fullArg := arg
+
+ switch arg.pegRule {
+ case ruleRegisterOrConstant, ruleLocalLabelRef, ruleARMConstantTweak:
+ args = append(args, d.contents(fullArg))
+
+ case ruleGOTSymbolOffset:
+ // These should only be arguments to adrp and thus unreachable.
+ panic("unreachable")
+
+ case ruleMemoryRef:
+ ref := arg.up
+
+ switch ref.pegRule {
+ case ruleSymbolRef:
+ // This is a branch. Either the target needs to be written to a local
+ // version of the symbol to ensure that no relocations are emitted, or
+ // it needs to jump to a redirector function.
+ symbol, _, _, didChange, symbolIsLocal, _ := d.parseMemRef(arg.up)
+ changed = didChange
+
+ if _, knownSymbol := d.symbols[symbol]; knownSymbol {
+ symbol = localTargetName(symbol)
+ changed = true
+ } else if !symbolIsLocal && !isSynthesized(symbol) {
+ redirector := redirectorName(symbol)
+ d.redirectors[symbol] = redirector
+ symbol = redirector
+ changed = true
+ }
+
+ args = append(args, symbol)
+
+ case ruleARMBaseIndexScale:
+ parts := ref.up
+ assertNodeType(parts, ruleARMRegister)
+ baseAddrReg := d.contents(parts)
+ parts = skipWS(parts.next)
+
+ // Only two forms need special handling. First there's memory references
+ // like "[x*, :got_lo12:foo]". The base register here will have been the
+ // target of an adrp instruction to load the page address, but the adrp
+ // will have turned into loading the full address *and dereferencing it*,
+ // above. Thus this instruction needs to be dropped otherwise we'll be
+ // dereferencing twice.
+ //
+ // Second there are forms like "[x*, :lo12:foo]" where the code has used
+ // adrp to load the page address into x*. That adrp will have been turned
+ // into loading the full address so just the offset needs to be dropped.
+
+ if parts != nil {
+ if parts.pegRule == ruleARMGOTLow12 {
+ if instructionName != "ldr" {
+ panic("Symbol reference outside of ldr instruction")
+ }
+
+ if skipWS(parts.next) != nil || parts.up.next != nil {
+ panic("can't handle tweak or post-increment with symbol references")
+ }
+
+ // The GOT helper already dereferenced the entry so, at most, just a mov
+ // is needed to put things in the right register.
+ d.writeCommentedNode(statement)
+ if baseAddrReg != args[0] {
+ d.output.WriteString("\tmov " + args[0] + ", " + baseAddrReg + "\n")
+ }
+ return statement, nil
+ } else if parts.pegRule == ruleLow12BitsSymbolRef {
+ if instructionName != "ldr" {
+ panic("Symbol reference outside of ldr instruction")
+ }
+
+ if skipWS(parts.next) != nil || parts.up.next != nil {
+ panic("can't handle tweak or post-increment with symbol references")
+ }
+
+ // Suppress the offset; adrp loaded the full address.
+ args = append(args, "["+baseAddrReg+"]")
+ changed = true
+ continue
+ }
+ }
+
+ args = append(args, d.contents(fullArg))
+
+ case ruleLow12BitsSymbolRef:
+ // These are the second instruction in a pair:
+ // adrp x0, symbol // Load the page address into x0
+ // add x1, x0, :lo12:symbol // Adds the page offset.
+ //
+ // The adrp instruction will have been turned into a sequence that loads
+ // the full address, above, thus the offset is turned into zero. If that
+ // results in the instruction being a nop, then it is deleted.
+ if instructionName != "add" {
+ panic(fmt.Sprintf("unsure how to handle %q instruction using lo12", instructionName))
+ }
+
+ if !strings.HasPrefix(args[0], "x") || !strings.HasPrefix(args[1], "x") {
+ panic("address arithmetic with incorrectly sized register")
+ }
+
+ if args[0] == args[1] {
+ d.writeCommentedNode(statement)
+ return statement, nil
+ }
+
+ args = append(args, "#0")
+ changed = true
+
+ default:
+ panic(fmt.Sprintf("unhandled MemoryRef type %s", rul3s[ref.pegRule]))
+ }
+
+ default:
+ panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule]))
+ }
+ }
+
+ if changed {
+ d.writeCommentedNode(statement)
+ replacement := "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n"
+ d.output.WriteString(replacement)
+ } else {
+ d.writeNode(statement)
+ }
+
+ return statement, nil
+}
+
/* ppc64le
[PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st,
@@ -1347,6 +1619,17 @@
return lastStatement, nil
}
+func writeAarch64Function(w stringWriter, funcName string, writeContents func(stringWriter)) {
+ w.WriteString(".p2align 2\n")
+ w.WriteString(".hidden " + funcName + "\n")
+ w.WriteString(".type " + funcName + ", @function\n")
+ w.WriteString(funcName + ":\n")
+ w.WriteString(".cfi_startproc\n")
+ writeContents(w)
+ w.WriteString(".cfi_endproc\n")
+ w.WriteString(".size " + funcName + ", .-" + funcName + "\n")
+}
+
func transform(w stringWriter, inputs []inputFile) error {
// symbols contains all defined symbols.
symbols := make(map[string]struct{})
@@ -1481,7 +1764,8 @@
for _, name := range redirectorNames {
redirector := d.redirectors[name]
- if d.processor == ppc64le {
+ switch d.processor {
+ case ppc64le:
w.WriteString(".section \".toc\", \"aw\"\n")
w.WriteString(".Lredirector_toc_" + name + ":\n")
w.WriteString(".quad " + name + "\n")
@@ -1496,7 +1780,13 @@
w.WriteString("\tld 12, .Lredirector_toc_" + name + "@toc@l(12)\n")
w.WriteString("\tmtctr 12\n")
w.WriteString("\tbctr\n")
- } else {
+
+ case aarch64:
+ writeAarch64Function(w, redirector, func(w stringWriter) {
+ w.WriteString("\tb " + name + "\n")
+ })
+
+ case x86_64:
w.WriteString(".type " + redirector + ", @function\n")
w.WriteString(redirector + ":\n")
w.WriteString("\tjmp\t" + name + "\n")
@@ -1512,20 +1802,32 @@
// Emit BSS accessor functions. Each is a single LEA followed by RET.
for _, name := range accessorNames {
funcName := accessorName(name)
- w.WriteString(".type " + funcName + ", @function\n")
- w.WriteString(funcName + ":\n")
target := d.bssAccessorsNeeded[name]
- if d.processor == ppc64le {
+ switch d.processor {
+ case ppc64le:
+ w.WriteString(".type " + funcName + ", @function\n")
+ w.WriteString(funcName + ":\n")
w.WriteString("\taddis 3, 2, " + target + "@toc@ha\n")
w.WriteString("\taddi 3, 3, " + target + "@toc@l\n")
w.WriteString("\tblr\n")
- } else {
+
+ case x86_64:
+ w.WriteString(".type " + funcName + ", @function\n")
+ w.WriteString(funcName + ":\n")
w.WriteString("\tleaq\t" + target + "(%rip), %rax\n\tret\n")
+
+ case aarch64:
+ writeAarch64Function(w, funcName, func(w stringWriter) {
+ w.WriteString("\tadrp x0, " + target + "\n")
+ w.WriteString("\tadd x0, x0, :lo12:" + target + "\n")
+ w.WriteString("\tret\n")
+ })
}
}
- if d.processor == ppc64le {
+ switch d.processor {
+ case ppc64le:
loadTOCNames := sortedSet(d.tocLoaders)
for _, symbolAndOffset := range loadTOCNames {
parts := strings.SplitN(symbolAndOffset, "\x00", 2)
@@ -1544,7 +1846,24 @@
w.WriteString(".LBORINGSSL_external_toc:\n")
w.WriteString(".quad .TOC.-.LBORINGSSL_external_toc\n")
- } else {
+
+ case aarch64:
+ externalNames := sortedSet(d.gotExternalsNeeded)
+ for _, symbol := range externalNames {
+ writeAarch64Function(w, gotHelperName(symbol), func(w stringWriter) {
+ w.WriteString("\tadrp x0, :got:" + symbol + "\n")
+ w.WriteString("\tldr x0, [x0, :got_lo12:" + symbol + "]\n")
+ w.WriteString("\tret\n")
+ })
+ }
+
+ writeAarch64Function(w, ".LOPENSSL_armcap_P_addr", func(w stringWriter) {
+ w.WriteString("\tadrp x0, OPENSSL_armcap_P\n")
+ w.WriteString("\tadd x0, x0, :lo12:OPENSSL_armcap_P\n")
+ w.WriteString("\tret\n")
+ })
+
+ case x86_64:
externalNames := sortedSet(d.gotExternalsNeeded)
for _, name := range externalNames {
parts := strings.SplitN(name, "@", 2)
@@ -1819,6 +2138,8 @@
return x86_64
case "addis", "addi", "mflr":
return ppc64le
+ case "str", "bl", "ldr", "st1":
+ return aarch64
}
}
diff --git a/util/fipstools/delocate/delocate.peg b/util/fipstools/delocate/delocate.peg
index 4392949..991cd01 100644
--- a/util/fipstools/delocate/delocate.peg
+++ b/util/fipstools/delocate/delocate.peg
@@ -89,9 +89,8 @@
BaseIndexScale)
SymbolRef <- (Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?
Low12BitsSymbolRef <- ":lo12:" (LocalSymbol / SymbolName) Offset?
-ARMBaseIndexScale <- '[' ARMRegister (',' WS? (('#' Offset ('*' [0-9]+)? ) / ARMGOTLow12 / ARMCapReference / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?
+ARMBaseIndexScale <- '[' ARMRegister (',' WS? (('#' Offset ('*' [0-9]+)? ) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?
ARMGOTLow12 <- ":got_lo12:" SymbolName
-ARMCapReference <- ":lo12:OPENSSL_armcap_P"
ARMPostincrement <- '!'
BaseIndexScale <- '(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)? )? ')'
Operator <- [+\-]
diff --git a/util/fipstools/delocate/delocate.peg.go b/util/fipstools/delocate/delocate.peg.go
index 85858e5..6e21346 100644
--- a/util/fipstools/delocate/delocate.peg.go
+++ b/util/fipstools/delocate/delocate.peg.go
@@ -59,7 +59,6 @@
ruleLow12BitsSymbolRef
ruleARMBaseIndexScale
ruleARMGOTLow12
- ruleARMCapReference
ruleARMPostincrement
ruleBaseIndexScale
ruleOperator
@@ -115,7 +114,6 @@
"Low12BitsSymbolRef",
"ARMBaseIndexScale",
"ARMGOTLow12",
- "ARMCapReference",
"ARMPostincrement",
"BaseIndexScale",
"Operator",
@@ -236,7 +234,7 @@
type Asm struct {
Buffer string
buffer []rune
- rules [53]func() bool
+ rules [52]func() bool
parse func(rule ...int) error
reset func()
Pretty bool
@@ -5404,7 +5402,7 @@
position, tokenIndex = position681, tokenIndex681
return false
},
- /* 43 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset ('*' [0-9]+)?) / ARMGOTLow12 / ARMCapReference / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */
+ /* 43 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset ('*' [0-9]+)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */
func() bool {
position691, tokenIndex691 := position, tokenIndex
{
@@ -5476,47 +5474,41 @@
goto l697
l703:
position, tokenIndex = position697, tokenIndex697
- if !_rules[ruleARMCapReference]() {
+ if !_rules[ruleLow12BitsSymbolRef]() {
goto l704
}
goto l697
l704:
position, tokenIndex = position697, tokenIndex697
- if !_rules[ruleLow12BitsSymbolRef]() {
- goto l705
- }
- goto l697
- l705:
- position, tokenIndex = position697, tokenIndex697
if !_rules[ruleARMRegister]() {
goto l693
}
}
l697:
{
- position706, tokenIndex706 := position, tokenIndex
+ position705, tokenIndex705 := position, tokenIndex
if buffer[position] != rune(',') {
- goto l706
+ goto l705
}
position++
{
- position708, tokenIndex708 := position, tokenIndex
+ position707, tokenIndex707 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l708
+ goto l707
}
- goto l709
- l708:
- position, tokenIndex = position708, tokenIndex708
+ goto l708
+ l707:
+ position, tokenIndex = position707, tokenIndex707
}
- l709:
+ l708:
if !_rules[ruleARMConstantTweak]() {
- goto l706
+ goto l705
}
- goto l707
- l706:
- position, tokenIndex = position706, tokenIndex706
+ goto l706
+ l705:
+ position, tokenIndex = position705, tokenIndex705
}
- l707:
+ l706:
goto l694
l693:
position, tokenIndex = position693, tokenIndex693
@@ -5527,15 +5519,15 @@
}
position++
{
- position710, tokenIndex710 := position, tokenIndex
+ position709, tokenIndex709 := position, tokenIndex
if !_rules[ruleARMPostincrement]() {
- goto l710
+ goto l709
}
- goto l711
- l710:
- position, tokenIndex = position710, tokenIndex710
+ goto l710
+ l709:
+ position, tokenIndex = position709, tokenIndex709
}
- l711:
+ l710:
add(ruleARMBaseIndexScale, position692)
}
return true
@@ -5545,840 +5537,564 @@
},
/* 44 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */
func() bool {
- position712, tokenIndex712 := position, tokenIndex
+ position711, tokenIndex711 := position, tokenIndex
{
- position713 := position
+ position712 := position
if buffer[position] != rune(':') {
- goto l712
+ goto l711
}
position++
{
- position714, tokenIndex714 := position, tokenIndex
+ position713, tokenIndex713 := position, tokenIndex
if buffer[position] != rune('g') {
- goto l715
+ goto l714
}
position++
- goto l714
- l715:
- position, tokenIndex = position714, tokenIndex714
+ goto l713
+ l714:
+ position, tokenIndex = position713, tokenIndex713
if buffer[position] != rune('G') {
- goto l712
+ goto l711
}
position++
}
- l714:
+ l713:
{
- position716, tokenIndex716 := position, tokenIndex
+ position715, tokenIndex715 := position, tokenIndex
if buffer[position] != rune('o') {
- goto l717
+ goto l716
}
position++
- goto l716
- l717:
- position, tokenIndex = position716, tokenIndex716
+ goto l715
+ l716:
+ position, tokenIndex = position715, tokenIndex715
if buffer[position] != rune('O') {
- goto l712
+ goto l711
}
position++
}
- l716:
+ l715:
{
- position718, tokenIndex718 := position, tokenIndex
+ position717, tokenIndex717 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l719
+ goto l718
}
position++
- goto l718
- l719:
- position, tokenIndex = position718, tokenIndex718
+ goto l717
+ l718:
+ position, tokenIndex = position717, tokenIndex717
if buffer[position] != rune('T') {
- goto l712
+ goto l711
}
position++
}
- l718:
+ l717:
if buffer[position] != rune('_') {
- goto l712
+ goto l711
}
position++
{
- position720, tokenIndex720 := position, tokenIndex
+ position719, tokenIndex719 := position, tokenIndex
if buffer[position] != rune('l') {
- goto l721
+ goto l720
}
position++
- goto l720
- l721:
- position, tokenIndex = position720, tokenIndex720
+ goto l719
+ l720:
+ position, tokenIndex = position719, tokenIndex719
if buffer[position] != rune('L') {
- goto l712
+ goto l711
}
position++
}
- l720:
+ l719:
{
- position722, tokenIndex722 := position, tokenIndex
+ position721, tokenIndex721 := position, tokenIndex
if buffer[position] != rune('o') {
- goto l723
+ goto l722
}
position++
- goto l722
- l723:
- position, tokenIndex = position722, tokenIndex722
+ goto l721
+ l722:
+ position, tokenIndex = position721, tokenIndex721
if buffer[position] != rune('O') {
- goto l712
+ goto l711
}
position++
}
- l722:
+ l721:
if buffer[position] != rune('1') {
- goto l712
+ goto l711
}
position++
if buffer[position] != rune('2') {
- goto l712
+ goto l711
}
position++
if buffer[position] != rune(':') {
- goto l712
+ goto l711
}
position++
if !_rules[ruleSymbolName]() {
- goto l712
+ goto l711
}
- add(ruleARMGOTLow12, position713)
+ add(ruleARMGOTLow12, position712)
}
return true
- l712:
- position, tokenIndex = position712, tokenIndex712
+ l711:
+ position, tokenIndex = position711, tokenIndex711
return false
},
- /* 45 ARMCapReference <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' ('o' / 'O') ('p' / 'P') ('e' / 'E') ('n' / 'N') ('s' / 'S') ('s' / 'S') ('l' / 'L') '_' ('a' / 'A') ('r' / 'R') ('m' / 'M') ('c' / 'C') ('a' / 'A') ('p' / 'P') '_' ('p' / 'P'))> */
+ /* 45 ARMPostincrement <- <'!'> */
func() bool {
- position724, tokenIndex724 := position, tokenIndex
+ position723, tokenIndex723 := position, tokenIndex
{
- position725 := position
- if buffer[position] != rune(':') {
- goto l724
+ position724 := position
+ if buffer[position] != rune('!') {
+ goto l723
+ }
+ position++
+ add(ruleARMPostincrement, position724)
+ }
+ return true
+ l723:
+ position, tokenIndex = position723, tokenIndex723
+ return false
+ },
+ /* 46 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */
+ func() bool {
+ position725, tokenIndex725 := position, tokenIndex
+ {
+ position726 := position
+ if buffer[position] != rune('(') {
+ goto l725
}
position++
{
- position726, tokenIndex726 := position, tokenIndex
- if buffer[position] != rune('l') {
+ position727, tokenIndex727 := position, tokenIndex
+ if !_rules[ruleRegisterOrConstant]() {
goto l727
}
- position++
- goto l726
- l727:
- position, tokenIndex = position726, tokenIndex726
- if buffer[position] != rune('L') {
- goto l724
- }
- position++
- }
- l726:
- {
- position728, tokenIndex728 := position, tokenIndex
- if buffer[position] != rune('o') {
- goto l729
- }
- position++
goto l728
- l729:
- position, tokenIndex = position728, tokenIndex728
- if buffer[position] != rune('O') {
- goto l724
- }
- position++
+ l727:
+ position, tokenIndex = position727, tokenIndex727
}
l728:
- if buffer[position] != rune('1') {
- goto l724
- }
- position++
- if buffer[position] != rune('2') {
- goto l724
- }
- position++
- if buffer[position] != rune(':') {
- goto l724
- }
- position++
{
- position730, tokenIndex730 := position, tokenIndex
- if buffer[position] != rune('o') {
- goto l731
+ position729, tokenIndex729 := position, tokenIndex
+ if !_rules[ruleWS]() {
+ goto l729
}
- position++
goto l730
- l731:
- position, tokenIndex = position730, tokenIndex730
- if buffer[position] != rune('O') {
- goto l724
- }
- position++
+ l729:
+ position, tokenIndex = position729, tokenIndex729
}
l730:
{
- position732, tokenIndex732 := position, tokenIndex
- if buffer[position] != rune('p') {
- goto l733
+ position731, tokenIndex731 := position, tokenIndex
+ if buffer[position] != rune(',') {
+ goto l731
}
position++
+ {
+ position733, tokenIndex733 := position, tokenIndex
+ if !_rules[ruleWS]() {
+ goto l733
+ }
+ goto l734
+ l733:
+ position, tokenIndex = position733, tokenIndex733
+ }
+ l734:
+ if !_rules[ruleRegisterOrConstant]() {
+ goto l731
+ }
+ {
+ position735, tokenIndex735 := position, tokenIndex
+ if !_rules[ruleWS]() {
+ goto l735
+ }
+ goto l736
+ l735:
+ position, tokenIndex = position735, tokenIndex735
+ }
+ l736:
+ {
+ position737, tokenIndex737 := position, tokenIndex
+ if buffer[position] != rune(',') {
+ goto l737
+ }
+ position++
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l737
+ }
+ position++
+ l739:
+ {
+ position740, tokenIndex740 := position, tokenIndex
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l740
+ }
+ position++
+ goto l739
+ l740:
+ position, tokenIndex = position740, tokenIndex740
+ }
+ goto l738
+ l737:
+ position, tokenIndex = position737, tokenIndex737
+ }
+ l738:
goto l732
- l733:
- position, tokenIndex = position732, tokenIndex732
- if buffer[position] != rune('P') {
- goto l724
- }
- position++
+ l731:
+ position, tokenIndex = position731, tokenIndex731
}
l732:
- {
- position734, tokenIndex734 := position, tokenIndex
- if buffer[position] != rune('e') {
- goto l735
- }
- position++
- goto l734
- l735:
- position, tokenIndex = position734, tokenIndex734
- if buffer[position] != rune('E') {
- goto l724
- }
- position++
+ if buffer[position] != rune(')') {
+ goto l725
}
- l734:
+ position++
+ add(ruleBaseIndexScale, position726)
+ }
+ return true
+ l725:
+ position, tokenIndex = position725, tokenIndex725
+ return false
+ },
+ /* 47 Operator <- <('+' / '-')> */
+ func() bool {
+ position741, tokenIndex741 := position, tokenIndex
+ {
+ position742 := position
{
- position736, tokenIndex736 := position, tokenIndex
- if buffer[position] != rune('n') {
- goto l737
+ position743, tokenIndex743 := position, tokenIndex
+ if buffer[position] != rune('+') {
+ goto l744
}
position++
- goto l736
- l737:
- position, tokenIndex = position736, tokenIndex736
- if buffer[position] != rune('N') {
- goto l724
- }
- position++
- }
- l736:
- {
- position738, tokenIndex738 := position, tokenIndex
- if buffer[position] != rune('s') {
- goto l739
- }
- position++
- goto l738
- l739:
- position, tokenIndex = position738, tokenIndex738
- if buffer[position] != rune('S') {
- goto l724
- }
- position++
- }
- l738:
- {
- position740, tokenIndex740 := position, tokenIndex
- if buffer[position] != rune('s') {
+ goto l743
+ l744:
+ position, tokenIndex = position743, tokenIndex743
+ if buffer[position] != rune('-') {
goto l741
}
position++
- goto l740
- l741:
- position, tokenIndex = position740, tokenIndex740
- if buffer[position] != rune('S') {
- goto l724
- }
- position++
}
- l740:
+ l743:
+ add(ruleOperator, position742)
+ }
+ return true
+ l741:
+ position, tokenIndex = position741, tokenIndex741
+ return false
+ },
+ /* 48 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */
+ func() bool {
+ position745, tokenIndex745 := position, tokenIndex
+ {
+ position746 := position
{
- position742, tokenIndex742 := position, tokenIndex
- if buffer[position] != rune('l') {
- goto l743
- }
- position++
- goto l742
- l743:
- position, tokenIndex = position742, tokenIndex742
- if buffer[position] != rune('L') {
- goto l724
- }
- position++
- }
- l742:
- if buffer[position] != rune('_') {
- goto l724
- }
- position++
- {
- position744, tokenIndex744 := position, tokenIndex
- if buffer[position] != rune('a') {
- goto l745
- }
- position++
- goto l744
- l745:
- position, tokenIndex = position744, tokenIndex744
- if buffer[position] != rune('A') {
- goto l724
- }
- position++
- }
- l744:
- {
- position746, tokenIndex746 := position, tokenIndex
- if buffer[position] != rune('r') {
+ position747, tokenIndex747 := position, tokenIndex
+ if buffer[position] != rune('+') {
goto l747
}
position++
- goto l746
- l747:
- position, tokenIndex = position746, tokenIndex746
- if buffer[position] != rune('R') {
- goto l724
- }
- position++
- }
- l746:
- {
- position748, tokenIndex748 := position, tokenIndex
- if buffer[position] != rune('m') {
- goto l749
- }
- position++
goto l748
- l749:
- position, tokenIndex = position748, tokenIndex748
- if buffer[position] != rune('M') {
- goto l724
- }
- position++
+ l747:
+ position, tokenIndex = position747, tokenIndex747
}
l748:
{
- position750, tokenIndex750 := position, tokenIndex
- if buffer[position] != rune('c') {
- goto l751
+ position749, tokenIndex749 := position, tokenIndex
+ if buffer[position] != rune('-') {
+ goto l749
}
position++
goto l750
- l751:
- position, tokenIndex = position750, tokenIndex750
- if buffer[position] != rune('C') {
- goto l724
- }
- position++
+ l749:
+ position, tokenIndex = position749, tokenIndex749
}
l750:
{
- position752, tokenIndex752 := position, tokenIndex
- if buffer[position] != rune('a') {
+ position751, tokenIndex751 := position, tokenIndex
+ if buffer[position] != rune('0') {
+ goto l752
+ }
+ position++
+ {
+ position753, tokenIndex753 := position, tokenIndex
+ if buffer[position] != rune('b') {
+ goto l754
+ }
+ position++
goto l753
+ l754:
+ position, tokenIndex = position753, tokenIndex753
+ if buffer[position] != rune('B') {
+ goto l752
+ }
+ position++
}
- position++
- goto l752
l753:
- position, tokenIndex = position752, tokenIndex752
- if buffer[position] != rune('A') {
- goto l724
- }
- position++
- }
- l752:
- {
- position754, tokenIndex754 := position, tokenIndex
- if buffer[position] != rune('p') {
- goto l755
- }
- position++
- goto l754
- l755:
- position, tokenIndex = position754, tokenIndex754
- if buffer[position] != rune('P') {
- goto l724
- }
- position++
- }
- l754:
- if buffer[position] != rune('_') {
- goto l724
- }
- position++
- {
- position756, tokenIndex756 := position, tokenIndex
- if buffer[position] != rune('p') {
+ {
+ position757, tokenIndex757 := position, tokenIndex
+ if buffer[position] != rune('0') {
+ goto l758
+ }
+ position++
goto l757
+ l758:
+ position, tokenIndex = position757, tokenIndex757
+ if buffer[position] != rune('1') {
+ goto l752
+ }
+ position++
}
- position++
- goto l756
l757:
- position, tokenIndex = position756, tokenIndex756
- if buffer[position] != rune('P') {
- goto l724
- }
- position++
- }
- l756:
- add(ruleARMCapReference, position725)
- }
- return true
- l724:
- position, tokenIndex = position724, tokenIndex724
- return false
- },
- /* 46 ARMPostincrement <- <'!'> */
- func() bool {
- position758, tokenIndex758 := position, tokenIndex
- {
- position759 := position
- if buffer[position] != rune('!') {
- goto l758
- }
- position++
- add(ruleARMPostincrement, position759)
- }
- return true
- l758:
- position, tokenIndex = position758, tokenIndex758
- return false
- },
- /* 47 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */
- func() bool {
- position760, tokenIndex760 := position, tokenIndex
- {
- position761 := position
- if buffer[position] != rune('(') {
- goto l760
- }
- position++
- {
- position762, tokenIndex762 := position, tokenIndex
- if !_rules[ruleRegisterOrConstant]() {
- goto l762
- }
- goto l763
- l762:
- position, tokenIndex = position762, tokenIndex762
- }
- l763:
- {
- position764, tokenIndex764 := position, tokenIndex
- if !_rules[ruleWS]() {
- goto l764
- }
- goto l765
- l764:
- position, tokenIndex = position764, tokenIndex764
- }
- l765:
- {
- position766, tokenIndex766 := position, tokenIndex
- if buffer[position] != rune(',') {
- goto l766
- }
- position++
+ l755:
{
- position768, tokenIndex768 := position, tokenIndex
- if !_rules[ruleWS]() {
- goto l768
- }
- goto l769
- l768:
- position, tokenIndex = position768, tokenIndex768
- }
- l769:
- if !_rules[ruleRegisterOrConstant]() {
- goto l766
- }
- {
- position770, tokenIndex770 := position, tokenIndex
- if !_rules[ruleWS]() {
- goto l770
- }
- goto l771
- l770:
- position, tokenIndex = position770, tokenIndex770
- }
- l771:
- {
- position772, tokenIndex772 := position, tokenIndex
- if buffer[position] != rune(',') {
- goto l772
- }
- position++
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l772
- }
- position++
- l774:
+ position756, tokenIndex756 := position, tokenIndex
{
- position775, tokenIndex775 := position, tokenIndex
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l775
+ position759, tokenIndex759 := position, tokenIndex
+ if buffer[position] != rune('0') {
+ goto l760
}
position++
- goto l774
- l775:
- position, tokenIndex = position775, tokenIndex775
+ goto l759
+ l760:
+ position, tokenIndex = position759, tokenIndex759
+ if buffer[position] != rune('1') {
+ goto l756
+ }
+ position++
}
- goto l773
- l772:
- position, tokenIndex = position772, tokenIndex772
+ l759:
+ goto l755
+ l756:
+ position, tokenIndex = position756, tokenIndex756
}
- l773:
- goto l767
+ goto l751
+ l752:
+ position, tokenIndex = position751, tokenIndex751
+ if buffer[position] != rune('0') {
+ goto l761
+ }
+ position++
+ {
+ position762, tokenIndex762 := position, tokenIndex
+ if buffer[position] != rune('x') {
+ goto l763
+ }
+ position++
+ goto l762
+ l763:
+ position, tokenIndex = position762, tokenIndex762
+ if buffer[position] != rune('X') {
+ goto l761
+ }
+ position++
+ }
+ l762:
+ {
+ position766, tokenIndex766 := position, tokenIndex
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l767
+ }
+ position++
+ goto l766
+ l767:
+ position, tokenIndex = position766, tokenIndex766
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l768
+ }
+ position++
+ goto l766
+ l768:
+ position, tokenIndex = position766, tokenIndex766
+ {
+ position769, tokenIndex769 := position, tokenIndex
+ if c := buffer[position]; c < rune('a') || c > rune('f') {
+ goto l770
+ }
+ position++
+ goto l769
+ l770:
+ position, tokenIndex = position769, tokenIndex769
+ if c := buffer[position]; c < rune('A') || c > rune('F') {
+ goto l761
+ }
+ position++
+ }
+ l769:
+ }
l766:
- position, tokenIndex = position766, tokenIndex766
- }
- l767:
- if buffer[position] != rune(')') {
- goto l760
- }
- position++
- add(ruleBaseIndexScale, position761)
- }
- return true
- l760:
- position, tokenIndex = position760, tokenIndex760
- return false
- },
- /* 48 Operator <- <('+' / '-')> */
- func() bool {
- position776, tokenIndex776 := position, tokenIndex
- {
- position777 := position
- {
- position778, tokenIndex778 := position, tokenIndex
- if buffer[position] != rune('+') {
- goto l779
+ l764:
+ {
+ position765, tokenIndex765 := position, tokenIndex
+ {
+ position771, tokenIndex771 := position, tokenIndex
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l772
+ }
+ position++
+ goto l771
+ l772:
+ position, tokenIndex = position771, tokenIndex771
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l773
+ }
+ position++
+ goto l771
+ l773:
+ position, tokenIndex = position771, tokenIndex771
+ {
+ position774, tokenIndex774 := position, tokenIndex
+ if c := buffer[position]; c < rune('a') || c > rune('f') {
+ goto l775
+ }
+ position++
+ goto l774
+ l775:
+ position, tokenIndex = position774, tokenIndex774
+ if c := buffer[position]; c < rune('A') || c > rune('F') {
+ goto l765
+ }
+ position++
+ }
+ l774:
+ }
+ l771:
+ goto l764
+ l765:
+ position, tokenIndex = position765, tokenIndex765
+ }
+ goto l751
+ l761:
+ position, tokenIndex = position751, tokenIndex751
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l745
}
position++
- goto l778
- l779:
- position, tokenIndex = position778, tokenIndex778
- if buffer[position] != rune('-') {
+ l776:
+ {
+ position777, tokenIndex777 := position, tokenIndex
+ if c := buffer[position]; c < rune('0') || c > rune('9') {
+ goto l777
+ }
+ position++
goto l776
+ l777:
+ position, tokenIndex = position777, tokenIndex777
}
- position++
}
- l778:
- add(ruleOperator, position777)
+ l751:
+ add(ruleOffset, position746)
}
return true
- l776:
- position, tokenIndex = position776, tokenIndex776
+ l745:
+ position, tokenIndex = position745, tokenIndex745
return false
},
- /* 49 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */
+ /* 49 Section <- <([a-z] / [A-Z] / '@')+> */
func() bool {
- position780, tokenIndex780 := position, tokenIndex
+ position778, tokenIndex778 := position, tokenIndex
{
- position781 := position
+ position779 := position
{
position782, tokenIndex782 := position, tokenIndex
- if buffer[position] != rune('+') {
- goto l782
+ if c := buffer[position]; c < rune('a') || c > rune('z') {
+ goto l783
}
position++
- goto l783
- l782:
+ goto l782
+ l783:
position, tokenIndex = position782, tokenIndex782
- }
- l783:
- {
- position784, tokenIndex784 := position, tokenIndex
- if buffer[position] != rune('-') {
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l784
}
position++
- goto l785
+ goto l782
l784:
- position, tokenIndex = position784, tokenIndex784
- }
- l785:
- {
- position786, tokenIndex786 := position, tokenIndex
- if buffer[position] != rune('0') {
- goto l787
- }
- position++
- {
- position788, tokenIndex788 := position, tokenIndex
- if buffer[position] != rune('b') {
- goto l789
- }
- position++
- goto l788
- l789:
- position, tokenIndex = position788, tokenIndex788
- if buffer[position] != rune('B') {
- goto l787
- }
- position++
- }
- l788:
- {
- position792, tokenIndex792 := position, tokenIndex
- if buffer[position] != rune('0') {
- goto l793
- }
- position++
- goto l792
- l793:
- position, tokenIndex = position792, tokenIndex792
- if buffer[position] != rune('1') {
- goto l787
- }
- position++
- }
- l792:
- l790:
- {
- position791, tokenIndex791 := position, tokenIndex
- {
- position794, tokenIndex794 := position, tokenIndex
- if buffer[position] != rune('0') {
- goto l795
- }
- position++
- goto l794
- l795:
- position, tokenIndex = position794, tokenIndex794
- if buffer[position] != rune('1') {
- goto l791
- }
- position++
- }
- l794:
- goto l790
- l791:
- position, tokenIndex = position791, tokenIndex791
- }
- goto l786
- l787:
- position, tokenIndex = position786, tokenIndex786
- if buffer[position] != rune('0') {
- goto l796
- }
- position++
- {
- position797, tokenIndex797 := position, tokenIndex
- if buffer[position] != rune('x') {
- goto l798
- }
- position++
- goto l797
- l798:
- position, tokenIndex = position797, tokenIndex797
- if buffer[position] != rune('X') {
- goto l796
- }
- position++
- }
- l797:
- {
- position801, tokenIndex801 := position, tokenIndex
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l802
- }
- position++
- goto l801
- l802:
- position, tokenIndex = position801, tokenIndex801
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l803
- }
- position++
- goto l801
- l803:
- position, tokenIndex = position801, tokenIndex801
- {
- position804, tokenIndex804 := position, tokenIndex
- if c := buffer[position]; c < rune('a') || c > rune('f') {
- goto l805
- }
- position++
- goto l804
- l805:
- position, tokenIndex = position804, tokenIndex804
- if c := buffer[position]; c < rune('A') || c > rune('F') {
- goto l796
- }
- position++
- }
- l804:
- }
- l801:
- l799:
- {
- position800, tokenIndex800 := position, tokenIndex
- {
- position806, tokenIndex806 := position, tokenIndex
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l807
- }
- position++
- goto l806
- l807:
- position, tokenIndex = position806, tokenIndex806
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l808
- }
- position++
- goto l806
- l808:
- position, tokenIndex = position806, tokenIndex806
- {
- position809, tokenIndex809 := position, tokenIndex
- if c := buffer[position]; c < rune('a') || c > rune('f') {
- goto l810
- }
- position++
- goto l809
- l810:
- position, tokenIndex = position809, tokenIndex809
- if c := buffer[position]; c < rune('A') || c > rune('F') {
- goto l800
- }
- position++
- }
- l809:
- }
- l806:
- goto l799
- l800:
- position, tokenIndex = position800, tokenIndex800
- }
- goto l786
- l796:
- position, tokenIndex = position786, tokenIndex786
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l780
- }
- position++
- l811:
- {
- position812, tokenIndex812 := position, tokenIndex
- if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l812
- }
- position++
- goto l811
- l812:
- position, tokenIndex = position812, tokenIndex812
- }
- }
- l786:
- add(ruleOffset, position781)
- }
- return true
- l780:
- position, tokenIndex = position780, tokenIndex780
- return false
- },
- /* 50 Section <- <([a-z] / [A-Z] / '@')+> */
- func() bool {
- position813, tokenIndex813 := position, tokenIndex
- {
- position814 := position
- {
- position817, tokenIndex817 := position, tokenIndex
- if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l818
- }
- position++
- goto l817
- l818:
- position, tokenIndex = position817, tokenIndex817
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l819
- }
- position++
- goto l817
- l819:
- position, tokenIndex = position817, tokenIndex817
+ position, tokenIndex = position782, tokenIndex782
if buffer[position] != rune('@') {
- goto l813
+ goto l778
}
position++
}
- l817:
- l815:
+ l782:
+ l780:
{
- position816, tokenIndex816 := position, tokenIndex
+ position781, tokenIndex781 := position, tokenIndex
{
- position820, tokenIndex820 := position, tokenIndex
+ position785, tokenIndex785 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l821
+ goto l786
}
position++
- goto l820
- l821:
- position, tokenIndex = position820, tokenIndex820
+ goto l785
+ l786:
+ position, tokenIndex = position785, tokenIndex785
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l822
+ goto l787
}
position++
- goto l820
- l822:
- position, tokenIndex = position820, tokenIndex820
+ goto l785
+ l787:
+ position, tokenIndex = position785, tokenIndex785
if buffer[position] != rune('@') {
- goto l816
+ goto l781
}
position++
}
- l820:
- goto l815
- l816:
- position, tokenIndex = position816, tokenIndex816
+ l785:
+ goto l780
+ l781:
+ position, tokenIndex = position781, tokenIndex781
}
- add(ruleSection, position814)
+ add(ruleSection, position779)
}
return true
- l813:
- position, tokenIndex = position813, tokenIndex813
+ l778:
+ position, tokenIndex = position778, tokenIndex778
return false
},
- /* 51 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */
+ /* 50 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */
func() bool {
- position823, tokenIndex823 := position, tokenIndex
+ position788, tokenIndex788 := position, tokenIndex
{
- position824 := position
+ position789 := position
if buffer[position] != rune('%') {
- goto l823
+ goto l788
}
position++
{
- position825, tokenIndex825 := position, tokenIndex
+ position790, tokenIndex790 := position, tokenIndex
if c := buffer[position]; c < rune('c') || c > rune('g') {
- goto l826
+ goto l791
}
position++
- goto l825
- l826:
- position, tokenIndex = position825, tokenIndex825
+ goto l790
+ l791:
+ position, tokenIndex = position790, tokenIndex790
if buffer[position] != rune('s') {
- goto l823
+ goto l788
}
position++
}
- l825:
+ l790:
if buffer[position] != rune('s') {
- goto l823
+ goto l788
}
position++
if buffer[position] != rune(':') {
- goto l823
+ goto l788
}
position++
- add(ruleSegmentRegister, position824)
+ add(ruleSegmentRegister, position789)
}
return true
- l823:
- position, tokenIndex = position823, tokenIndex823
+ l788:
+ position, tokenIndex = position788, tokenIndex788
return false
},
}
diff --git a/util/fipstools/delocate/delocate_test.go b/util/fipstools/delocate/delocate_test.go
index ed504a0..43b3ff1 100644
--- a/util/fipstools/delocate/delocate_test.go
+++ b/util/fipstools/delocate/delocate_test.go
@@ -51,6 +51,7 @@
{"x86_64-LabelRewrite", []string{"in1.s", "in2.s"}, "out.s"},
{"x86_64-Sections", []string{"in.s"}, "out.s"},
{"x86_64-ThreeArg", []string{"in.s"}, "out.s"},
+ {"aarch64-Basic", []string{"in.s"}, "out.s"},
}
func TestDelocate(t *testing.T) {
diff --git a/util/fipstools/delocate/testdata/aarch64-Basic/in.s b/util/fipstools/delocate/testdata/aarch64-Basic/in.s
new file mode 100644
index 0000000..e1c256a
--- /dev/null
+++ b/util/fipstools/delocate/testdata/aarch64-Basic/in.s
@@ -0,0 +1,53 @@
+ .type foo, %function
+ .globl foo
+foo:
+ // GOT load
+ adrp x1, :got:stderr
+ ldr x0, [x1, :got_lo12:stderr]
+
+ // GOT load to x0
+ adrp x0, :got:stderr
+ ldr x1, [x0, :got_lo12:stderr]
+
+ // GOT load with no register move
+ adrp x0, :got:stderr
+ ldr x0, [x0, :got_lo12:stderr]
+
+ // Address load
+ adrp x0, .Llocal_data
+ add x1, x0, :lo12:.Llocal_data
+
+ // Address of local symbol with offset
+ adrp x10, .Llocal_data2+16
+ add x11, x10, :lo12:.Llocal_data2+16
+
+ // Address load with no-op add instruction
+ adrp x0, .Llocal_data
+ add x0, x0, :lo12:.Llocal_data
+
+ // armcap
+ adrp x1, OPENSSL_armcap_P
+ ldr w2, [x1, :lo12:OPENSSL_armcap_P]
+
+ // armcap to w0
+ adrp x0, OPENSSL_armcap_P
+ ldr w1, [x1, :lo12:OPENSSL_armcap_P]
+
+ // Load from local symbol
+ adrp x10, .Llocal_data2
+ ldr q0, [x10, :lo12:.Llocal_data2]
+
+ bl local_function
+
+ bl remote_function
+
+ bl bss_symbol_bss_get
+
+local_function:
+
+// BSS data
+.type bss_symbol,@object
+.section .bss.bss_symbol,"aw",@nobits
+bss_symbol:
+.word 0
+.size bss_symbol, 4
diff --git a/util/fipstools/delocate/testdata/aarch64-Basic/out.s b/util/fipstools/delocate/testdata/aarch64-Basic/out.s
new file mode 100644
index 0000000..eb401da
--- /dev/null
+++ b/util/fipstools/delocate/testdata/aarch64-Basic/out.s
@@ -0,0 +1,209 @@
+.text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
+BORINGSSL_bcm_text_start:
+ .type foo, %function
+ .globl foo
+.Lfoo_local_target:
+foo:
+ // GOT load
+// WAS adrp x1, :got:stderr
+ sub sp, sp, 128
+ stp x0, lr, [sp, #-16]!
+ bl .Lboringssl_loadgot_stderr
+ mov x1, x0
+ ldp x0, lr, [sp], #16
+ add sp, sp, 128
+// WAS ldr x0, [x1, :got_lo12:stderr]
+ mov x0, x1
+
+ // GOT load to x0
+// WAS adrp x0, :got:stderr
+ sub sp, sp, 128
+ stp x0, lr, [sp, #-16]!
+ bl .Lboringssl_loadgot_stderr
+ ldp xzr, lr, [sp], #16
+ add sp, sp, 128
+// WAS ldr x1, [x0, :got_lo12:stderr]
+ mov x1, x0
+
+ // GOT load with no register move
+// WAS adrp x0, :got:stderr
+ sub sp, sp, 128
+ stp x0, lr, [sp, #-16]!
+ bl .Lboringssl_loadgot_stderr
+ ldp xzr, lr, [sp], #16
+ add sp, sp, 128
+// WAS ldr x0, [x0, :got_lo12:stderr]
+
+ // Address load
+// WAS adrp x0, .Llocal_data
+ adr x0, .Llocal_data
+// WAS add x1, x0, :lo12:.Llocal_data
+ add x1, x0, #0
+
+ // Address of local symbol with offset
+// WAS adrp x10, .Llocal_data2+16
+ adr x10, .Llocal_data2+16
+// WAS add x11, x10, :lo12:.Llocal_data2+16
+ add x11, x10, #0
+
+ // Address load with no-op add instruction
+// WAS adrp x0, .Llocal_data
+ adr x0, .Llocal_data
+// WAS add x0, x0, :lo12:.Llocal_data
+
+ // armcap
+// WAS adrp x1, OPENSSL_armcap_P
+ sub sp, sp, 128
+ stp x0, lr, [sp, #-16]!
+ bl .LOPENSSL_armcap_P_addr
+ mov x1, x0
+ ldp x0, lr, [sp], #16
+ add sp, sp, 128
+// WAS ldr w2, [x1, :lo12:OPENSSL_armcap_P]
+ ldr w2, [x1]
+
+ // armcap to w0
+// WAS adrp x0, OPENSSL_armcap_P
+ sub sp, sp, 128
+ stp x0, lr, [sp, #-16]!
+ bl .LOPENSSL_armcap_P_addr
+ ldp xzr, lr, [sp], #16
+ add sp, sp, 128
+// WAS ldr w1, [x1, :lo12:OPENSSL_armcap_P]
+ ldr w1, [x1]
+
+ // Load from local symbol
+// WAS adrp x10, .Llocal_data2
+ adr x10, .Llocal_data2
+// WAS ldr q0, [x10, :lo12:.Llocal_data2]
+ ldr q0, [x10]
+
+// WAS bl local_function
+ bl .Llocal_function_local_target
+
+// WAS bl remote_function
+ bl bcm_redirector_remote_function
+
+ bl bss_symbol_bss_get
+
+.Llocal_function_local_target:
+local_function:
+
+// BSS data
+.type bss_symbol,@object
+.section .bss.bss_symbol,"aw",@nobits
+bss_symbol:
+.Lbss_symbol_local_target:
+
+.word 0
+.size bss_symbol, 4
+.text
+.loc 1 2 0
+BORINGSSL_bcm_text_end:
+.p2align 2
+.hidden bcm_redirector_remote_function
+.type bcm_redirector_remote_function, @function
+bcm_redirector_remote_function:
+.cfi_startproc
+ b remote_function
+.cfi_endproc
+.size bcm_redirector_remote_function, .-bcm_redirector_remote_function
+.p2align 2
+.hidden bss_symbol_bss_get
+.type bss_symbol_bss_get, @function
+bss_symbol_bss_get:
+.cfi_startproc
+ adrp x0, .Lbss_symbol_local_target
+ add x0, x0, :lo12:.Lbss_symbol_local_target
+ ret
+.cfi_endproc
+.size bss_symbol_bss_get, .-bss_symbol_bss_get
+.p2align 2
+.hidden .Lboringssl_loadgot_stderr
+.type .Lboringssl_loadgot_stderr, @function
+.Lboringssl_loadgot_stderr:
+.cfi_startproc
+ adrp x0, :got:stderr
+ ldr x0, [x0, :got_lo12:stderr]
+ ret
+.cfi_endproc
+.size .Lboringssl_loadgot_stderr, .-.Lboringssl_loadgot_stderr
+.p2align 2
+.hidden .LOPENSSL_armcap_P_addr
+.type .LOPENSSL_armcap_P_addr, @function
+.LOPENSSL_armcap_P_addr:
+.cfi_startproc
+ adrp x0, OPENSSL_armcap_P
+ add x0, x0, :lo12:OPENSSL_armcap_P
+ ret
+.cfi_endproc
+.size .LOPENSSL_armcap_P_addr, .-.LOPENSSL_armcap_P_addr
+.type BORINGSSL_bcm_text_hash, @object
+.size BORINGSSL_bcm_text_hash, 64
+BORINGSSL_bcm_text_hash:
+.byte 0xae
+.byte 0x2c
+.byte 0xea
+.byte 0x2a
+.byte 0xbd
+.byte 0xa6
+.byte 0xf3
+.byte 0xec
+.byte 0x97
+.byte 0x7f
+.byte 0x9b
+.byte 0xf6
+.byte 0x94
+.byte 0x9a
+.byte 0xfc
+.byte 0x83
+.byte 0x68
+.byte 0x27
+.byte 0xcb
+.byte 0xa0
+.byte 0xa0
+.byte 0x9f
+.byte 0x6b
+.byte 0x6f
+.byte 0xde
+.byte 0x52
+.byte 0xcd
+.byte 0xe2
+.byte 0xcd
+.byte 0xff
+.byte 0x31
+.byte 0x80
+.byte 0xa2
+.byte 0xd4
+.byte 0xc3
+.byte 0x66
+.byte 0xf
+.byte 0xc2
+.byte 0x6a
+.byte 0x7b
+.byte 0xf4
+.byte 0xbe
+.byte 0x39
+.byte 0xa2
+.byte 0xd7
+.byte 0x25
+.byte 0xdb
+.byte 0x21
+.byte 0x98
+.byte 0xe9
+.byte 0xd5
+.byte 0x53
+.byte 0xbf
+.byte 0x5c
+.byte 0x32
+.byte 0x6
+.byte 0x83
+.byte 0x34
+.byte 0xc
+.byte 0x65
+.byte 0x89
+.byte 0x52
+.byte 0xbd
+.byte 0x1f