From 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e Mon Sep 17 00:00:00 2001 From: Terin Stock Date: Sun, 9 Mar 2025 17:47:56 +0100 Subject: [chore] remove vendor --- .../github.com/twitchyliquid64/golang-asm/LICENSE | 27 - .../twitchyliquid64/golang-asm/asm/arch/arch.go | 716 -- .../twitchyliquid64/golang-asm/asm/arch/arm.go | 257 - .../twitchyliquid64/golang-asm/asm/arch/arm64.go | 350 - .../twitchyliquid64/golang-asm/asm/arch/mips.go | 72 - .../twitchyliquid64/golang-asm/asm/arch/ppc64.go | 102 - .../twitchyliquid64/golang-asm/asm/arch/riscv64.go | 28 - .../twitchyliquid64/golang-asm/asm/arch/s390x.go | 81 - .../twitchyliquid64/golang-asm/bio/buf.go | 148 - .../twitchyliquid64/golang-asm/bio/buf_mmap.go | 62 - .../twitchyliquid64/golang-asm/bio/buf_nommap.go | 11 - .../twitchyliquid64/golang-asm/bio/must.go | 43 - .../twitchyliquid64/golang-asm/dwarf/dwarf.go | 1650 ----- .../twitchyliquid64/golang-asm/dwarf/dwarf_defs.go | 493 -- .../twitchyliquid64/golang-asm/goobj/builtin.go | 45 - .../golang-asm/goobj/builtinlist.go | 245 - .../twitchyliquid64/golang-asm/goobj/funcinfo.go | 233 - .../twitchyliquid64/golang-asm/goobj/objfile.go | 871 --- .../twitchyliquid64/golang-asm/obj/abi_string.go | 16 - .../golang-asm/obj/addrtype_string.go | 16 - .../twitchyliquid64/golang-asm/obj/arm/a.out.go | 410 -- .../twitchyliquid64/golang-asm/obj/arm/anames.go | 144 - .../twitchyliquid64/golang-asm/obj/arm/anames5.go | 77 - .../twitchyliquid64/golang-asm/obj/arm/asm5.go | 3096 --------- .../twitchyliquid64/golang-asm/obj/arm/list5.go | 124 - .../twitchyliquid64/golang-asm/obj/arm/obj5.go | 784 --- .../twitchyliquid64/golang-asm/obj/arm64/a.out.go | 1033 --- .../twitchyliquid64/golang-asm/obj/arm64/anames.go | 512 -- .../golang-asm/obj/arm64/anames7.go | 100 - .../twitchyliquid64/golang-asm/obj/arm64/asm7.go | 7140 -------------------- .../twitchyliquid64/golang-asm/obj/arm64/doc.go | 249 - .../twitchyliquid64/golang-asm/obj/arm64/list7.go | 288 - .../twitchyliquid64/golang-asm/obj/arm64/obj7.go | 998 --- .../golang-asm/obj/arm64/sysRegEnc.go | 895 --- .../twitchyliquid64/golang-asm/obj/data.go | 200 - .../twitchyliquid64/golang-asm/obj/dwarf.go | 690 -- .../twitchyliquid64/golang-asm/obj/go.go | 16 - .../twitchyliquid64/golang-asm/obj/inl.go | 131 - .../twitchyliquid64/golang-asm/obj/ld.go | 85 - .../twitchyliquid64/golang-asm/obj/line.go | 30 - .../twitchyliquid64/golang-asm/obj/link.go | 771 --- .../twitchyliquid64/golang-asm/obj/mips/a.out.go | 481 -- .../twitchyliquid64/golang-asm/obj/mips/anames.go | 135 - .../twitchyliquid64/golang-asm/obj/mips/anames0.go | 45 - .../twitchyliquid64/golang-asm/obj/mips/asm0.go | 2108 ------ .../twitchyliquid64/golang-asm/obj/mips/list0.go | 83 - .../twitchyliquid64/golang-asm/obj/mips/obj0.go | 1457 ---- .../twitchyliquid64/golang-asm/obj/objfile.go | 755 --- .../twitchyliquid64/golang-asm/obj/pass.go | 176 - .../twitchyliquid64/golang-asm/obj/pcln.go | 413 -- .../twitchyliquid64/golang-asm/obj/plist.go | 314 - .../twitchyliquid64/golang-asm/obj/ppc64/a.out.go | 1032 --- .../twitchyliquid64/golang-asm/obj/ppc64/anames.go | 615 -- .../golang-asm/obj/ppc64/anames9.go | 51 - .../twitchyliquid64/golang-asm/obj/ppc64/asm9.go | 5367 --------------- .../twitchyliquid64/golang-asm/obj/ppc64/doc.go | 244 - .../twitchyliquid64/golang-asm/obj/ppc64/list9.go | 104 - .../twitchyliquid64/golang-asm/obj/ppc64/obj9.go | 1278 ---- .../twitchyliquid64/golang-asm/obj/riscv/anames.go | 258 - .../twitchyliquid64/golang-asm/obj/riscv/cpu.go | 644 -- .../twitchyliquid64/golang-asm/obj/riscv/inst.go | 459 -- .../twitchyliquid64/golang-asm/obj/riscv/list.go | 33 - .../twitchyliquid64/golang-asm/obj/riscv/obj.go | 1999 ------ .../twitchyliquid64/golang-asm/obj/s390x/a.out.go | 1003 --- .../twitchyliquid64/golang-asm/obj/s390x/anames.go | 720 -- .../golang-asm/obj/s390x/anamesz.go | 39 - .../twitchyliquid64/golang-asm/obj/s390x/asmz.go | 5043 -------------- .../golang-asm/obj/s390x/condition_code.go | 126 - .../twitchyliquid64/golang-asm/obj/s390x/listz.go | 73 - .../twitchyliquid64/golang-asm/obj/s390x/objz.go | 735 -- .../twitchyliquid64/golang-asm/obj/s390x/rotate.go | 47 - .../twitchyliquid64/golang-asm/obj/s390x/vector.go | 1069 --- .../twitchyliquid64/golang-asm/obj/sym.go | 421 -- .../twitchyliquid64/golang-asm/obj/textflag.go | 54 - .../twitchyliquid64/golang-asm/obj/util.go | 598 -- .../twitchyliquid64/golang-asm/obj/wasm/a.out.go | 331 - .../twitchyliquid64/golang-asm/obj/wasm/anames.go | 208 - .../twitchyliquid64/golang-asm/obj/wasm/wasmobj.go | 1185 ---- .../twitchyliquid64/golang-asm/obj/x86/a.out.go | 423 -- .../twitchyliquid64/golang-asm/obj/x86/aenum.go | 1609 ----- .../twitchyliquid64/golang-asm/obj/x86/anames.go | 1607 ----- .../twitchyliquid64/golang-asm/obj/x86/asm6.go | 5446 --------------- .../golang-asm/obj/x86/avx_optabs.go | 4628 ------------- .../twitchyliquid64/golang-asm/obj/x86/evex.go | 382 -- .../twitchyliquid64/golang-asm/obj/x86/list6.go | 264 - .../twitchyliquid64/golang-asm/obj/x86/obj6.go | 1261 ---- .../twitchyliquid64/golang-asm/obj/x86/ytab.go | 44 - .../twitchyliquid64/golang-asm/objabi/autotype.go | 38 - .../twitchyliquid64/golang-asm/objabi/flag.go | 162 - .../twitchyliquid64/golang-asm/objabi/funcdata.go | 54 - .../twitchyliquid64/golang-asm/objabi/funcid.go | 100 - .../twitchyliquid64/golang-asm/objabi/head.go | 109 - .../twitchyliquid64/golang-asm/objabi/line.go | 114 - .../twitchyliquid64/golang-asm/objabi/path.go | 41 - .../twitchyliquid64/golang-asm/objabi/reloctype.go | 269 - .../golang-asm/objabi/reloctype_string.go | 17 - .../twitchyliquid64/golang-asm/objabi/stack.go | 33 - .../twitchyliquid64/golang-asm/objabi/symkind.go | 79 - .../golang-asm/objabi/symkind_string.go | 41 - .../twitchyliquid64/golang-asm/objabi/typekind.go | 40 - .../twitchyliquid64/golang-asm/objabi/util.go | 203 - .../twitchyliquid64/golang-asm/src/pos.go | 470 -- .../twitchyliquid64/golang-asm/src/xpos.go | 176 - .../twitchyliquid64/golang-asm/sys/arch.go | 187 - .../twitchyliquid64/golang-asm/sys/supported.go | 116 - .../golang-asm/unsafeheader/unsafeheader.go | 37 - 106 files changed, 70892 deletions(-) delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/LICENSE delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/bio/buf.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/bio/buf_mmap.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/bio/buf_nommap.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/bio/must.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf_defs.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/goobj/builtin.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/goobj/builtinlist.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/goobj/funcinfo.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/goobj/objfile.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm/obj5.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/list7.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/obj7.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/sysRegEnc.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/data.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/dwarf.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/go.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/inl.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ld.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/line.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/link.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames0.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/asm0.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/list0.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/mips/obj0.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/objfile.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/pass.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/pcln.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/plist.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames9.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/asm9.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/doc.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/list9.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/obj9.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/cpu.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/inst.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/list.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/obj.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anamesz.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/asmz.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/condition_code.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/listz.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/objz.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/rotate.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/vector.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/sym.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/textflag.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/util.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/wasmobj.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/a.out.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/aenum.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/anames.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/asm6.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/avx_optabs.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/evex.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/list6.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/obj6.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/obj/x86/ytab.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/autotype.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/flag.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/funcdata.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/funcid.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/head.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/line.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/path.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/reloctype.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/reloctype_string.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/stack.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/symkind.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/symkind_string.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/typekind.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/objabi/util.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/src/pos.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/sys/arch.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/sys/supported.go delete mode 100644 vendor/github.com/twitchyliquid64/golang-asm/unsafeheader/unsafeheader.go (limited to 'vendor/github.com/twitchyliquid64/golang-asm') diff --git a/vendor/github.com/twitchyliquid64/golang-asm/LICENSE b/vendor/github.com/twitchyliquid64/golang-asm/LICENSE deleted file mode 100644 index 6a66aea5e..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go deleted file mode 100644 index b8ddbc99d..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go +++ /dev/null @@ -1,716 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package arch defines architecture-specific information and support functions. -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/arm" - "github.com/twitchyliquid64/golang-asm/obj/arm64" - "github.com/twitchyliquid64/golang-asm/obj/mips" - "github.com/twitchyliquid64/golang-asm/obj/ppc64" - "github.com/twitchyliquid64/golang-asm/obj/riscv" - "github.com/twitchyliquid64/golang-asm/obj/s390x" - "github.com/twitchyliquid64/golang-asm/obj/wasm" - "github.com/twitchyliquid64/golang-asm/obj/x86" - "fmt" - "strings" -) - -// Pseudo-registers whose names are the constant name without the leading R. -const ( - RFP = -(iota + 1) - RSB - RSP - RPC -) - -// Arch wraps the link architecture object with more architecture-specific information. -type Arch struct { - *obj.LinkArch - // Map of instruction names to enumeration. - Instructions map[string]obj.As - // Map of register names to enumeration. - Register map[string]int16 - // Table of register prefix names. These are things like R for R(0) and SPR for SPR(268). - RegisterPrefix map[string]bool - // RegisterNumber converts R(10) into arm.REG_R10. - RegisterNumber func(string, int16) (int16, bool) - // Instruction is a jump. - IsJump func(word string) bool -} - -// nilRegisterNumber is the register number function for architectures -// that do not accept the R(N) notation. It always returns failure. -func nilRegisterNumber(name string, n int16) (int16, bool) { - return 0, false -} - -// Set configures the architecture specified by GOARCH and returns its representation. -// It returns nil if GOARCH is not recognized. -func Set(GOARCH string) *Arch { - switch GOARCH { - case "386": - return archX86(&x86.Link386) - case "amd64": - return archX86(&x86.Linkamd64) - case "arm": - return archArm() - case "arm64": - return archArm64() - case "mips": - return archMips(&mips.Linkmips) - case "mipsle": - return archMips(&mips.Linkmipsle) - case "mips64": - return archMips64(&mips.Linkmips64) - case "mips64le": - return archMips64(&mips.Linkmips64le) - case "ppc64": - return archPPC64(&ppc64.Linkppc64) - case "ppc64le": - return archPPC64(&ppc64.Linkppc64le) - case "riscv64": - return archRISCV64() - case "s390x": - return archS390x() - case "wasm": - return archWasm() - } - return nil -} - -func jumpX86(word string) bool { - return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN" -} - -func jumpRISCV(word string) bool { - switch word { - case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ", - "BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP": - return true - } - return false -} - -func jumpWasm(word string) bool { - return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf" -} - -func archX86(linkArch *obj.LinkArch) *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - for i, s := range x86.Register { - register[s] = int16(i + x86.REG_AL) - } - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - // Register prefix not used on this architecture. - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range x86.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseAMD64 - } - } - // Annoying aliases. - instructions["JA"] = x86.AJHI /* alternate */ - instructions["JAE"] = x86.AJCC /* alternate */ - instructions["JB"] = x86.AJCS /* alternate */ - instructions["JBE"] = x86.AJLS /* alternate */ - instructions["JC"] = x86.AJCS /* alternate */ - instructions["JCC"] = x86.AJCC /* carry clear (CF = 0) */ - instructions["JCS"] = x86.AJCS /* carry set (CF = 1) */ - instructions["JE"] = x86.AJEQ /* alternate */ - instructions["JEQ"] = x86.AJEQ /* equal (ZF = 1) */ - instructions["JG"] = x86.AJGT /* alternate */ - instructions["JGE"] = x86.AJGE /* greater than or equal (signed) (SF = OF) */ - instructions["JGT"] = x86.AJGT /* greater than (signed) (ZF = 0 && SF = OF) */ - instructions["JHI"] = x86.AJHI /* higher (unsigned) (CF = 0 && ZF = 0) */ - instructions["JHS"] = x86.AJCC /* alternate */ - instructions["JL"] = x86.AJLT /* alternate */ - instructions["JLE"] = x86.AJLE /* less than or equal (signed) (ZF = 1 || SF != OF) */ - instructions["JLO"] = x86.AJCS /* alternate */ - instructions["JLS"] = x86.AJLS /* lower or same (unsigned) (CF = 1 || ZF = 1) */ - instructions["JLT"] = x86.AJLT /* less than (signed) (SF != OF) */ - instructions["JMI"] = x86.AJMI /* negative (minus) (SF = 1) */ - instructions["JNA"] = x86.AJLS /* alternate */ - instructions["JNAE"] = x86.AJCS /* alternate */ - instructions["JNB"] = x86.AJCC /* alternate */ - instructions["JNBE"] = x86.AJHI /* alternate */ - instructions["JNC"] = x86.AJCC /* alternate */ - instructions["JNE"] = x86.AJNE /* not equal (ZF = 0) */ - instructions["JNG"] = x86.AJLE /* alternate */ - instructions["JNGE"] = x86.AJLT /* alternate */ - instructions["JNL"] = x86.AJGE /* alternate */ - instructions["JNLE"] = x86.AJGT /* alternate */ - instructions["JNO"] = x86.AJOC /* alternate */ - instructions["JNP"] = x86.AJPC /* alternate */ - instructions["JNS"] = x86.AJPL /* alternate */ - instructions["JNZ"] = x86.AJNE /* alternate */ - instructions["JO"] = x86.AJOS /* alternate */ - instructions["JOC"] = x86.AJOC /* overflow clear (OF = 0) */ - instructions["JOS"] = x86.AJOS /* overflow set (OF = 1) */ - instructions["JP"] = x86.AJPS /* alternate */ - instructions["JPC"] = x86.AJPC /* parity clear (PF = 0) */ - instructions["JPE"] = x86.AJPS /* alternate */ - instructions["JPL"] = x86.AJPL /* non-negative (plus) (SF = 0) */ - instructions["JPO"] = x86.AJPC /* alternate */ - instructions["JPS"] = x86.AJPS /* parity set (PF = 1) */ - instructions["JS"] = x86.AJMI /* alternate */ - instructions["JZ"] = x86.AJEQ /* alternate */ - instructions["MASKMOVDQU"] = x86.AMASKMOVOU - instructions["MOVD"] = x86.AMOVQ - instructions["MOVDQ2Q"] = x86.AMOVQ - instructions["MOVNTDQ"] = x86.AMOVNTO - instructions["MOVOA"] = x86.AMOVO - instructions["PSLLDQ"] = x86.APSLLO - instructions["PSRLDQ"] = x86.APSRLO - instructions["PADDD"] = x86.APADDL - - return &Arch{ - LinkArch: linkArch, - Instructions: instructions, - Register: register, - RegisterPrefix: nil, - RegisterNumber: nilRegisterNumber, - IsJump: jumpX86, - } -} - -func archArm() *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for x86. - for i := arm.REG_R0; i < arm.REG_SPSR; i++ { - register[obj.Rconv(i)] = int16(i) - } - // Avoid unintentionally clobbering g using R10. - delete(register, "R10") - register["g"] = arm.REG_R10 - for i := 0; i < 16; i++ { - register[fmt.Sprintf("C%d", i)] = int16(i) - } - - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - register["SP"] = RSP - registerPrefix := map[string]bool{ - "F": true, - "R": true, - } - - // special operands for DMB/DSB instructions - register["MB_SY"] = arm.REG_MB_SY - register["MB_ST"] = arm.REG_MB_ST - register["MB_ISH"] = arm.REG_MB_ISH - register["MB_ISHST"] = arm.REG_MB_ISHST - register["MB_NSH"] = arm.REG_MB_NSH - register["MB_NSHST"] = arm.REG_MB_NSHST - register["MB_OSH"] = arm.REG_MB_OSH - register["MB_OSHST"] = arm.REG_MB_OSHST - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range arm.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseARM - } - } - // Annoying aliases. - instructions["B"] = obj.AJMP - instructions["BL"] = obj.ACALL - // MCR differs from MRC by the way fields of the word are encoded. - // (Details in arm.go). Here we add the instruction so parse will find - // it, but give it an opcode number known only to us. - instructions["MCR"] = aMCR - - return &Arch{ - LinkArch: &arm.Linkarm, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: armRegisterNumber, - IsJump: jumpArm, - } -} - -func archArm64() *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for 386 and amd64. - register[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP) - for i := arm64.REG_R0; i <= arm64.REG_R31; i++ { - register[obj.Rconv(i)] = int16(i) - } - // Rename R18 to R18_PLATFORM to avoid accidental use. - register["R18_PLATFORM"] = register["R18"] - delete(register, "R18") - for i := arm64.REG_F0; i <= arm64.REG_F31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := arm64.REG_V0; i <= arm64.REG_V31; i++ { - register[obj.Rconv(i)] = int16(i) - } - - // System registers. - for i := 0; i < len(arm64.SystemReg); i++ { - register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg - } - - register["LR"] = arm64.REGLINK - register["DAIFSet"] = arm64.REG_DAIFSet - register["DAIFClr"] = arm64.REG_DAIFClr - register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP - register["PLDL1STRM"] = arm64.REG_PLDL1STRM - register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP - register["PLDL2STRM"] = arm64.REG_PLDL2STRM - register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP - register["PLDL3STRM"] = arm64.REG_PLDL3STRM - register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP - register["PLIL1STRM"] = arm64.REG_PLIL1STRM - register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP - register["PLIL2STRM"] = arm64.REG_PLIL2STRM - register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP - register["PLIL3STRM"] = arm64.REG_PLIL3STRM - register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP - register["PSTL1STRM"] = arm64.REG_PSTL1STRM - register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP - register["PSTL2STRM"] = arm64.REG_PSTL2STRM - register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP - register["PSTL3STRM"] = arm64.REG_PSTL3STRM - - // Conditional operators, like EQ, NE, etc. - register["EQ"] = arm64.COND_EQ - register["NE"] = arm64.COND_NE - register["HS"] = arm64.COND_HS - register["CS"] = arm64.COND_HS - register["LO"] = arm64.COND_LO - register["CC"] = arm64.COND_LO - register["MI"] = arm64.COND_MI - register["PL"] = arm64.COND_PL - register["VS"] = arm64.COND_VS - register["VC"] = arm64.COND_VC - register["HI"] = arm64.COND_HI - register["LS"] = arm64.COND_LS - register["GE"] = arm64.COND_GE - register["LT"] = arm64.COND_LT - register["GT"] = arm64.COND_GT - register["LE"] = arm64.COND_LE - register["AL"] = arm64.COND_AL - register["NV"] = arm64.COND_NV - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - register["SP"] = RSP - // Avoid unintentionally clobbering g using R28. - delete(register, "R28") - register["g"] = arm64.REG_R28 - registerPrefix := map[string]bool{ - "F": true, - "R": true, - "V": true, - } - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range arm64.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseARM64 - } - } - // Annoying aliases. - instructions["B"] = arm64.AB - instructions["BL"] = arm64.ABL - - return &Arch{ - LinkArch: &arm64.Linkarm64, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: arm64RegisterNumber, - IsJump: jumpArm64, - } - -} - -func archPPC64(linkArch *obj.LinkArch) *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for x86. - for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { - register[obj.Rconv(i)] = int16(i) - } - register["CR"] = ppc64.REG_CR - register["XER"] = ppc64.REG_XER - register["LR"] = ppc64.REG_LR - register["CTR"] = ppc64.REG_CTR - register["FPSCR"] = ppc64.REG_FPSCR - register["MSR"] = ppc64.REG_MSR - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - // Avoid unintentionally clobbering g using R30. - delete(register, "R30") - register["g"] = ppc64.REG_R30 - registerPrefix := map[string]bool{ - "CR": true, - "F": true, - "R": true, - "SPR": true, - } - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range ppc64.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABasePPC64 - } - } - // Annoying aliases. - instructions["BR"] = ppc64.ABR - instructions["BL"] = ppc64.ABL - - return &Arch{ - LinkArch: linkArch, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: ppc64RegisterNumber, - IsJump: jumpPPC64, - } -} - -func archMips(linkArch *obj.LinkArch) *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for x86. - for i := mips.REG_R0; i <= mips.REG_R31; i++ { - register[obj.Rconv(i)] = int16(i) - } - - for i := mips.REG_F0; i <= mips.REG_F31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_M0; i <= mips.REG_M31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { - register[obj.Rconv(i)] = int16(i) - } - register["HI"] = mips.REG_HI - register["LO"] = mips.REG_LO - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - // Avoid unintentionally clobbering g using R30. - delete(register, "R30") - register["g"] = mips.REG_R30 - - registerPrefix := map[string]bool{ - "F": true, - "FCR": true, - "M": true, - "R": true, - } - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range mips.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseMIPS - } - } - // Annoying alias. - instructions["JAL"] = mips.AJAL - - return &Arch{ - LinkArch: linkArch, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: mipsRegisterNumber, - IsJump: jumpMIPS, - } -} - -func archMips64(linkArch *obj.LinkArch) *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for x86. - for i := mips.REG_R0; i <= mips.REG_R31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_F0; i <= mips.REG_F31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_M0; i <= mips.REG_M31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := mips.REG_W0; i <= mips.REG_W31; i++ { - register[obj.Rconv(i)] = int16(i) - } - register["HI"] = mips.REG_HI - register["LO"] = mips.REG_LO - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - // Avoid unintentionally clobbering g using R30. - delete(register, "R30") - register["g"] = mips.REG_R30 - // Avoid unintentionally clobbering RSB using R28. - delete(register, "R28") - register["RSB"] = mips.REG_R28 - registerPrefix := map[string]bool{ - "F": true, - "FCR": true, - "M": true, - "R": true, - "W": true, - } - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range mips.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseMIPS - } - } - // Annoying alias. - instructions["JAL"] = mips.AJAL - - return &Arch{ - LinkArch: linkArch, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: mipsRegisterNumber, - IsJump: jumpMIPS, - } -} - -func archRISCV64() *Arch { - register := make(map[string]int16) - - // Standard register names. - for i := riscv.REG_X0; i <= riscv.REG_X31; i++ { - name := fmt.Sprintf("X%d", i-riscv.REG_X0) - register[name] = int16(i) - } - for i := riscv.REG_F0; i <= riscv.REG_F31; i++ { - name := fmt.Sprintf("F%d", i-riscv.REG_F0) - register[name] = int16(i) - } - - // General registers with ABI names. - register["ZERO"] = riscv.REG_ZERO - register["RA"] = riscv.REG_RA - register["SP"] = riscv.REG_SP - register["GP"] = riscv.REG_GP - register["TP"] = riscv.REG_TP - register["T0"] = riscv.REG_T0 - register["T1"] = riscv.REG_T1 - register["T2"] = riscv.REG_T2 - register["S0"] = riscv.REG_S0 - register["S1"] = riscv.REG_S1 - register["A0"] = riscv.REG_A0 - register["A1"] = riscv.REG_A1 - register["A2"] = riscv.REG_A2 - register["A3"] = riscv.REG_A3 - register["A4"] = riscv.REG_A4 - register["A5"] = riscv.REG_A5 - register["A6"] = riscv.REG_A6 - register["A7"] = riscv.REG_A7 - register["S2"] = riscv.REG_S2 - register["S3"] = riscv.REG_S3 - register["S4"] = riscv.REG_S4 - register["S5"] = riscv.REG_S5 - register["S6"] = riscv.REG_S6 - register["S7"] = riscv.REG_S7 - register["S8"] = riscv.REG_S8 - register["S9"] = riscv.REG_S9 - register["S10"] = riscv.REG_S10 - register["S11"] = riscv.REG_S11 - register["T3"] = riscv.REG_T3 - register["T4"] = riscv.REG_T4 - register["T5"] = riscv.REG_T5 - register["T6"] = riscv.REG_T6 - - // Go runtime register names. - register["g"] = riscv.REG_G - register["CTXT"] = riscv.REG_CTXT - register["TMP"] = riscv.REG_TMP - - // ABI names for floating point register. - register["FT0"] = riscv.REG_FT0 - register["FT1"] = riscv.REG_FT1 - register["FT2"] = riscv.REG_FT2 - register["FT3"] = riscv.REG_FT3 - register["FT4"] = riscv.REG_FT4 - register["FT5"] = riscv.REG_FT5 - register["FT6"] = riscv.REG_FT6 - register["FT7"] = riscv.REG_FT7 - register["FS0"] = riscv.REG_FS0 - register["FS1"] = riscv.REG_FS1 - register["FA0"] = riscv.REG_FA0 - register["FA1"] = riscv.REG_FA1 - register["FA2"] = riscv.REG_FA2 - register["FA3"] = riscv.REG_FA3 - register["FA4"] = riscv.REG_FA4 - register["FA5"] = riscv.REG_FA5 - register["FA6"] = riscv.REG_FA6 - register["FA7"] = riscv.REG_FA7 - register["FS2"] = riscv.REG_FS2 - register["FS3"] = riscv.REG_FS3 - register["FS4"] = riscv.REG_FS4 - register["FS5"] = riscv.REG_FS5 - register["FS6"] = riscv.REG_FS6 - register["FS7"] = riscv.REG_FS7 - register["FS8"] = riscv.REG_FS8 - register["FS9"] = riscv.REG_FS9 - register["FS10"] = riscv.REG_FS10 - register["FS11"] = riscv.REG_FS11 - register["FT8"] = riscv.REG_FT8 - register["FT9"] = riscv.REG_FT9 - register["FT10"] = riscv.REG_FT10 - register["FT11"] = riscv.REG_FT11 - - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range riscv.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseRISCV - } - } - - return &Arch{ - LinkArch: &riscv.LinkRISCV64, - Instructions: instructions, - Register: register, - RegisterPrefix: nil, - RegisterNumber: nilRegisterNumber, - IsJump: jumpRISCV, - } -} - -func archS390x() *Arch { - register := make(map[string]int16) - // Create maps for easy lookup of instruction names etc. - // Note that there is no list of names as there is for x86. - for i := s390x.REG_R0; i <= s390x.REG_R15; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := s390x.REG_F0; i <= s390x.REG_F15; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := s390x.REG_V0; i <= s390x.REG_V31; i++ { - register[obj.Rconv(i)] = int16(i) - } - for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ { - register[obj.Rconv(i)] = int16(i) - } - register["LR"] = s390x.REG_LR - // Pseudo-registers. - register["SB"] = RSB - register["FP"] = RFP - register["PC"] = RPC - // Avoid unintentionally clobbering g using R13. - delete(register, "R13") - register["g"] = s390x.REG_R13 - registerPrefix := map[string]bool{ - "AR": true, - "F": true, - "R": true, - } - - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range s390x.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseS390X - } - } - // Annoying aliases. - instructions["BR"] = s390x.ABR - instructions["BL"] = s390x.ABL - - return &Arch{ - LinkArch: &s390x.Links390x, - Instructions: instructions, - Register: register, - RegisterPrefix: registerPrefix, - RegisterNumber: s390xRegisterNumber, - IsJump: jumpS390x, - } -} - -func archWasm() *Arch { - instructions := make(map[string]obj.As) - for i, s := range obj.Anames { - instructions[s] = obj.As(i) - } - for i, s := range wasm.Anames { - if obj.As(i) >= obj.A_ARCHSPECIFIC { - instructions[s] = obj.As(i) + obj.ABaseWasm - } - } - - return &Arch{ - LinkArch: &wasm.Linkwasm, - Instructions: instructions, - Register: wasm.Register, - RegisterPrefix: nil, - RegisterNumber: nilRegisterNumber, - IsJump: jumpWasm, - } -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go deleted file mode 100644 index 645e98a57..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the ARM -// instruction set, to minimize its interaction with the core of the -// assembler. - -package arch - -import ( - "strings" - - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/arm" -) - -var armLS = map[string]uint8{ - "U": arm.C_UBIT, - "S": arm.C_SBIT, - "W": arm.C_WBIT, - "P": arm.C_PBIT, - "PW": arm.C_WBIT | arm.C_PBIT, - "WP": arm.C_WBIT | arm.C_PBIT, -} - -var armSCOND = map[string]uint8{ - "EQ": arm.C_SCOND_EQ, - "NE": arm.C_SCOND_NE, - "CS": arm.C_SCOND_HS, - "HS": arm.C_SCOND_HS, - "CC": arm.C_SCOND_LO, - "LO": arm.C_SCOND_LO, - "MI": arm.C_SCOND_MI, - "PL": arm.C_SCOND_PL, - "VS": arm.C_SCOND_VS, - "VC": arm.C_SCOND_VC, - "HI": arm.C_SCOND_HI, - "LS": arm.C_SCOND_LS, - "GE": arm.C_SCOND_GE, - "LT": arm.C_SCOND_LT, - "GT": arm.C_SCOND_GT, - "LE": arm.C_SCOND_LE, - "AL": arm.C_SCOND_NONE, - "U": arm.C_UBIT, - "S": arm.C_SBIT, - "W": arm.C_WBIT, - "P": arm.C_PBIT, - "PW": arm.C_WBIT | arm.C_PBIT, - "WP": arm.C_WBIT | arm.C_PBIT, - "F": arm.C_FBIT, - "IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT, - "IAW": arm.C_WBIT | arm.C_UBIT, - "DBW": arm.C_WBIT | arm.C_PBIT, - "DAW": arm.C_WBIT, - "IB": arm.C_PBIT | arm.C_UBIT, - "IA": arm.C_UBIT, - "DB": arm.C_PBIT, - "DA": 0, -} - -var armJump = map[string]bool{ - "B": true, - "BL": true, - "BX": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CALL": true, - "JMP": true, -} - -func jumpArm(word string) bool { - return armJump[word] -} - -// IsARMCMP reports whether the op (as defined by an arm.A* constant) is -// one of the comparison instructions that require special handling. -func IsARMCMP(op obj.As) bool { - switch op { - case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST: - return true - } - return false -} - -// IsARMSTREX reports whether the op (as defined by an arm.A* constant) is -// one of the STREX-like instructions that require special handling. -func IsARMSTREX(op obj.As) bool { - switch op { - case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU: - return true - } - return false -} - -// MCR is not defined by the obj/arm; instead we define it privately here. -// It is encoded as an MRC with a bit inside the instruction word, -// passed to arch.ARMMRCOffset. -const aMCR = arm.ALAST + 1 - -// IsARMMRC reports whether the op (as defined by an arm.A* constant) is -// MRC or MCR -func IsARMMRC(op obj.As) bool { - switch op { - case arm.AMRC, aMCR: // Note: aMCR is defined in this package. - return true - } - return false -} - -// IsARMBFX reports whether the op (as defined by an arm.A* constant) is one the -// BFX-like instructions which are in the form of "op $width, $LSB, (Reg,) Reg". -func IsARMBFX(op obj.As) bool { - switch op { - case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI: - return true - } - return false -} - -// IsARMFloatCmp reports whether the op is a floating comparison instruction. -func IsARMFloatCmp(op obj.As) bool { - switch op { - case arm.ACMPF, arm.ACMPD: - return true - } - return false -} - -// ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions. -// The difference between MRC and MCR is represented by a bit high in the word, not -// in the usual way by the opcode itself. Asm must use AMRC for both instructions, so -// we return the opcode for MRC so that asm doesn't need to import obj/arm. -func ARMMRCOffset(op obj.As, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 obj.As, ok bool) { - op1 := int64(0) - if op == arm.AMRC { - op1 = 1 - } - bits, ok := ParseARMCondition(cond) - if !ok { - return - } - offset = (0xe << 24) | // opcode - (op1 << 20) | // MCR/MRC - ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond - ((x0 & 15) << 8) | //coprocessor number - ((x1 & 7) << 21) | // coprocessor operation - ((x2 & 15) << 12) | // ARM register - ((x3 & 15) << 16) | // Crn - ((x4 & 15) << 0) | // Crm - ((x5 & 7) << 5) | // coprocessor information - (1 << 4) /* must be set */ - return offset, arm.AMRC, true -} - -// IsARMMULA reports whether the op (as defined by an arm.A* constant) is -// MULA, MULS, MMULA, MMULS, MULABB, MULAWB or MULAWT, the 4-operand instructions. -func IsARMMULA(op obj.As) bool { - switch op { - case arm.AMULA, arm.AMULS, arm.AMMULA, arm.AMMULS, arm.AMULABB, arm.AMULAWB, arm.AMULAWT: - return true - } - return false -} - -var bcode = []obj.As{ - arm.ABEQ, - arm.ABNE, - arm.ABCS, - arm.ABCC, - arm.ABMI, - arm.ABPL, - arm.ABVS, - arm.ABVC, - arm.ABHI, - arm.ABLS, - arm.ABGE, - arm.ABLT, - arm.ABGT, - arm.ABLE, - arm.AB, - obj.ANOP, -} - -// ARMConditionCodes handles the special condition code situation for the ARM. -// It returns a boolean to indicate success; failure means cond was unrecognized. -func ARMConditionCodes(prog *obj.Prog, cond string) bool { - if cond == "" { - return true - } - bits, ok := ParseARMCondition(cond) - if !ok { - return false - } - /* hack to make B.NE etc. work: turn it into the corresponding conditional */ - if prog.As == arm.AB { - prog.As = bcode[(bits^arm.C_SCOND_XOR)&0xf] - bits = (bits &^ 0xf) | arm.C_SCOND_NONE - } - prog.Scond = bits - return true -} - -// ParseARMCondition parses the conditions attached to an ARM instruction. -// The input is a single string consisting of period-separated condition -// codes, such as ".P.W". An initial period is ignored. -func ParseARMCondition(cond string) (uint8, bool) { - return parseARMCondition(cond, armLS, armSCOND) -} - -func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) { - cond = strings.TrimPrefix(cond, ".") - if cond == "" { - return arm.C_SCOND_NONE, true - } - names := strings.Split(cond, ".") - bits := uint8(0) - for _, name := range names { - if b, present := ls[name]; present { - bits |= b - continue - } - if b, present := scond[name]; present { - bits = (bits &^ arm.C_SCOND) | b - continue - } - return 0, false - } - return bits, true -} - -func armRegisterNumber(name string, n int16) (int16, bool) { - if n < 0 || 15 < n { - return 0, false - } - switch name { - case "R": - return arm.REG_R0 + n, true - case "F": - return arm.REG_F0 + n, true - } - return 0, false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go deleted file mode 100644 index b0606beb3..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the ARM64 -// instruction set, to minimize its interaction with the core of the -// assembler. - -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/arm64" - "errors" -) - -var arm64LS = map[string]uint8{ - "P": arm64.C_XPOST, - "W": arm64.C_XPRE, -} - -var arm64Jump = map[string]bool{ - "B": true, - "BL": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CALL": true, - "CBZ": true, - "CBZW": true, - "CBNZ": true, - "CBNZW": true, - "JMP": true, - "TBNZ": true, - "TBZ": true, -} - -func jumpArm64(word string) bool { - return arm64Jump[word] -} - -// IsARM64CMP reports whether the op (as defined by an arm.A* constant) is -// one of the comparison instructions that require special handling. -func IsARM64CMP(op obj.As) bool { - switch op { - case arm64.ACMN, arm64.ACMP, arm64.ATST, - arm64.ACMNW, arm64.ACMPW, arm64.ATSTW, - arm64.AFCMPS, arm64.AFCMPD, - arm64.AFCMPES, arm64.AFCMPED: - return true - } - return false -} - -// IsARM64STLXR reports whether the op (as defined by an arm64.A* -// constant) is one of the STLXR-like instructions that require special -// handling. -func IsARM64STLXR(op obj.As) bool { - switch op { - case arm64.ASTLXRB, arm64.ASTLXRH, arm64.ASTLXRW, arm64.ASTLXR, - arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR, - arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW: - return true - } - // atomic instructions - if arm64.IsAtomicInstruction(op) { - return true - } - return false -} - -// ARM64Suffix handles the special suffix for the ARM64. -// It returns a boolean to indicate success; failure means -// cond was unrecognized. -func ARM64Suffix(prog *obj.Prog, cond string) bool { - if cond == "" { - return true - } - bits, ok := parseARM64Suffix(cond) - if !ok { - return false - } - prog.Scond = bits - return true -} - -// parseARM64Suffix parses the suffix attached to an ARM64 instruction. -// The input is a single string consisting of period-separated condition -// codes, such as ".P.W". An initial period is ignored. -func parseARM64Suffix(cond string) (uint8, bool) { - if cond == "" { - return 0, true - } - return parseARMCondition(cond, arm64LS, nil) -} - -func arm64RegisterNumber(name string, n int16) (int16, bool) { - switch name { - case "F": - if 0 <= n && n <= 31 { - return arm64.REG_F0 + n, true - } - case "R": - if 0 <= n && n <= 30 { // not 31 - return arm64.REG_R0 + n, true - } - case "V": - if 0 <= n && n <= 31 { - return arm64.REG_V0 + n, true - } - } - return 0, false -} - -// IsARM64TBL reports whether the op (as defined by an arm64.A* -// constant) is one of the table lookup instructions that require special -// handling. -func IsARM64TBL(op obj.As) bool { - return op == arm64.AVTBL -} - -// ARM64RegisterExtension parses an ARM64 register with extension or arrangement. -func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error { - Rnum := (reg & 31) + int16(num<<5) - if isAmount { - if num < 0 || num > 7 { - return errors.New("index shift amount is out of range") - } - } - switch ext { - case "UXTB": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - return errors.New("invalid shift for the register offset addressing mode") - } - a.Reg = arm64.REG_UXTB + Rnum - case "UXTH": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - return errors.New("invalid shift for the register offset addressing mode") - } - a.Reg = arm64.REG_UXTH + Rnum - case "UXTW": - if !isAmount { - return errors.New("invalid register extension") - } - // effective address of memory is a base register value and an offset register value. - if a.Type == obj.TYPE_MEM { - a.Index = arm64.REG_UXTW + Rnum - } else { - a.Reg = arm64.REG_UXTW + Rnum - } - case "UXTX": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - return errors.New("invalid shift for the register offset addressing mode") - } - a.Reg = arm64.REG_UXTX + Rnum - case "SXTB": - if !isAmount { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_SXTB + Rnum - case "SXTH": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - return errors.New("invalid shift for the register offset addressing mode") - } - a.Reg = arm64.REG_SXTH + Rnum - case "SXTW": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - a.Index = arm64.REG_SXTW + Rnum - } else { - a.Reg = arm64.REG_SXTW + Rnum - } - case "SXTX": - if !isAmount { - return errors.New("invalid register extension") - } - if a.Type == obj.TYPE_MEM { - a.Index = arm64.REG_SXTX + Rnum - } else { - a.Reg = arm64.REG_SXTX + Rnum - } - case "LSL": - if !isAmount { - return errors.New("invalid register extension") - } - a.Index = arm64.REG_LSL + Rnum - case "B8": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5) - case "B16": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5) - case "H4": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5) - case "H8": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5) - case "S2": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5) - case "S4": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5) - case "D1": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5) - case "D2": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5) - case "Q1": - if isIndex { - return errors.New("invalid register extension") - } - a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5) - case "B": - if !isIndex { - return nil - } - a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5) - a.Index = num - case "H": - if !isIndex { - return nil - } - a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5) - a.Index = num - case "S": - if !isIndex { - return nil - } - a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5) - a.Index = num - case "D": - if !isIndex { - return nil - } - a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5) - a.Index = num - default: - return errors.New("unsupported register extension type: " + ext) - } - - return nil -} - -// ARM64RegisterArrangement parses an ARM64 vector register arrangement. -func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) { - var curQ, curSize uint16 - if name[0] != 'V' { - return 0, errors.New("expect V0 through V31; found: " + name) - } - if reg < 0 { - return 0, errors.New("invalid register number: " + name) - } - switch arng { - case "B8": - curSize = 0 - curQ = 0 - case "B16": - curSize = 0 - curQ = 1 - case "H4": - curSize = 1 - curQ = 0 - case "H8": - curSize = 1 - curQ = 1 - case "S2": - curSize = 2 - curQ = 0 - case "S4": - curSize = 2 - curQ = 1 - case "D1": - curSize = 3 - curQ = 0 - case "D2": - curSize = 3 - curQ = 1 - default: - return 0, errors.New("invalid arrangement in ARM64 register list") - } - return (int64(curQ) & 1 << 30) | (int64(curSize&3) << 10), nil -} - -// ARM64RegisterListOffset generates offset encoding according to AArch64 specification. -func ARM64RegisterListOffset(firstReg, regCnt int, arrangement int64) (int64, error) { - offset := int64(firstReg) - switch regCnt { - case 1: - offset |= 0x7 << 12 - case 2: - offset |= 0xa << 12 - case 3: - offset |= 0x6 << 12 - case 4: - offset |= 0x2 << 12 - default: - return 0, errors.New("invalid register numbers in ARM64 register list") - } - offset |= arrangement - // arm64 uses the 60th bit to differentiate from other archs - // For more details, refer to: obj/arm64/list7.go - offset |= 1 << 60 - return offset, nil -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go deleted file mode 100644 index 7af9dbb23..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the -// MIPS (MIPS64) instruction set, to minimize its interaction -// with the core of the assembler. - -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/mips" -) - -func jumpMIPS(word string) bool { - switch word { - case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL": - return true - } - return false -} - -// IsMIPSCMP reports whether the op (as defined by an mips.A* constant) is -// one of the CMP instructions that require special handling. -func IsMIPSCMP(op obj.As) bool { - switch op { - case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED, - mips.ACMPGTF, mips.ACMPGTD: - return true - } - return false -} - -// IsMIPSMUL reports whether the op (as defined by an mips.A* constant) is -// one of the MUL/DIV/REM/MADD/MSUB instructions that require special handling. -func IsMIPSMUL(op obj.As) bool { - switch op { - case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU, - mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU, - mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU, - mips.AMADD, mips.AMSUB: - return true - } - return false -} - -func mipsRegisterNumber(name string, n int16) (int16, bool) { - switch name { - case "F": - if 0 <= n && n <= 31 { - return mips.REG_F0 + n, true - } - case "FCR": - if 0 <= n && n <= 31 { - return mips.REG_FCR0 + n, true - } - case "M": - if 0 <= n && n <= 31 { - return mips.REG_M0 + n, true - } - case "R": - if 0 <= n && n <= 31 { - return mips.REG_R0 + n, true - } - case "W": - if 0 <= n && n <= 31 { - return mips.REG_W0 + n, true - } - } - return 0, false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go deleted file mode 100644 index 8b2f097d5..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the -// 64-bit PowerPC (PPC64) instruction set, to minimize its interaction -// with the core of the assembler. - -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/ppc64" -) - -func jumpPPC64(word string) bool { - switch word { - case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "CALL", "JMP": - return true - } - return false -} - -// IsPPC64RLD reports whether the op (as defined by an ppc64.A* constant) is -// one of the RLD-like instructions that require special handling. -// The FMADD-like instructions behave similarly. -func IsPPC64RLD(op obj.As) bool { - switch op { - case ppc64.ARLDC, ppc64.ARLDCCC, ppc64.ARLDCL, ppc64.ARLDCLCC, - ppc64.ARLDCR, ppc64.ARLDCRCC, ppc64.ARLDMI, ppc64.ARLDMICC, - ppc64.ARLWMI, ppc64.ARLWMICC, ppc64.ARLWNM, ppc64.ARLWNMCC: - return true - case ppc64.AFMADD, ppc64.AFMADDCC, ppc64.AFMADDS, ppc64.AFMADDSCC, - ppc64.AFMSUB, ppc64.AFMSUBCC, ppc64.AFMSUBS, ppc64.AFMSUBSCC, - ppc64.AFNMADD, ppc64.AFNMADDCC, ppc64.AFNMADDS, ppc64.AFNMADDSCC, - ppc64.AFNMSUB, ppc64.AFNMSUBCC, ppc64.AFNMSUBS, ppc64.AFNMSUBSCC: - return true - } - return false -} - -func IsPPC64ISEL(op obj.As) bool { - return op == ppc64.AISEL -} - -// IsPPC64CMP reports whether the op (as defined by an ppc64.A* constant) is -// one of the CMP instructions that require special handling. -func IsPPC64CMP(op obj.As) bool { - switch op { - case ppc64.ACMP, ppc64.ACMPU, ppc64.ACMPW, ppc64.ACMPWU, ppc64.AFCMPU: - return true - } - return false -} - -// IsPPC64NEG reports whether the op (as defined by an ppc64.A* constant) is -// one of the NEG-like instructions that require special handling. -func IsPPC64NEG(op obj.As) bool { - switch op { - case ppc64.AADDMECC, ppc64.AADDMEVCC, ppc64.AADDMEV, ppc64.AADDME, - ppc64.AADDZECC, ppc64.AADDZEVCC, ppc64.AADDZEV, ppc64.AADDZE, - ppc64.ACNTLZDCC, ppc64.ACNTLZD, ppc64.ACNTLZWCC, ppc64.ACNTLZW, - ppc64.AEXTSBCC, ppc64.AEXTSB, ppc64.AEXTSHCC, ppc64.AEXTSH, - ppc64.AEXTSWCC, ppc64.AEXTSW, ppc64.ANEGCC, ppc64.ANEGVCC, - ppc64.ANEGV, ppc64.ANEG, ppc64.ASLBMFEE, ppc64.ASLBMFEV, - ppc64.ASLBMTE, ppc64.ASUBMECC, ppc64.ASUBMEVCC, ppc64.ASUBMEV, - ppc64.ASUBME, ppc64.ASUBZECC, ppc64.ASUBZEVCC, ppc64.ASUBZEV, - ppc64.ASUBZE: - return true - } - return false -} - -func ppc64RegisterNumber(name string, n int16) (int16, bool) { - switch name { - case "CR": - if 0 <= n && n <= 7 { - return ppc64.REG_CR0 + n, true - } - case "VS": - if 0 <= n && n <= 63 { - return ppc64.REG_VS0 + n, true - } - case "V": - if 0 <= n && n <= 31 { - return ppc64.REG_V0 + n, true - } - case "F": - if 0 <= n && n <= 31 { - return ppc64.REG_F0 + n, true - } - case "R": - if 0 <= n && n <= 31 { - return ppc64.REG_R0 + n, true - } - case "SPR": - if 0 <= n && n <= 1024 { - return ppc64.REG_SPR0 + n, true - } - } - return 0, false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go deleted file mode 100644 index e4f17536a..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the RISCV64 -// instruction set, to minimize its interaction with the core of the -// assembler. - -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/obj/riscv" -) - -// IsRISCV64AMO reports whether the op (as defined by a riscv.A* -// constant) is one of the AMO instructions that requires special -// handling. -func IsRISCV64AMO(op obj.As) bool { - switch op { - case riscv.ASCW, riscv.ASCD, riscv.AAMOSWAPW, riscv.AAMOSWAPD, riscv.AAMOADDW, riscv.AAMOADDD, - riscv.AAMOANDW, riscv.AAMOANDD, riscv.AAMOORW, riscv.AAMOORD, riscv.AAMOXORW, riscv.AAMOXORD, - riscv.AAMOMINW, riscv.AAMOMIND, riscv.AAMOMINUW, riscv.AAMOMINUD, - riscv.AAMOMAXW, riscv.AAMOMAXD, riscv.AAMOMAXUW, riscv.AAMOMAXUD: - return true - } - return false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go deleted file mode 100644 index 1e33f1e32..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file encapsulates some of the odd characteristics of the -// s390x instruction set, to minimize its interaction -// with the core of the assembler. - -package arch - -import ( - "github.com/twitchyliquid64/golang-asm/obj/s390x" -) - -func jumpS390x(word string) bool { - switch word { - case "BRC", - "BC", - "BCL", - "BEQ", - "BGE", - "BGT", - "BL", - "BLE", - "BLEU", - "BLT", - "BLTU", - "BNE", - "BR", - "BVC", - "BVS", - "BRCT", - "BRCTG", - "CMPBEQ", - "CMPBGE", - "CMPBGT", - "CMPBLE", - "CMPBLT", - "CMPBNE", - "CMPUBEQ", - "CMPUBGE", - "CMPUBGT", - "CMPUBLE", - "CMPUBLT", - "CMPUBNE", - "CRJ", - "CGRJ", - "CLRJ", - "CLGRJ", - "CIJ", - "CGIJ", - "CLIJ", - "CLGIJ", - "CALL", - "JMP": - return true - } - return false -} - -func s390xRegisterNumber(name string, n int16) (int16, bool) { - switch name { - case "AR": - if 0 <= n && n <= 15 { - return s390x.REG_AR0 + n, true - } - case "F": - if 0 <= n && n <= 15 { - return s390x.REG_F0 + n, true - } - case "R": - if 0 <= n && n <= 15 { - return s390x.REG_R0 + n, true - } - case "V": - if 0 <= n && n <= 31 { - return s390x.REG_V0 + n, true - } - } - return 0, false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf.go b/vendor/github.com/twitchyliquid64/golang-asm/bio/buf.go deleted file mode 100644 index c4c251490..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bio implements common I/O abstractions used within the Go toolchain. -package bio - -import ( - "bufio" - "io" - "log" - "os" -) - -// Reader implements a seekable buffered io.Reader. -type Reader struct { - f *os.File - *bufio.Reader -} - -// Writer implements a seekable buffered io.Writer. -type Writer struct { - f *os.File - *bufio.Writer -} - -// Create creates the file named name and returns a Writer -// for that file. -func Create(name string) (*Writer, error) { - f, err := os.Create(name) - if err != nil { - return nil, err - } - return &Writer{f: f, Writer: bufio.NewWriter(f)}, nil -} - -// Open returns a Reader for the file named name. -func Open(name string) (*Reader, error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - return NewReader(f), nil -} - -// NewReader returns a Reader from an open file. -func NewReader(f *os.File) *Reader { - return &Reader{f: f, Reader: bufio.NewReader(f)} -} - -func (r *Reader) MustSeek(offset int64, whence int) int64 { - if whence == 1 { - offset -= int64(r.Buffered()) - } - off, err := r.f.Seek(offset, whence) - if err != nil { - log.Fatalf("seeking in output: %v", err) - } - r.Reset(r.f) - return off -} - -func (w *Writer) MustSeek(offset int64, whence int) int64 { - if err := w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } - off, err := w.f.Seek(offset, whence) - if err != nil { - log.Fatalf("seeking in output: %v", err) - } - return off -} - -func (r *Reader) Offset() int64 { - off, err := r.f.Seek(0, 1) - if err != nil { - log.Fatalf("seeking in output [0, 1]: %v", err) - } - off -= int64(r.Buffered()) - return off -} - -func (w *Writer) Offset() int64 { - if err := w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } - off, err := w.f.Seek(0, 1) - if err != nil { - log.Fatalf("seeking in output [0, 1]: %v", err) - } - return off -} - -func (r *Reader) Close() error { - return r.f.Close() -} - -func (w *Writer) Close() error { - err := w.Flush() - err1 := w.f.Close() - if err == nil { - err = err1 - } - return err -} - -func (r *Reader) File() *os.File { - return r.f -} - -func (w *Writer) File() *os.File { - return w.f -} - -// Slice reads the next length bytes of r into a slice. -// -// This slice may be backed by mmap'ed memory. Currently, this memory -// will never be unmapped. The second result reports whether the -// backing memory is read-only. -func (r *Reader) Slice(length uint64) ([]byte, bool, error) { - if length == 0 { - return []byte{}, false, nil - } - - data, ok := r.sliceOS(length) - if ok { - return data, true, nil - } - - data = make([]byte, length) - _, err := io.ReadFull(r, data) - if err != nil { - return nil, false, err - } - return data, false, nil -} - -// SliceRO returns a slice containing the next length bytes of r -// backed by a read-only mmap'd data. If the mmap cannot be -// established (limit exceeded, region too small, etc) a nil slice -// will be returned. If mmap succeeds, it will never be unmapped. -func (r *Reader) SliceRO(length uint64) []byte { - data, ok := r.sliceOS(length) - if ok { - return data - } - return nil -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_mmap.go b/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_mmap.go deleted file mode 100644 index 4b43d74f2..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_mmap.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd - -package bio - -import ( - "runtime" - "sync/atomic" - "syscall" -) - -// mmapLimit is the maximum number of mmaped regions to create before -// falling back to reading into a heap-allocated slice. This exists -// because some operating systems place a limit on the number of -// distinct mapped regions per process. As of this writing: -// -// Darwin unlimited -// DragonFly 1000000 (vm.max_proc_mmap) -// FreeBSD unlimited -// Linux 65530 (vm.max_map_count) // TODO: query /proc/sys/vm/max_map_count? -// NetBSD unlimited -// OpenBSD unlimited -var mmapLimit int32 = 1<<31 - 1 - -func init() { - // Linux is the only practically concerning OS. - if runtime.GOOS == "linux" { - mmapLimit = 30000 - } -} - -func (r *Reader) sliceOS(length uint64) ([]byte, bool) { - // For small slices, don't bother with the overhead of a - // mapping, especially since we have no way to unmap it. - const threshold = 16 << 10 - if length < threshold { - return nil, false - } - - // Have we reached the mmap limit? - if atomic.AddInt32(&mmapLimit, -1) < 0 { - atomic.AddInt32(&mmapLimit, 1) - return nil, false - } - - // Page-align the offset. - off := r.Offset() - align := syscall.Getpagesize() - aoff := off &^ int64(align-1) - - data, err := syscall.Mmap(int(r.f.Fd()), aoff, int(length+uint64(off-aoff)), syscall.PROT_READ, syscall.MAP_SHARED|syscall.MAP_FILE) - if err != nil { - return nil, false - } - - data = data[off-aoff:] - r.MustSeek(int64(length), 1) - return data, true -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_nommap.go b/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_nommap.go deleted file mode 100644 index f43c67ac2..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/bio/buf_nommap.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd - -package bio - -func (r *Reader) sliceOS(length uint64) ([]byte, bool) { - return nil, false -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/bio/must.go b/vendor/github.com/twitchyliquid64/golang-asm/bio/must.go deleted file mode 100644 index 3604b2917..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/bio/must.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bio - -import ( - "io" - "log" -) - -// MustClose closes Closer c and calls log.Fatal if it returns a non-nil error. -func MustClose(c io.Closer) { - if err := c.Close(); err != nil { - log.Fatal(err) - } -} - -// MustWriter returns a Writer that wraps the provided Writer, -// except that it calls log.Fatal instead of returning a non-nil error. -func MustWriter(w io.Writer) io.Writer { - return mustWriter{w} -} - -type mustWriter struct { - w io.Writer -} - -func (w mustWriter) Write(b []byte) (int, error) { - n, err := w.w.Write(b) - if err != nil { - log.Fatal(err) - } - return n, nil -} - -func (w mustWriter) WriteString(s string) (int, error) { - n, err := io.WriteString(w.w, s) - if err != nil { - log.Fatal(err) - } - return n, nil -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf.go b/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf.go deleted file mode 100644 index 2fee79d38..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf.go +++ /dev/null @@ -1,1650 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package dwarf generates DWARF debugging information. -// DWARF generation is split between the compiler and the linker, -// this package contains the shared code. -package dwarf - -import ( - "bytes" - "github.com/twitchyliquid64/golang-asm/objabi" - "errors" - "fmt" - "os/exec" - "sort" - "strconv" - "strings" -) - -// InfoPrefix is the prefix for all the symbols containing DWARF info entries. -const InfoPrefix = "go.info." - -// ConstInfoPrefix is the prefix for all symbols containing DWARF info -// entries that contain constants. -const ConstInfoPrefix = "go.constinfo." - -// CUInfoPrefix is the prefix for symbols containing information to -// populate the DWARF compilation unit info entries. -const CUInfoPrefix = "go.cuinfo." - -// Used to form the symbol name assigned to the DWARF 'abstract subprogram" -// info entry for a function -const AbstractFuncSuffix = "$abstract" - -// Controls logging/debugging for selected aspects of DWARF subprogram -// generation (functions, scopes). -var logDwarf bool - -// Sym represents a symbol. -type Sym interface { - Length(dwarfContext interface{}) int64 -} - -// A Var represents a local variable or a function parameter. -type Var struct { - Name string - Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST] - IsReturnValue bool - IsInlFormal bool - StackOffset int32 - // This package can't use the ssa package, so it can't mention ssa.FuncDebug, - // so indirect through a closure. - PutLocationList func(listSym, startPC Sym) - Scope int32 - Type Sym - DeclFile string - DeclLine uint - DeclCol uint - InlIndex int32 // subtract 1 to form real index into InlTree - ChildIndex int32 // child DIE index in abstract function - IsInAbstract bool // variable exists in abstract function -} - -// A Scope represents a lexical scope. All variables declared within a -// scope will only be visible to instructions covered by the scope. -// Lexical scopes are contiguous in source files but can end up being -// compiled to discontiguous blocks of instructions in the executable. -// The Ranges field lists all the blocks of instructions that belong -// in this scope. -type Scope struct { - Parent int32 - Ranges []Range - Vars []*Var -} - -// A Range represents a half-open interval [Start, End). -type Range struct { - Start, End int64 -} - -// This container is used by the PutFunc* variants below when -// creating the DWARF subprogram DIE(s) for a function. -type FnState struct { - Name string - Importpath string - Info Sym - Filesym Sym - Loc Sym - Ranges Sym - Absfn Sym - StartPC Sym - Size int64 - External bool - Scopes []Scope - InlCalls InlCalls - UseBASEntries bool -} - -func EnableLogging(doit bool) { - logDwarf = doit -} - -// UnifyRanges merges the list of ranges of c into the list of ranges of s -func (s *Scope) UnifyRanges(c *Scope) { - out := make([]Range, 0, len(s.Ranges)+len(c.Ranges)) - - i, j := 0, 0 - for { - var cur Range - if i < len(s.Ranges) && j < len(c.Ranges) { - if s.Ranges[i].Start < c.Ranges[j].Start { - cur = s.Ranges[i] - i++ - } else { - cur = c.Ranges[j] - j++ - } - } else if i < len(s.Ranges) { - cur = s.Ranges[i] - i++ - } else if j < len(c.Ranges) { - cur = c.Ranges[j] - j++ - } else { - break - } - - if n := len(out); n > 0 && cur.Start <= out[n-1].End { - out[n-1].End = cur.End - } else { - out = append(out, cur) - } - } - - s.Ranges = out -} - -// AppendRange adds r to s, if r is non-empty. -// If possible, it extends the last Range in s.Ranges; if not, it creates a new one. -func (s *Scope) AppendRange(r Range) { - if r.End <= r.Start { - return - } - i := len(s.Ranges) - if i > 0 && s.Ranges[i-1].End == r.Start { - s.Ranges[i-1].End = r.End - return - } - s.Ranges = append(s.Ranges, r) -} - -type InlCalls struct { - Calls []InlCall -} - -type InlCall struct { - // index into ctx.InlTree describing the call inlined here - InlIndex int - - // Symbol of file containing inlined call site (really *obj.LSym). - CallFile Sym - - // Line number of inlined call site. - CallLine uint32 - - // Dwarf abstract subroutine symbol (really *obj.LSym). - AbsFunSym Sym - - // Indices of child inlines within Calls array above. - Children []int - - // entries in this list are PAUTO's created by the inliner to - // capture the promoted formals and locals of the inlined callee. - InlVars []*Var - - // PC ranges for this inlined call. - Ranges []Range - - // Root call (not a child of some other call). - Root bool -} - -// A Context specifies how to add data to a Sym. -type Context interface { - PtrSize() int - AddInt(s Sym, size int, i int64) - AddBytes(s Sym, b []byte) - AddAddress(s Sym, t interface{}, ofs int64) - AddCURelativeAddress(s Sym, t interface{}, ofs int64) - AddSectionOffset(s Sym, size int, t interface{}, ofs int64) - AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64) - CurrentOffset(s Sym) int64 - RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int) - RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32) - AddString(s Sym, v string) - AddFileRef(s Sym, f interface{}) - Logf(format string, args ...interface{}) -} - -// AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding. -func AppendUleb128(b []byte, v uint64) []byte { - for { - c := uint8(v & 0x7f) - v >>= 7 - if v != 0 { - c |= 0x80 - } - b = append(b, c) - if c&0x80 == 0 { - break - } - } - return b -} - -// AppendSleb128 appends v to b using DWARF's signed LEB128 encoding. -func AppendSleb128(b []byte, v int64) []byte { - for { - c := uint8(v & 0x7f) - s := uint8(v & 0x40) - v >>= 7 - if (v != -1 || s == 0) && (v != 0 || s != 0) { - c |= 0x80 - } - b = append(b, c) - if c&0x80 == 0 { - break - } - } - return b -} - -// sevenbits contains all unsigned seven bit numbers, indexed by their value. -var sevenbits = [...]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, -} - -// sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise. -// The contents of the returned slice must not be modified. -func sevenBitU(v int64) []byte { - if uint64(v) < uint64(len(sevenbits)) { - return sevenbits[v : v+1] - } - return nil -} - -// sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise. -// The contents of the returned slice must not be modified. -func sevenBitS(v int64) []byte { - if uint64(v) <= 63 { - return sevenbits[v : v+1] - } - if uint64(-v) <= 64 { - return sevenbits[128+v : 128+v+1] - } - return nil -} - -// Uleb128put appends v to s using DWARF's unsigned LEB128 encoding. -func Uleb128put(ctxt Context, s Sym, v int64) { - b := sevenBitU(v) - if b == nil { - var encbuf [20]byte - b = AppendUleb128(encbuf[:0], uint64(v)) - } - ctxt.AddBytes(s, b) -} - -// Sleb128put appends v to s using DWARF's signed LEB128 encoding. -func Sleb128put(ctxt Context, s Sym, v int64) { - b := sevenBitS(v) - if b == nil { - var encbuf [20]byte - b = AppendSleb128(encbuf[:0], v) - } - ctxt.AddBytes(s, b) -} - -/* - * Defining Abbrevs. This is hardcoded on a per-platform basis (that is, - * each platform will see a fixed abbrev table for all objects); the number - * of abbrev entries is fairly small (compared to C++ objects). The DWARF - * spec places no restriction on the ordering of attributes in the - * Abbrevs and DIEs, and we will always write them out in the order - * of declaration in the abbrev. - */ -type dwAttrForm struct { - attr uint16 - form uint8 -} - -// Go-specific type attributes. -const ( - DW_AT_go_kind = 0x2900 - DW_AT_go_key = 0x2901 - DW_AT_go_elem = 0x2902 - // Attribute for DW_TAG_member of a struct type. - // Nonzero value indicates the struct field is an embedded field. - DW_AT_go_embedded_field = 0x2903 - DW_AT_go_runtime_type = 0x2904 - - DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit - - DW_AT_internal_location = 253 // params and locals; not emitted -) - -// Index into the abbrevs table below. -// Keep in sync with ispubname() and ispubtype() in ld/dwarf.go. -// ispubtype considers >= NULLTYPE public -const ( - DW_ABRV_NULL = iota - DW_ABRV_COMPUNIT - DW_ABRV_COMPUNIT_TEXTLESS - DW_ABRV_FUNCTION - DW_ABRV_FUNCTION_ABSTRACT - DW_ABRV_FUNCTION_CONCRETE - DW_ABRV_INLINED_SUBROUTINE - DW_ABRV_INLINED_SUBROUTINE_RANGES - DW_ABRV_VARIABLE - DW_ABRV_INT_CONSTANT - DW_ABRV_AUTO - DW_ABRV_AUTO_LOCLIST - DW_ABRV_AUTO_ABSTRACT - DW_ABRV_AUTO_CONCRETE - DW_ABRV_AUTO_CONCRETE_LOCLIST - DW_ABRV_PARAM - DW_ABRV_PARAM_LOCLIST - DW_ABRV_PARAM_ABSTRACT - DW_ABRV_PARAM_CONCRETE - DW_ABRV_PARAM_CONCRETE_LOCLIST - DW_ABRV_LEXICAL_BLOCK_RANGES - DW_ABRV_LEXICAL_BLOCK_SIMPLE - DW_ABRV_STRUCTFIELD - DW_ABRV_FUNCTYPEPARAM - DW_ABRV_DOTDOTDOT - DW_ABRV_ARRAYRANGE - DW_ABRV_NULLTYPE - DW_ABRV_BASETYPE - DW_ABRV_ARRAYTYPE - DW_ABRV_CHANTYPE - DW_ABRV_FUNCTYPE - DW_ABRV_IFACETYPE - DW_ABRV_MAPTYPE - DW_ABRV_PTRTYPE - DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. - DW_ABRV_SLICETYPE - DW_ABRV_STRINGTYPE - DW_ABRV_STRUCTTYPE - DW_ABRV_TYPEDECL - DW_NABRV -) - -type dwAbbrev struct { - tag uint8 - children uint8 - attr []dwAttrForm -} - -var abbrevsFinalized bool - -// expandPseudoForm takes an input DW_FORM_xxx value and translates it -// into a platform-appropriate concrete form. Existing concrete/real -// DW_FORM values are left untouched. For the moment the only -// pseudo-form is DW_FORM_udata_pseudo, which gets expanded to -// DW_FORM_data4 on Darwin and DW_FORM_udata everywhere else. See -// issue #31459 for more context. -func expandPseudoForm(form uint8) uint8 { - // Is this a pseudo-form? - if form != DW_FORM_udata_pseudo { - return form - } - expandedForm := DW_FORM_udata - if objabi.GOOS == "darwin" { - expandedForm = DW_FORM_data4 - } - return uint8(expandedForm) -} - -// Abbrevs() returns the finalized abbrev array for the platform, -// expanding any DW_FORM pseudo-ops to real values. -func Abbrevs() []dwAbbrev { - if abbrevsFinalized { - return abbrevs[:] - } - for i := 1; i < DW_NABRV; i++ { - for j := 0; j < len(abbrevs[i].attr); j++ { - abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form) - } - } - abbrevsFinalized = true - return abbrevs[:] -} - -// abbrevs is a raw table of abbrev entries; it needs to be post-processed -// by the Abbrevs() function above prior to being consumed, to expand -// the 'pseudo-form' entries below to real DWARF form values. - -var abbrevs = [DW_NABRV]dwAbbrev{ - /* The mandatory DW_ABRV_NULL entry. */ - {0, 0, []dwAttrForm{}}, - - /* COMPUNIT */ - { - DW_TAG_compile_unit, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_language, DW_FORM_data1}, - {DW_AT_stmt_list, DW_FORM_sec_offset}, - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_ranges, DW_FORM_sec_offset}, - {DW_AT_comp_dir, DW_FORM_string}, - {DW_AT_producer, DW_FORM_string}, - {DW_AT_go_package_name, DW_FORM_string}, - }, - }, - - /* COMPUNIT_TEXTLESS */ - { - DW_TAG_compile_unit, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_language, DW_FORM_data1}, - {DW_AT_comp_dir, DW_FORM_string}, - {DW_AT_producer, DW_FORM_string}, - {DW_AT_go_package_name, DW_FORM_string}, - }, - }, - - /* FUNCTION */ - { - DW_TAG_subprogram, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_high_pc, DW_FORM_addr}, - {DW_AT_frame_base, DW_FORM_block1}, - {DW_AT_decl_file, DW_FORM_data4}, - {DW_AT_external, DW_FORM_flag}, - }, - }, - - /* FUNCTION_ABSTRACT */ - { - DW_TAG_subprogram, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_inline, DW_FORM_data1}, - {DW_AT_external, DW_FORM_flag}, - }, - }, - - /* FUNCTION_CONCRETE */ - { - DW_TAG_subprogram, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_high_pc, DW_FORM_addr}, - {DW_AT_frame_base, DW_FORM_block1}, - }, - }, - - /* INLINED_SUBROUTINE */ - { - DW_TAG_inlined_subroutine, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_high_pc, DW_FORM_addr}, - {DW_AT_call_file, DW_FORM_data4}, - {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form - }, - }, - - /* INLINED_SUBROUTINE_RANGES */ - { - DW_TAG_inlined_subroutine, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_ranges, DW_FORM_sec_offset}, - {DW_AT_call_file, DW_FORM_data4}, - {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form - }, - }, - - /* VARIABLE */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_location, DW_FORM_block1}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_external, DW_FORM_flag}, - }, - }, - - /* INT CONSTANT */ - { - DW_TAG_constant, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_const_value, DW_FORM_sdata}, - }, - }, - - /* AUTO */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_decl_line, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_block1}, - }, - }, - - /* AUTO_LOCLIST */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_decl_line, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_sec_offset}, - }, - }, - - /* AUTO_ABSTRACT */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_decl_line, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - }, - }, - - /* AUTO_CONCRETE */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_block1}, - }, - }, - - /* AUTO_CONCRETE_LOCLIST */ - { - DW_TAG_variable, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_sec_offset}, - }, - }, - - /* PARAM */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_variable_parameter, DW_FORM_flag}, - {DW_AT_decl_line, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_block1}, - }, - }, - - /* PARAM_LOCLIST */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_variable_parameter, DW_FORM_flag}, - {DW_AT_decl_line, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_sec_offset}, - }, - }, - - /* PARAM_ABSTRACT */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_variable_parameter, DW_FORM_flag}, - {DW_AT_type, DW_FORM_ref_addr}, - }, - }, - - /* PARAM_CONCRETE */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_block1}, - }, - }, - - /* PARAM_CONCRETE_LOCLIST */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_abstract_origin, DW_FORM_ref_addr}, - {DW_AT_location, DW_FORM_sec_offset}, - }, - }, - - /* LEXICAL_BLOCK_RANGES */ - { - DW_TAG_lexical_block, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_ranges, DW_FORM_sec_offset}, - }, - }, - - /* LEXICAL_BLOCK_SIMPLE */ - { - DW_TAG_lexical_block, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_high_pc, DW_FORM_addr}, - }, - }, - - /* STRUCTFIELD */ - { - DW_TAG_member, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_data_member_location, DW_FORM_udata}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_go_embedded_field, DW_FORM_flag}, - }, - }, - - /* FUNCTYPEPARAM */ - { - DW_TAG_formal_parameter, - DW_CHILDREN_no, - - // No name! - []dwAttrForm{ - {DW_AT_type, DW_FORM_ref_addr}, - }, - }, - - /* DOTDOTDOT */ - { - DW_TAG_unspecified_parameters, - DW_CHILDREN_no, - []dwAttrForm{}, - }, - - /* ARRAYRANGE */ - { - DW_TAG_subrange_type, - DW_CHILDREN_no, - - // No name! - []dwAttrForm{ - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_count, DW_FORM_udata}, - }, - }, - - // Below here are the types considered public by ispubtype - /* NULLTYPE */ - { - DW_TAG_unspecified_type, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - }, - }, - - /* BASETYPE */ - { - DW_TAG_base_type, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_encoding, DW_FORM_data1}, - {DW_AT_byte_size, DW_FORM_data1}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* ARRAYTYPE */ - // child is subrange with upper bound - { - DW_TAG_array_type, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_byte_size, DW_FORM_udata}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* CHANTYPE */ - { - DW_TAG_typedef, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - {DW_AT_go_elem, DW_FORM_ref_addr}, - }, - }, - - /* FUNCTYPE */ - { - DW_TAG_subroutine_type, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_byte_size, DW_FORM_udata}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* IFACETYPE */ - { - DW_TAG_typedef, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* MAPTYPE */ - { - DW_TAG_typedef, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - {DW_AT_go_key, DW_FORM_ref_addr}, - {DW_AT_go_elem, DW_FORM_ref_addr}, - }, - }, - - /* PTRTYPE */ - { - DW_TAG_pointer_type, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* BARE_PTRTYPE */ - { - DW_TAG_pointer_type, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - }, - }, - - /* SLICETYPE */ - { - DW_TAG_structure_type, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_byte_size, DW_FORM_udata}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - {DW_AT_go_elem, DW_FORM_ref_addr}, - }, - }, - - /* STRINGTYPE */ - { - DW_TAG_structure_type, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_byte_size, DW_FORM_udata}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* STRUCTTYPE */ - { - DW_TAG_structure_type, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_byte_size, DW_FORM_udata}, - {DW_AT_go_kind, DW_FORM_data1}, - {DW_AT_go_runtime_type, DW_FORM_addr}, - }, - }, - - /* TYPEDECL */ - { - DW_TAG_typedef, - DW_CHILDREN_no, - []dwAttrForm{ - {DW_AT_name, DW_FORM_string}, - {DW_AT_type, DW_FORM_ref_addr}, - }, - }, -} - -// GetAbbrev returns the contents of the .debug_abbrev section. -func GetAbbrev() []byte { - abbrevs := Abbrevs() - var buf []byte - for i := 1; i < DW_NABRV; i++ { - // See section 7.5.3 - buf = AppendUleb128(buf, uint64(i)) - buf = AppendUleb128(buf, uint64(abbrevs[i].tag)) - buf = append(buf, abbrevs[i].children) - for _, f := range abbrevs[i].attr { - buf = AppendUleb128(buf, uint64(f.attr)) - buf = AppendUleb128(buf, uint64(f.form)) - } - buf = append(buf, 0, 0) - } - return append(buf, 0) -} - -/* - * Debugging Information Entries and their attributes. - */ - -// DWAttr represents an attribute of a DWDie. -// -// For DW_CLS_string and _block, value should contain the length, and -// data the data, for _reference, value is 0 and data is a DWDie* to -// the referenced instance, for all others, value is the whole thing -// and data is null. -type DWAttr struct { - Link *DWAttr - Atr uint16 // DW_AT_ - Cls uint8 // DW_CLS_ - Value int64 - Data interface{} -} - -// DWDie represents a DWARF debug info entry. -type DWDie struct { - Abbrev int - Link *DWDie - Child *DWDie - Attr *DWAttr - Sym Sym -} - -func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { - switch form { - case DW_FORM_addr: // address - // Allow nil addresses for DW_AT_go_runtime_type. - if data == nil && value == 0 { - ctxt.AddInt(s, ctxt.PtrSize(), 0) - break - } - if cls == DW_CLS_GO_TYPEREF { - ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value) - break - } - ctxt.AddAddress(s, data, value) - - case DW_FORM_block1: // block - if cls == DW_CLS_ADDRESS { - ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) - ctxt.AddInt(s, 1, DW_OP_addr) - ctxt.AddAddress(s, data, 0) - break - } - - value &= 0xff - ctxt.AddInt(s, 1, value) - p := data.([]byte)[:value] - ctxt.AddBytes(s, p) - - case DW_FORM_block2: // block - value &= 0xffff - - ctxt.AddInt(s, 2, value) - p := data.([]byte)[:value] - ctxt.AddBytes(s, p) - - case DW_FORM_block4: // block - value &= 0xffffffff - - ctxt.AddInt(s, 4, value) - p := data.([]byte)[:value] - ctxt.AddBytes(s, p) - - case DW_FORM_block: // block - Uleb128put(ctxt, s, value) - - p := data.([]byte)[:value] - ctxt.AddBytes(s, p) - - case DW_FORM_data1: // constant - ctxt.AddInt(s, 1, value) - - case DW_FORM_data2: // constant - ctxt.AddInt(s, 2, value) - - case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr - if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges - ctxt.AddDWARFAddrSectionOffset(s, data, value) - break - } - ctxt.AddInt(s, 4, value) - - case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr - ctxt.AddInt(s, 8, value) - - case DW_FORM_sdata: // constant - Sleb128put(ctxt, s, value) - - case DW_FORM_udata: // constant - Uleb128put(ctxt, s, value) - - case DW_FORM_string: // string - str := data.(string) - ctxt.AddString(s, str) - // TODO(ribrdb): verify padded strings are never used and remove this - for i := int64(len(str)); i < value; i++ { - ctxt.AddInt(s, 1, 0) - } - - case DW_FORM_flag: // flag - if value != 0 { - ctxt.AddInt(s, 1, 1) - } else { - ctxt.AddInt(s, 1, 0) - } - - // As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large - // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. - case DW_FORM_ref_addr: // reference to a DIE in the .info section - fallthrough - case DW_FORM_sec_offset: // offset into a DWARF section other than .info - if data == nil { - return fmt.Errorf("dwarf: null reference in %d", abbrev) - } - ctxt.AddDWARFAddrSectionOffset(s, data, value) - - case DW_FORM_ref1, // reference within the compilation unit - DW_FORM_ref2, // reference - DW_FORM_ref4, // reference - DW_FORM_ref8, // reference - DW_FORM_ref_udata, // reference - - DW_FORM_strp, // string - DW_FORM_indirect: // (see Section 7.5.3) - fallthrough - default: - return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) - } - return nil -} - -// PutAttrs writes the attributes for a DIE to symbol 's'. -// -// Note that we can (and do) add arbitrary attributes to a DIE, but -// only the ones actually listed in the Abbrev will be written out. -func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { - abbrevs := Abbrevs() -Outer: - for _, f := range abbrevs[abbrev].attr { - for ap := attr; ap != nil; ap = ap.Link { - if ap.Atr == f.attr { - putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) - continue Outer - } - } - - putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) - } -} - -// HasChildren reports whether 'die' uses an abbrev that supports children. -func HasChildren(die *DWDie) bool { - abbrevs := Abbrevs() - return abbrevs[die.Abbrev].children != 0 -} - -// PutIntConst writes a DIE for an integer constant -func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) { - Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT) - putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) - putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ) - putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil) -} - -// PutBasedRanges writes a range table to sym. All addresses in ranges are -// relative to some base address, which must be arranged by the caller -// (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range). -func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) { - ps := ctxt.PtrSize() - // Write ranges. - for _, r := range ranges { - ctxt.AddInt(sym, ps, r.Start) - ctxt.AddInt(sym, ps, r.End) - } - // Write trailer. - ctxt.AddInt(sym, ps, 0) - ctxt.AddInt(sym, ps, 0) -} - -// PutRanges writes a range table to s.Ranges. -// All addresses in ranges are relative to s.base. -func (s *FnState) PutRanges(ctxt Context, ranges []Range) { - ps := ctxt.PtrSize() - sym, base := s.Ranges, s.StartPC - - if s.UseBASEntries { - // Using a Base Address Selection Entry reduces the number of relocations, but - // this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb - ctxt.AddInt(sym, ps, -1) - ctxt.AddAddress(sym, base, 0) - PutBasedRanges(ctxt, sym, ranges) - return - } - - // Write ranges full of relocations - for _, r := range ranges { - ctxt.AddCURelativeAddress(sym, base, r.Start) - ctxt.AddCURelativeAddress(sym, base, r.End) - } - // Write trailer. - ctxt.AddInt(sym, ps, 0) - ctxt.AddInt(sym, ps, 0) -} - -// Return TRUE if the inlined call in the specified slot is empty, -// meaning it has a zero-length range (no instructions), and all -// of its children are empty. -func isEmptyInlinedCall(slot int, calls *InlCalls) bool { - ic := &calls.Calls[slot] - if ic.InlIndex == -2 { - return true - } - live := false - for _, k := range ic.Children { - if !isEmptyInlinedCall(k, calls) { - live = true - } - } - if len(ic.Ranges) > 0 { - live = true - } - if !live { - ic.InlIndex = -2 - } - return !live -} - -// Slot -1: return top-level inlines -// Slot >= 0: return children of that slot -func inlChildren(slot int, calls *InlCalls) []int { - var kids []int - if slot != -1 { - for _, k := range calls.Calls[slot].Children { - if !isEmptyInlinedCall(k, calls) { - kids = append(kids, k) - } - } - } else { - for k := 0; k < len(calls.Calls); k += 1 { - if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) { - kids = append(kids, k) - } - } - } - return kids -} - -func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool { - vars := make(map[*Var]bool) - for _, ic := range inlcalls.Calls { - for _, v := range ic.InlVars { - vars[v] = true - } - } - return vars -} - -// The s.Scopes slice contains variables were originally part of the -// function being emitted, as well as variables that were imported -// from various callee functions during the inlining process. This -// function prunes out any variables from the latter category (since -// they will be emitted as part of DWARF inlined_subroutine DIEs) and -// then generates scopes for vars in the former category. -func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error { - if len(s.Scopes) == 0 { - return nil - } - scopes := make([]Scope, len(s.Scopes), len(s.Scopes)) - pvars := inlinedVarTable(&s.InlCalls) - for k, s := range s.Scopes { - var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges} - for i := 0; i < len(s.Vars); i++ { - _, found := pvars[s.Vars[i]] - if !found { - pruned.Vars = append(pruned.Vars, s.Vars[i]) - } - } - sort.Sort(byChildIndex(pruned.Vars)) - scopes[k] = pruned - } - var encbuf [20]byte - if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) { - return errors.New("multiple toplevel scopes") - } - return nil -} - -// Emit DWARF attributes and child DIEs for an 'abstract' subprogram. -// The abstract subprogram DIE for a function contains its -// location-independent attributes (name, type, etc). Other instances -// of the function (any inlined copy of it, or the single out-of-line -// 'concrete' instance) will contain a pointer back to this abstract -// DIE (as a space-saving measure, so that name/type etc doesn't have -// to be repeated for each inlined copy). -func PutAbstractFunc(ctxt Context, s *FnState) error { - - if logDwarf { - ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn) - } - - abbrev := DW_ABRV_FUNCTION_ABSTRACT - Uleb128put(ctxt, s.Absfn, int64(abbrev)) - - fullname := s.Name - if strings.HasPrefix(s.Name, "\"\".") { - // Generate a fully qualified name for the function in the - // abstract case. This is so as to avoid the need for the - // linker to process the DIE with patchDWARFName(); we can't - // allow the name attribute of an abstract subprogram DIE to - // be rewritten, since it would change the offsets of the - // child DIEs (which we're relying on in order for abstract - // origin references to work). - fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:] - } - putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname) - - // DW_AT_inlined value - putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil) - - var ev int64 - if s.External { - ev = 1 - } - putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) - - // Child variables (may be empty) - var flattened []*Var - - // This slice will hold the offset in bytes for each child var DIE - // with respect to the start of the parent subprogram DIE. - var offsets []int32 - - // Scopes/vars - if len(s.Scopes) > 0 { - // For abstract subprogram DIEs we want to flatten out scope info: - // lexical scope DIEs contain range and/or hi/lo PC attributes, - // which we explicitly don't want for the abstract subprogram DIE. - pvars := inlinedVarTable(&s.InlCalls) - for _, scope := range s.Scopes { - for i := 0; i < len(scope.Vars); i++ { - _, found := pvars[scope.Vars[i]] - if found || !scope.Vars[i].IsInAbstract { - continue - } - flattened = append(flattened, scope.Vars[i]) - } - } - if len(flattened) > 0 { - sort.Sort(byChildIndex(flattened)) - - if logDwarf { - ctxt.Logf("putAbstractScope(%v): vars:", s.Info) - for i, v := range flattened { - ctxt.Logf(" %d:%s", i, v.Name) - } - ctxt.Logf("\n") - } - - // This slice will hold the offset in bytes for each child - // variable DIE with respect to the start of the parent - // subprogram DIE. - for _, v := range flattened { - offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn))) - putAbstractVar(ctxt, s.Absfn, v) - } - } - } - ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets) - - Uleb128put(ctxt, s.Absfn, 0) - return nil -} - -// Emit DWARF attributes and child DIEs for an inlined subroutine. The -// first attribute of an inlined subroutine DIE is a reference back to -// its corresponding 'abstract' DIE (containing location-independent -// attributes such as name, type, etc). Inlined subroutine DIEs can -// have other inlined subroutine DIEs as children. -func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error { - ic := s.InlCalls.Calls[callIdx] - callee := ic.AbsFunSym - - abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES - if len(ic.Ranges) == 1 { - abbrev = DW_ABRV_INLINED_SUBROUTINE - } - Uleb128put(ctxt, s.Info, int64(abbrev)) - - if logDwarf { - ctxt.Logf("PutInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev) - } - - // Abstract origin. - putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee) - - if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES { - putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges) - s.PutRanges(ctxt, ic.Ranges) - } else { - st := ic.Ranges[0].Start - en := ic.Ranges[0].End - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC) - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC) - } - - // Emit call file, line attrs. - ctxt.AddFileRef(s.Info, ic.CallFile) - form := int(expandPseudoForm(DW_FORM_udata_pseudo)) - putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil) - - // Variables associated with this inlined routine instance. - vars := ic.InlVars - sort.Sort(byChildIndex(vars)) - inlIndex := ic.InlIndex - var encbuf [20]byte - for _, v := range vars { - if !v.IsInAbstract { - continue - } - putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0]) - } - - // Children of this inline. - for _, sib := range inlChildren(callIdx, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := PutInlinedFunc(ctxt, s, absfn, sib) - if err != nil { - return err - } - } - - Uleb128put(ctxt, s.Info, 0) - return nil -} - -// Emit DWARF attributes and child DIEs for a 'concrete' subprogram, -// meaning the out-of-line copy of a function that was inlined at some -// point during the compilation of its containing package. The first -// attribute for a concrete DIE is a reference to the 'abstract' DIE -// for the function (which holds location-independent attributes such -// as name, type), then the remainder of the attributes are specific -// to this instance (location, frame base, etc). -func PutConcreteFunc(ctxt Context, s *FnState) error { - if logDwarf { - ctxt.Logf("PutConcreteFunc(%v)\n", s.Info) - } - abbrev := DW_ABRV_FUNCTION_CONCRETE - Uleb128put(ctxt, s.Info, int64(abbrev)) - - // Abstract origin. - putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn) - - // Start/end PC. - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) - - // cfa / frame base - putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) - - // Scopes - if err := putPrunedScopes(ctxt, s, abbrev); err != nil { - return err - } - - // Inlined subroutines. - for _, sib := range inlChildren(-1, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := PutInlinedFunc(ctxt, s, absfn, sib) - if err != nil { - return err - } - } - - Uleb128put(ctxt, s.Info, 0) - return nil -} - -// Emit DWARF attributes and child DIEs for a subprogram. Here -// 'default' implies that the function in question was not inlined -// when its containing package was compiled (hence there is no need to -// emit an abstract version for it to use as a base for inlined -// routine records). -func PutDefaultFunc(ctxt Context, s *FnState) error { - if logDwarf { - ctxt.Logf("PutDefaultFunc(%v)\n", s.Info) - } - abbrev := DW_ABRV_FUNCTION - Uleb128put(ctxt, s.Info, int64(abbrev)) - - // Expand '"".' to import path. - name := s.Name - if s.Importpath != "" { - name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1) - } - - putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) - putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) - putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) - ctxt.AddFileRef(s.Info, s.Filesym) - - var ev int64 - if s.External { - ev = 1 - } - putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) - - // Scopes - if err := putPrunedScopes(ctxt, s, abbrev); err != nil { - return err - } - - // Inlined subroutines. - for _, sib := range inlChildren(-1, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := PutInlinedFunc(ctxt, s, absfn, sib) - if err != nil { - return err - } - } - - Uleb128put(ctxt, s.Info, 0) - return nil -} - -func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 { - - if logDwarf { - ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope) - for i, v := range scopes[curscope].Vars { - ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name) - } - ctxt.Logf("\n") - } - - for _, v := range scopes[curscope].Vars { - putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf) - } - this := curscope - curscope++ - for curscope < int32(len(scopes)) { - scope := scopes[curscope] - if scope.Parent != this { - return curscope - } - - if len(scopes[curscope].Vars) == 0 { - curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) - continue - } - - if len(scope.Ranges) == 1 { - Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) - putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC) - putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC) - } else { - Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES) - putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges) - - s.PutRanges(ctxt, scope.Ranges) - } - - curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) - - Uleb128put(ctxt, s.Info, 0) - } - return curscope -} - -// Given a default var abbrev code, select corresponding concrete code. -func concreteVarAbbrev(varAbbrev int) int { - switch varAbbrev { - case DW_ABRV_AUTO: - return DW_ABRV_AUTO_CONCRETE - case DW_ABRV_PARAM: - return DW_ABRV_PARAM_CONCRETE - case DW_ABRV_AUTO_LOCLIST: - return DW_ABRV_AUTO_CONCRETE_LOCLIST - case DW_ABRV_PARAM_LOCLIST: - return DW_ABRV_PARAM_CONCRETE_LOCLIST - default: - panic("should never happen") - } -} - -// Pick the correct abbrev code for variable or parameter DIE. -func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) { - abbrev := v.Abbrev - - // If the variable was entirely optimized out, don't emit a location list; - // convert to an inline abbreviation and emit an empty location. - missing := false - switch { - case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil: - missing = true - abbrev = DW_ABRV_AUTO - case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil: - missing = true - abbrev = DW_ABRV_PARAM - } - - // Determine whether to use a concrete variable or regular variable DIE. - concrete := true - switch fnabbrev { - case DW_ABRV_FUNCTION: - concrete = false - break - case DW_ABRV_FUNCTION_CONCRETE: - // If we're emitting a concrete subprogram DIE and the variable - // in question is not part of the corresponding abstract function DIE, - // then use the default (non-concrete) abbrev for this param. - if !v.IsInAbstract { - concrete = false - } - case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES: - default: - panic("should never happen") - } - - // Select proper abbrev based on concrete/non-concrete - if concrete { - abbrev = concreteVarAbbrev(abbrev) - } - - return abbrev, missing, concrete -} - -func abbrevUsesLoclist(abbrev int) bool { - switch abbrev { - case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST, - DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST: - return true - default: - return false - } -} - -// Emit DWARF attributes for a variable belonging to an 'abstract' subprogram. -func putAbstractVar(ctxt Context, info Sym, v *Var) { - // Remap abbrev - abbrev := v.Abbrev - switch abbrev { - case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST: - abbrev = DW_ABRV_AUTO_ABSTRACT - case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST: - abbrev = DW_ABRV_PARAM_ABSTRACT - } - - Uleb128put(ctxt, info, int64(abbrev)) - putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) - - // Isreturn attribute if this is a param - if abbrev == DW_ABRV_PARAM_ABSTRACT { - var isReturn int64 - if v.IsReturnValue { - isReturn = 1 - } - putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) - } - - // Line - if abbrev != DW_ABRV_PARAM_ABSTRACT { - // See issue 23374 for more on why decl line is skipped for abs params. - putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) - } - - // Type - putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) - - // Var has no children => no terminator -} - -func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) { - // Remap abbrev according to parent DIE abbrev - abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev) - - Uleb128put(ctxt, s.Info, int64(abbrev)) - - // Abstract origin for concrete / inlined case - if concrete { - // Here we are making a reference to a child DIE of an abstract - // function subprogram DIE. The child DIE has no LSym, so instead - // after the call to 'putattr' below we make a call to register - // the child DIE reference. - putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) - ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex) - } else { - // Var name, line for abstract and default cases - n := v.Name - putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) - if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT { - var isReturn int64 - if v.IsReturnValue { - isReturn = 1 - } - putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) - } - putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) - putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) - } - - if abbrevUsesLoclist(abbrev) { - putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc) - v.PutLocationList(s.Loc, s.StartPC) - } else { - loc := encbuf[:0] - switch { - case missing: - break // no location - case v.StackOffset == 0: - loc = append(loc, DW_OP_call_frame_cfa) - default: - loc = append(loc, DW_OP_fbreg) - loc = AppendSleb128(loc, int64(v.StackOffset)) - } - putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) - } - - // Var has no children => no terminator -} - -// VarsByOffset attaches the methods of sort.Interface to []*Var, -// sorting in increasing StackOffset. -type VarsByOffset []*Var - -func (s VarsByOffset) Len() int { return len(s) } -func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset } -func (s VarsByOffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// byChildIndex implements sort.Interface for []*dwarf.Var by child index. -type byChildIndex []*Var - -func (s byChildIndex) Len() int { return len(s) } -func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex } -func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// IsDWARFEnabledOnAIX returns true if DWARF is possible on the -// current extld. -// AIX ld doesn't support DWARF with -bnoobjreorder with version -// prior to 7.2.2. -func IsDWARFEnabledOnAIXLd(extld string) (bool, error) { - out, err := exec.Command(extld, "-Wl,-V").CombinedOutput() - if err != nil { - // The normal output should display ld version and - // then fails because ".main" is not defined: - // ld: 0711-317 ERROR: Undefined symbol: .main - if !bytes.Contains(out, []byte("0711-317")) { - return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out) - } - } - // gcc -Wl,-V output should be: - // /usr/bin/ld: LD X.X.X(date) - // ... - out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD ")) - vers := string(bytes.Split(out, []byte("("))[0]) - subvers := strings.Split(vers, ".") - if len(subvers) != 3 { - return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err) - } - if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 { - return false, nil - } else if v > 7 { - return true, nil - } - if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 { - return false, nil - } else if v > 2 { - return true, nil - } - if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 { - return false, nil - } - return true, nil -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf_defs.go b/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf_defs.go deleted file mode 100644 index e2716e506..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/dwarf/dwarf_defs.go +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dwarf - -// Cut, pasted, tr-and-awk'ed from tables in -// http://dwarfstd.org/doc/Dwarf3.pdf - -// Table 18 -const ( - DW_TAG_array_type = 0x01 - DW_TAG_class_type = 0x02 - DW_TAG_entry_point = 0x03 - DW_TAG_enumeration_type = 0x04 - DW_TAG_formal_parameter = 0x05 - DW_TAG_imported_declaration = 0x08 - DW_TAG_label = 0x0a - DW_TAG_lexical_block = 0x0b - DW_TAG_member = 0x0d - DW_TAG_pointer_type = 0x0f - DW_TAG_reference_type = 0x10 - DW_TAG_compile_unit = 0x11 - DW_TAG_string_type = 0x12 - DW_TAG_structure_type = 0x13 - DW_TAG_subroutine_type = 0x15 - DW_TAG_typedef = 0x16 - DW_TAG_union_type = 0x17 - DW_TAG_unspecified_parameters = 0x18 - DW_TAG_variant = 0x19 - DW_TAG_common_block = 0x1a - DW_TAG_common_inclusion = 0x1b - DW_TAG_inheritance = 0x1c - DW_TAG_inlined_subroutine = 0x1d - DW_TAG_module = 0x1e - DW_TAG_ptr_to_member_type = 0x1f - DW_TAG_set_type = 0x20 - DW_TAG_subrange_type = 0x21 - DW_TAG_with_stmt = 0x22 - DW_TAG_access_declaration = 0x23 - DW_TAG_base_type = 0x24 - DW_TAG_catch_block = 0x25 - DW_TAG_const_type = 0x26 - DW_TAG_constant = 0x27 - DW_TAG_enumerator = 0x28 - DW_TAG_file_type = 0x29 - DW_TAG_friend = 0x2a - DW_TAG_namelist = 0x2b - DW_TAG_namelist_item = 0x2c - DW_TAG_packed_type = 0x2d - DW_TAG_subprogram = 0x2e - DW_TAG_template_type_parameter = 0x2f - DW_TAG_template_value_parameter = 0x30 - DW_TAG_thrown_type = 0x31 - DW_TAG_try_block = 0x32 - DW_TAG_variant_part = 0x33 - DW_TAG_variable = 0x34 - DW_TAG_volatile_type = 0x35 - // Dwarf3 - DW_TAG_dwarf_procedure = 0x36 - DW_TAG_restrict_type = 0x37 - DW_TAG_interface_type = 0x38 - DW_TAG_namespace = 0x39 - DW_TAG_imported_module = 0x3a - DW_TAG_unspecified_type = 0x3b - DW_TAG_partial_unit = 0x3c - DW_TAG_imported_unit = 0x3d - DW_TAG_condition = 0x3f - DW_TAG_shared_type = 0x40 - // Dwarf4 - DW_TAG_type_unit = 0x41 - DW_TAG_rvalue_reference_type = 0x42 - DW_TAG_template_alias = 0x43 - - // User defined - DW_TAG_lo_user = 0x4080 - DW_TAG_hi_user = 0xffff -) - -// Table 19 -const ( - DW_CHILDREN_no = 0x00 - DW_CHILDREN_yes = 0x01 -) - -// Not from the spec, but logically belongs here -const ( - DW_CLS_ADDRESS = 0x01 + iota - DW_CLS_BLOCK - DW_CLS_CONSTANT - DW_CLS_FLAG - DW_CLS_PTR // lineptr, loclistptr, macptr, rangelistptr - DW_CLS_REFERENCE - DW_CLS_ADDRLOC - DW_CLS_STRING - - // Go-specific internal hackery. - DW_CLS_GO_TYPEREF -) - -// Table 20 -const ( - DW_AT_sibling = 0x01 // reference - DW_AT_location = 0x02 // block, loclistptr - DW_AT_name = 0x03 // string - DW_AT_ordering = 0x09 // constant - DW_AT_byte_size = 0x0b // block, constant, reference - DW_AT_bit_offset = 0x0c // block, constant, reference - DW_AT_bit_size = 0x0d // block, constant, reference - DW_AT_stmt_list = 0x10 // lineptr - DW_AT_low_pc = 0x11 // address - DW_AT_high_pc = 0x12 // address - DW_AT_language = 0x13 // constant - DW_AT_discr = 0x15 // reference - DW_AT_discr_value = 0x16 // constant - DW_AT_visibility = 0x17 // constant - DW_AT_import = 0x18 // reference - DW_AT_string_length = 0x19 // block, loclistptr - DW_AT_common_reference = 0x1a // reference - DW_AT_comp_dir = 0x1b // string - DW_AT_const_value = 0x1c // block, constant, string - DW_AT_containing_type = 0x1d // reference - DW_AT_default_value = 0x1e // reference - DW_AT_inline = 0x20 // constant - DW_AT_is_optional = 0x21 // flag - DW_AT_lower_bound = 0x22 // block, constant, reference - DW_AT_producer = 0x25 // string - DW_AT_prototyped = 0x27 // flag - DW_AT_return_addr = 0x2a // block, loclistptr - DW_AT_start_scope = 0x2c // constant - DW_AT_bit_stride = 0x2e // constant - DW_AT_upper_bound = 0x2f // block, constant, reference - DW_AT_abstract_origin = 0x31 // reference - DW_AT_accessibility = 0x32 // constant - DW_AT_address_class = 0x33 // constant - DW_AT_artificial = 0x34 // flag - DW_AT_base_types = 0x35 // reference - DW_AT_calling_convention = 0x36 // constant - DW_AT_count = 0x37 // block, constant, reference - DW_AT_data_member_location = 0x38 // block, constant, loclistptr - DW_AT_decl_column = 0x39 // constant - DW_AT_decl_file = 0x3a // constant - DW_AT_decl_line = 0x3b // constant - DW_AT_declaration = 0x3c // flag - DW_AT_discr_list = 0x3d // block - DW_AT_encoding = 0x3e // constant - DW_AT_external = 0x3f // flag - DW_AT_frame_base = 0x40 // block, loclistptr - DW_AT_friend = 0x41 // reference - DW_AT_identifier_case = 0x42 // constant - DW_AT_macro_info = 0x43 // macptr - DW_AT_namelist_item = 0x44 // block - DW_AT_priority = 0x45 // reference - DW_AT_segment = 0x46 // block, loclistptr - DW_AT_specification = 0x47 // reference - DW_AT_static_link = 0x48 // block, loclistptr - DW_AT_type = 0x49 // reference - DW_AT_use_location = 0x4a // block, loclistptr - DW_AT_variable_parameter = 0x4b // flag - DW_AT_virtuality = 0x4c // constant - DW_AT_vtable_elem_location = 0x4d // block, loclistptr - // Dwarf3 - DW_AT_allocated = 0x4e // block, constant, reference - DW_AT_associated = 0x4f // block, constant, reference - DW_AT_data_location = 0x50 // block - DW_AT_byte_stride = 0x51 // block, constant, reference - DW_AT_entry_pc = 0x52 // address - DW_AT_use_UTF8 = 0x53 // flag - DW_AT_extension = 0x54 // reference - DW_AT_ranges = 0x55 // rangelistptr - DW_AT_trampoline = 0x56 // address, flag, reference, string - DW_AT_call_column = 0x57 // constant - DW_AT_call_file = 0x58 // constant - DW_AT_call_line = 0x59 // constant - DW_AT_description = 0x5a // string - DW_AT_binary_scale = 0x5b // constant - DW_AT_decimal_scale = 0x5c // constant - DW_AT_small = 0x5d // reference - DW_AT_decimal_sign = 0x5e // constant - DW_AT_digit_count = 0x5f // constant - DW_AT_picture_string = 0x60 // string - DW_AT_mutable = 0x61 // flag - DW_AT_threads_scaled = 0x62 // flag - DW_AT_explicit = 0x63 // flag - DW_AT_object_pointer = 0x64 // reference - DW_AT_endianity = 0x65 // constant - DW_AT_elemental = 0x66 // flag - DW_AT_pure = 0x67 // flag - DW_AT_recursive = 0x68 // flag - - DW_AT_lo_user = 0x2000 // --- - DW_AT_hi_user = 0x3fff // --- -) - -// Table 21 -const ( - DW_FORM_addr = 0x01 // address - DW_FORM_block2 = 0x03 // block - DW_FORM_block4 = 0x04 // block - DW_FORM_data2 = 0x05 // constant - DW_FORM_data4 = 0x06 // constant, lineptr, loclistptr, macptr, rangelistptr - DW_FORM_data8 = 0x07 // constant, lineptr, loclistptr, macptr, rangelistptr - DW_FORM_string = 0x08 // string - DW_FORM_block = 0x09 // block - DW_FORM_block1 = 0x0a // block - DW_FORM_data1 = 0x0b // constant - DW_FORM_flag = 0x0c // flag - DW_FORM_sdata = 0x0d // constant - DW_FORM_strp = 0x0e // string - DW_FORM_udata = 0x0f // constant - DW_FORM_ref_addr = 0x10 // reference - DW_FORM_ref1 = 0x11 // reference - DW_FORM_ref2 = 0x12 // reference - DW_FORM_ref4 = 0x13 // reference - DW_FORM_ref8 = 0x14 // reference - DW_FORM_ref_udata = 0x15 // reference - DW_FORM_indirect = 0x16 // (see Section 7.5.3) - // Dwarf4 - DW_FORM_sec_offset = 0x17 // lineptr, loclistptr, macptr, rangelistptr - DW_FORM_exprloc = 0x18 // exprloc - DW_FORM_flag_present = 0x19 // flag - DW_FORM_ref_sig8 = 0x20 // reference - // Pseudo-form: expanded to data4 on IOS, udata elsewhere. - DW_FORM_udata_pseudo = 0x99 -) - -// Table 24 (#operands, notes) -const ( - DW_OP_addr = 0x03 // 1 constant address (size target specific) - DW_OP_deref = 0x06 // 0 - DW_OP_const1u = 0x08 // 1 1-byte constant - DW_OP_const1s = 0x09 // 1 1-byte constant - DW_OP_const2u = 0x0a // 1 2-byte constant - DW_OP_const2s = 0x0b // 1 2-byte constant - DW_OP_const4u = 0x0c // 1 4-byte constant - DW_OP_const4s = 0x0d // 1 4-byte constant - DW_OP_const8u = 0x0e // 1 8-byte constant - DW_OP_const8s = 0x0f // 1 8-byte constant - DW_OP_constu = 0x10 // 1 ULEB128 constant - DW_OP_consts = 0x11 // 1 SLEB128 constant - DW_OP_dup = 0x12 // 0 - DW_OP_drop = 0x13 // 0 - DW_OP_over = 0x14 // 0 - DW_OP_pick = 0x15 // 1 1-byte stack index - DW_OP_swap = 0x16 // 0 - DW_OP_rot = 0x17 // 0 - DW_OP_xderef = 0x18 // 0 - DW_OP_abs = 0x19 // 0 - DW_OP_and = 0x1a // 0 - DW_OP_div = 0x1b // 0 - DW_OP_minus = 0x1c // 0 - DW_OP_mod = 0x1d // 0 - DW_OP_mul = 0x1e // 0 - DW_OP_neg = 0x1f // 0 - DW_OP_not = 0x20 // 0 - DW_OP_or = 0x21 // 0 - DW_OP_plus = 0x22 // 0 - DW_OP_plus_uconst = 0x23 // 1 ULEB128 addend - DW_OP_shl = 0x24 // 0 - DW_OP_shr = 0x25 // 0 - DW_OP_shra = 0x26 // 0 - DW_OP_xor = 0x27 // 0 - DW_OP_skip = 0x2f // 1 signed 2-byte constant - DW_OP_bra = 0x28 // 1 signed 2-byte constant - DW_OP_eq = 0x29 // 0 - DW_OP_ge = 0x2a // 0 - DW_OP_gt = 0x2b // 0 - DW_OP_le = 0x2c // 0 - DW_OP_lt = 0x2d // 0 - DW_OP_ne = 0x2e // 0 - DW_OP_lit0 = 0x30 // 0 ... - DW_OP_lit31 = 0x4f // 0 literals 0..31 = (DW_OP_lit0 + literal) - DW_OP_reg0 = 0x50 // 0 .. - DW_OP_reg31 = 0x6f // 0 reg 0..31 = (DW_OP_reg0 + regnum) - DW_OP_breg0 = 0x70 // 1 ... - DW_OP_breg31 = 0x8f // 1 SLEB128 offset base register 0..31 = (DW_OP_breg0 + regnum) - DW_OP_regx = 0x90 // 1 ULEB128 register - DW_OP_fbreg = 0x91 // 1 SLEB128 offset - DW_OP_bregx = 0x92 // 2 ULEB128 register followed by SLEB128 offset - DW_OP_piece = 0x93 // 1 ULEB128 size of piece addressed - DW_OP_deref_size = 0x94 // 1 1-byte size of data retrieved - DW_OP_xderef_size = 0x95 // 1 1-byte size of data retrieved - DW_OP_nop = 0x96 // 0 - DW_OP_push_object_address = 0x97 // 0 - DW_OP_call2 = 0x98 // 1 2-byte offset of DIE - DW_OP_call4 = 0x99 // 1 4-byte offset of DIE - DW_OP_call_ref = 0x9a // 1 4- or 8-byte offset of DIE - DW_OP_form_tls_address = 0x9b // 0 - DW_OP_call_frame_cfa = 0x9c // 0 - DW_OP_bit_piece = 0x9d // 2 - DW_OP_lo_user = 0xe0 - DW_OP_hi_user = 0xff -) - -// Table 25 -const ( - DW_ATE_address = 0x01 - DW_ATE_boolean = 0x02 - DW_ATE_complex_float = 0x03 - DW_ATE_float = 0x04 - DW_ATE_signed = 0x05 - DW_ATE_signed_char = 0x06 - DW_ATE_unsigned = 0x07 - DW_ATE_unsigned_char = 0x08 - DW_ATE_imaginary_float = 0x09 - DW_ATE_packed_decimal = 0x0a - DW_ATE_numeric_string = 0x0b - DW_ATE_edited = 0x0c - DW_ATE_signed_fixed = 0x0d - DW_ATE_unsigned_fixed = 0x0e - DW_ATE_decimal_float = 0x0f - DW_ATE_lo_user = 0x80 - DW_ATE_hi_user = 0xff -) - -// Table 26 -const ( - DW_DS_unsigned = 0x01 - DW_DS_leading_overpunch = 0x02 - DW_DS_trailing_overpunch = 0x03 - DW_DS_leading_separate = 0x04 - DW_DS_trailing_separate = 0x05 -) - -// Table 27 -const ( - DW_END_default = 0x00 - DW_END_big = 0x01 - DW_END_little = 0x02 - DW_END_lo_user = 0x40 - DW_END_hi_user = 0xff -) - -// Table 28 -const ( - DW_ACCESS_public = 0x01 - DW_ACCESS_protected = 0x02 - DW_ACCESS_private = 0x03 -) - -// Table 29 -const ( - DW_VIS_local = 0x01 - DW_VIS_exported = 0x02 - DW_VIS_qualified = 0x03 -) - -// Table 30 -const ( - DW_VIRTUALITY_none = 0x00 - DW_VIRTUALITY_virtual = 0x01 - DW_VIRTUALITY_pure_virtual = 0x02 -) - -// Table 31 -const ( - DW_LANG_C89 = 0x0001 - DW_LANG_C = 0x0002 - DW_LANG_Ada83 = 0x0003 - DW_LANG_C_plus_plus = 0x0004 - DW_LANG_Cobol74 = 0x0005 - DW_LANG_Cobol85 = 0x0006 - DW_LANG_Fortran77 = 0x0007 - DW_LANG_Fortran90 = 0x0008 - DW_LANG_Pascal83 = 0x0009 - DW_LANG_Modula2 = 0x000a - // Dwarf3 - DW_LANG_Java = 0x000b - DW_LANG_C99 = 0x000c - DW_LANG_Ada95 = 0x000d - DW_LANG_Fortran95 = 0x000e - DW_LANG_PLI = 0x000f - DW_LANG_ObjC = 0x0010 - DW_LANG_ObjC_plus_plus = 0x0011 - DW_LANG_UPC = 0x0012 - DW_LANG_D = 0x0013 - // Dwarf4 - DW_LANG_Python = 0x0014 - // Dwarf5 - DW_LANG_Go = 0x0016 - - DW_LANG_lo_user = 0x8000 - DW_LANG_hi_user = 0xffff -) - -// Table 32 -const ( - DW_ID_case_sensitive = 0x00 - DW_ID_up_case = 0x01 - DW_ID_down_case = 0x02 - DW_ID_case_insensitive = 0x03 -) - -// Table 33 -const ( - DW_CC_normal = 0x01 - DW_CC_program = 0x02 - DW_CC_nocall = 0x03 - DW_CC_lo_user = 0x40 - DW_CC_hi_user = 0xff -) - -// Table 34 -const ( - DW_INL_not_inlined = 0x00 - DW_INL_inlined = 0x01 - DW_INL_declared_not_inlined = 0x02 - DW_INL_declared_inlined = 0x03 -) - -// Table 35 -const ( - DW_ORD_row_major = 0x00 - DW_ORD_col_major = 0x01 -) - -// Table 36 -const ( - DW_DSC_label = 0x00 - DW_DSC_range = 0x01 -) - -// Table 37 -const ( - DW_LNS_copy = 0x01 - DW_LNS_advance_pc = 0x02 - DW_LNS_advance_line = 0x03 - DW_LNS_set_file = 0x04 - DW_LNS_set_column = 0x05 - DW_LNS_negate_stmt = 0x06 - DW_LNS_set_basic_block = 0x07 - DW_LNS_const_add_pc = 0x08 - DW_LNS_fixed_advance_pc = 0x09 - // Dwarf3 - DW_LNS_set_prologue_end = 0x0a - DW_LNS_set_epilogue_begin = 0x0b - DW_LNS_set_isa = 0x0c -) - -// Table 38 -const ( - DW_LNE_end_sequence = 0x01 - DW_LNE_set_address = 0x02 - DW_LNE_define_file = 0x03 - DW_LNE_lo_user = 0x80 - DW_LNE_hi_user = 0xff -) - -// Table 39 -const ( - DW_MACINFO_define = 0x01 - DW_MACINFO_undef = 0x02 - DW_MACINFO_start_file = 0x03 - DW_MACINFO_end_file = 0x04 - DW_MACINFO_vendor_ext = 0xff -) - -// Table 40. -const ( - // operand,... - DW_CFA_nop = 0x00 - DW_CFA_set_loc = 0x01 // address - DW_CFA_advance_loc1 = 0x02 // 1-byte delta - DW_CFA_advance_loc2 = 0x03 // 2-byte delta - DW_CFA_advance_loc4 = 0x04 // 4-byte delta - DW_CFA_offset_extended = 0x05 // ULEB128 register, ULEB128 offset - DW_CFA_restore_extended = 0x06 // ULEB128 register - DW_CFA_undefined = 0x07 // ULEB128 register - DW_CFA_same_value = 0x08 // ULEB128 register - DW_CFA_register = 0x09 // ULEB128 register, ULEB128 register - DW_CFA_remember_state = 0x0a - DW_CFA_restore_state = 0x0b - - DW_CFA_def_cfa = 0x0c // ULEB128 register, ULEB128 offset - DW_CFA_def_cfa_register = 0x0d // ULEB128 register - DW_CFA_def_cfa_offset = 0x0e // ULEB128 offset - DW_CFA_def_cfa_expression = 0x0f // BLOCK - DW_CFA_expression = 0x10 // ULEB128 register, BLOCK - DW_CFA_offset_extended_sf = 0x11 // ULEB128 register, SLEB128 offset - DW_CFA_def_cfa_sf = 0x12 // ULEB128 register, SLEB128 offset - DW_CFA_def_cfa_offset_sf = 0x13 // SLEB128 offset - DW_CFA_val_offset = 0x14 // ULEB128, ULEB128 - DW_CFA_val_offset_sf = 0x15 // ULEB128, SLEB128 - DW_CFA_val_expression = 0x16 // ULEB128, BLOCK - - DW_CFA_lo_user = 0x1c - DW_CFA_hi_user = 0x3f - - // Opcodes that take an addend operand. - DW_CFA_advance_loc = 0x1 << 6 // +delta - DW_CFA_offset = 0x2 << 6 // +register (ULEB128 offset) - DW_CFA_restore = 0x3 << 6 // +register -) diff --git a/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtin.go b/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtin.go deleted file mode 100644 index e7d612aeb..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtin.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package goobj - -// Builtin (compiler-generated) function references appear -// frequently. We assign special indices for them, so they -// don't need to be referenced by name. - -// NBuiltin returns the number of listed builtin -// symbols. -func NBuiltin() int { - return len(builtins) -} - -// BuiltinName returns the name and ABI of the i-th -// builtin symbol. -func BuiltinName(i int) (string, int) { - return builtins[i].name, builtins[i].abi -} - -// BuiltinIdx returns the index of the builtin with the -// given name and abi, or -1 if it is not a builtin. -func BuiltinIdx(name string, abi int) int { - i, ok := builtinMap[name] - if !ok { - return -1 - } - if builtins[i].abi != abi { - return -1 - } - return i -} - -//go:generate go run mkbuiltin.go - -var builtinMap map[string]int - -func init() { - builtinMap = make(map[string]int, len(builtins)) - for i, b := range builtins { - builtinMap[b.name] = i - } -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtinlist.go b/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtinlist.go deleted file mode 100644 index 0cca75233..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/goobj/builtinlist.go +++ /dev/null @@ -1,245 +0,0 @@ -// Code generated by mkbuiltin.go. DO NOT EDIT. - -package goobj - -var builtins = [...]struct { - name string - abi int -}{ - {"runtime.newobject", 1}, - {"runtime.mallocgc", 1}, - {"runtime.panicdivide", 1}, - {"runtime.panicshift", 1}, - {"runtime.panicmakeslicelen", 1}, - {"runtime.panicmakeslicecap", 1}, - {"runtime.throwinit", 1}, - {"runtime.panicwrap", 1}, - {"runtime.gopanic", 1}, - {"runtime.gorecover", 1}, - {"runtime.goschedguarded", 1}, - {"runtime.goPanicIndex", 1}, - {"runtime.goPanicIndexU", 1}, - {"runtime.goPanicSliceAlen", 1}, - {"runtime.goPanicSliceAlenU", 1}, - {"runtime.goPanicSliceAcap", 1}, - {"runtime.goPanicSliceAcapU", 1}, - {"runtime.goPanicSliceB", 1}, - {"runtime.goPanicSliceBU", 1}, - {"runtime.goPanicSlice3Alen", 1}, - {"runtime.goPanicSlice3AlenU", 1}, - {"runtime.goPanicSlice3Acap", 1}, - {"runtime.goPanicSlice3AcapU", 1}, - {"runtime.goPanicSlice3B", 1}, - {"runtime.goPanicSlice3BU", 1}, - {"runtime.goPanicSlice3C", 1}, - {"runtime.goPanicSlice3CU", 1}, - {"runtime.printbool", 1}, - {"runtime.printfloat", 1}, - {"runtime.printint", 1}, - {"runtime.printhex", 1}, - {"runtime.printuint", 1}, - {"runtime.printcomplex", 1}, - {"runtime.printstring", 1}, - {"runtime.printpointer", 1}, - {"runtime.printiface", 1}, - {"runtime.printeface", 1}, - {"runtime.printslice", 1}, - {"runtime.printnl", 1}, - {"runtime.printsp", 1}, - {"runtime.printlock", 1}, - {"runtime.printunlock", 1}, - {"runtime.concatstring2", 1}, - {"runtime.concatstring3", 1}, - {"runtime.concatstring4", 1}, - {"runtime.concatstring5", 1}, - {"runtime.concatstrings", 1}, - {"runtime.cmpstring", 1}, - {"runtime.intstring", 1}, - {"runtime.slicebytetostring", 1}, - {"runtime.slicebytetostringtmp", 1}, - {"runtime.slicerunetostring", 1}, - {"runtime.stringtoslicebyte", 1}, - {"runtime.stringtoslicerune", 1}, - {"runtime.slicecopy", 1}, - {"runtime.slicestringcopy", 1}, - {"runtime.decoderune", 1}, - {"runtime.countrunes", 1}, - {"runtime.convI2I", 1}, - {"runtime.convT16", 1}, - {"runtime.convT32", 1}, - {"runtime.convT64", 1}, - {"runtime.convTstring", 1}, - {"runtime.convTslice", 1}, - {"runtime.convT2E", 1}, - {"runtime.convT2Enoptr", 1}, - {"runtime.convT2I", 1}, - {"runtime.convT2Inoptr", 1}, - {"runtime.assertE2I", 1}, - {"runtime.assertE2I2", 1}, - {"runtime.assertI2I", 1}, - {"runtime.assertI2I2", 1}, - {"runtime.panicdottypeE", 1}, - {"runtime.panicdottypeI", 1}, - {"runtime.panicnildottype", 1}, - {"runtime.ifaceeq", 1}, - {"runtime.efaceeq", 1}, - {"runtime.fastrand", 1}, - {"runtime.makemap64", 1}, - {"runtime.makemap", 1}, - {"runtime.makemap_small", 1}, - {"runtime.mapaccess1", 1}, - {"runtime.mapaccess1_fast32", 1}, - {"runtime.mapaccess1_fast64", 1}, - {"runtime.mapaccess1_faststr", 1}, - {"runtime.mapaccess1_fat", 1}, - {"runtime.mapaccess2", 1}, - {"runtime.mapaccess2_fast32", 1}, - {"runtime.mapaccess2_fast64", 1}, - {"runtime.mapaccess2_faststr", 1}, - {"runtime.mapaccess2_fat", 1}, - {"runtime.mapassign", 1}, - {"runtime.mapassign_fast32", 1}, - {"runtime.mapassign_fast32ptr", 1}, - {"runtime.mapassign_fast64", 1}, - {"runtime.mapassign_fast64ptr", 1}, - {"runtime.mapassign_faststr", 1}, - {"runtime.mapiterinit", 1}, - {"runtime.mapdelete", 1}, - {"runtime.mapdelete_fast32", 1}, - {"runtime.mapdelete_fast64", 1}, - {"runtime.mapdelete_faststr", 1}, - {"runtime.mapiternext", 1}, - {"runtime.mapclear", 1}, - {"runtime.makechan64", 1}, - {"runtime.makechan", 1}, - {"runtime.chanrecv1", 1}, - {"runtime.chanrecv2", 1}, - {"runtime.chansend1", 1}, - {"runtime.closechan", 1}, - {"runtime.writeBarrier", 0}, - {"runtime.typedmemmove", 1}, - {"runtime.typedmemclr", 1}, - {"runtime.typedslicecopy", 1}, - {"runtime.selectnbsend", 1}, - {"runtime.selectnbrecv", 1}, - {"runtime.selectnbrecv2", 1}, - {"runtime.selectsetpc", 1}, - {"runtime.selectgo", 1}, - {"runtime.block", 1}, - {"runtime.makeslice", 1}, - {"runtime.makeslice64", 1}, - {"runtime.makeslicecopy", 1}, - {"runtime.growslice", 1}, - {"runtime.memmove", 1}, - {"runtime.memclrNoHeapPointers", 1}, - {"runtime.memclrHasPointers", 1}, - {"runtime.memequal", 1}, - {"runtime.memequal0", 1}, - {"runtime.memequal8", 1}, - {"runtime.memequal16", 1}, - {"runtime.memequal32", 1}, - {"runtime.memequal64", 1}, - {"runtime.memequal128", 1}, - {"runtime.f32equal", 1}, - {"runtime.f64equal", 1}, - {"runtime.c64equal", 1}, - {"runtime.c128equal", 1}, - {"runtime.strequal", 1}, - {"runtime.interequal", 1}, - {"runtime.nilinterequal", 1}, - {"runtime.memhash", 1}, - {"runtime.memhash0", 1}, - {"runtime.memhash8", 1}, - {"runtime.memhash16", 1}, - {"runtime.memhash32", 1}, - {"runtime.memhash64", 1}, - {"runtime.memhash128", 1}, - {"runtime.f32hash", 1}, - {"runtime.f64hash", 1}, - {"runtime.c64hash", 1}, - {"runtime.c128hash", 1}, - {"runtime.strhash", 1}, - {"runtime.interhash", 1}, - {"runtime.nilinterhash", 1}, - {"runtime.int64div", 1}, - {"runtime.uint64div", 1}, - {"runtime.int64mod", 1}, - {"runtime.uint64mod", 1}, - {"runtime.float64toint64", 1}, - {"runtime.float64touint64", 1}, - {"runtime.float64touint32", 1}, - {"runtime.int64tofloat64", 1}, - {"runtime.uint64tofloat64", 1}, - {"runtime.uint32tofloat64", 1}, - {"runtime.complex128div", 1}, - {"runtime.racefuncenter", 1}, - {"runtime.racefuncenterfp", 1}, - {"runtime.racefuncexit", 1}, - {"runtime.raceread", 1}, - {"runtime.racewrite", 1}, - {"runtime.racereadrange", 1}, - {"runtime.racewriterange", 1}, - {"runtime.msanread", 1}, - {"runtime.msanwrite", 1}, - {"runtime.checkptrAlignment", 1}, - {"runtime.checkptrArithmetic", 1}, - {"runtime.libfuzzerTraceCmp1", 1}, - {"runtime.libfuzzerTraceCmp2", 1}, - {"runtime.libfuzzerTraceCmp4", 1}, - {"runtime.libfuzzerTraceCmp8", 1}, - {"runtime.libfuzzerTraceConstCmp1", 1}, - {"runtime.libfuzzerTraceConstCmp2", 1}, - {"runtime.libfuzzerTraceConstCmp4", 1}, - {"runtime.libfuzzerTraceConstCmp8", 1}, - {"runtime.x86HasPOPCNT", 0}, - {"runtime.x86HasSSE41", 0}, - {"runtime.x86HasFMA", 0}, - {"runtime.armHasVFPv4", 0}, - {"runtime.arm64HasATOMICS", 0}, - {"runtime.deferproc", 1}, - {"runtime.deferprocStack", 1}, - {"runtime.deferreturn", 1}, - {"runtime.newproc", 1}, - {"runtime.panicoverflow", 1}, - {"runtime.sigpanic", 1}, - {"runtime.gcWriteBarrier", 0}, - {"runtime.morestack", 0}, - {"runtime.morestackc", 0}, - {"runtime.morestack_noctxt", 0}, - {"type.int8", 0}, - {"type.*int8", 0}, - {"type.uint8", 0}, - {"type.*uint8", 0}, - {"type.int16", 0}, - {"type.*int16", 0}, - {"type.uint16", 0}, - {"type.*uint16", 0}, - {"type.int32", 0}, - {"type.*int32", 0}, - {"type.uint32", 0}, - {"type.*uint32", 0}, - {"type.int64", 0}, - {"type.*int64", 0}, - {"type.uint64", 0}, - {"type.*uint64", 0}, - {"type.float32", 0}, - {"type.*float32", 0}, - {"type.float64", 0}, - {"type.*float64", 0}, - {"type.complex64", 0}, - {"type.*complex64", 0}, - {"type.complex128", 0}, - {"type.*complex128", 0}, - {"type.unsafe.Pointer", 0}, - {"type.*unsafe.Pointer", 0}, - {"type.uintptr", 0}, - {"type.*uintptr", 0}, - {"type.bool", 0}, - {"type.*bool", 0}, - {"type.string", 0}, - {"type.*string", 0}, - {"type.error", 0}, - {"type.*error", 0}, - {"type.func(error) string", 0}, - {"type.*func(error) string", 0}, -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/goobj/funcinfo.go b/vendor/github.com/twitchyliquid64/golang-asm/goobj/funcinfo.go deleted file mode 100644 index 9e192330d..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/goobj/funcinfo.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package goobj - -import ( - "bytes" - "github.com/twitchyliquid64/golang-asm/objabi" - "encoding/binary" -) - -// CUFileIndex is used to index the filenames that are stored in the -// per-package/per-CU FileList. -type CUFileIndex uint32 - -// FuncInfo is serialized as a symbol (aux symbol). The symbol data is -// the binary encoding of the struct below. -// -// TODO: make each pcdata a separate symbol? -type FuncInfo struct { - Args uint32 - Locals uint32 - FuncID objabi.FuncID - - Pcsp uint32 - Pcfile uint32 - Pcline uint32 - Pcinline uint32 - Pcdata []uint32 - PcdataEnd uint32 - Funcdataoff []uint32 - File []CUFileIndex - - InlTree []InlTreeNode -} - -func (a *FuncInfo) Write(w *bytes.Buffer) { - var b [4]byte - writeUint32 := func(x uint32) { - binary.LittleEndian.PutUint32(b[:], x) - w.Write(b[:]) - } - - writeUint32(a.Args) - writeUint32(a.Locals) - writeUint32(uint32(a.FuncID)) - - writeUint32(a.Pcsp) - writeUint32(a.Pcfile) - writeUint32(a.Pcline) - writeUint32(a.Pcinline) - writeUint32(uint32(len(a.Pcdata))) - for _, x := range a.Pcdata { - writeUint32(x) - } - writeUint32(a.PcdataEnd) - writeUint32(uint32(len(a.Funcdataoff))) - for _, x := range a.Funcdataoff { - writeUint32(x) - } - writeUint32(uint32(len(a.File))) - for _, f := range a.File { - writeUint32(uint32(f)) - } - writeUint32(uint32(len(a.InlTree))) - for i := range a.InlTree { - a.InlTree[i].Write(w) - } -} - -func (a *FuncInfo) Read(b []byte) { - readUint32 := func() uint32 { - x := binary.LittleEndian.Uint32(b) - b = b[4:] - return x - } - - a.Args = readUint32() - a.Locals = readUint32() - a.FuncID = objabi.FuncID(readUint32()) - - a.Pcsp = readUint32() - a.Pcfile = readUint32() - a.Pcline = readUint32() - a.Pcinline = readUint32() - pcdatalen := readUint32() - a.Pcdata = make([]uint32, pcdatalen) - for i := range a.Pcdata { - a.Pcdata[i] = readUint32() - } - a.PcdataEnd = readUint32() - funcdataofflen := readUint32() - a.Funcdataoff = make([]uint32, funcdataofflen) - for i := range a.Funcdataoff { - a.Funcdataoff[i] = readUint32() - } - filelen := readUint32() - a.File = make([]CUFileIndex, filelen) - for i := range a.File { - a.File[i] = CUFileIndex(readUint32()) - } - inltreelen := readUint32() - a.InlTree = make([]InlTreeNode, inltreelen) - for i := range a.InlTree { - b = a.InlTree[i].Read(b) - } -} - -// FuncInfoLengths is a cache containing a roadmap of offsets and -// lengths for things within a serialized FuncInfo. Each length field -// stores the number of items (e.g. files, inltree nodes, etc), and the -// corresponding "off" field stores the byte offset of the start of -// the items in question. -type FuncInfoLengths struct { - NumPcdata uint32 - PcdataOff uint32 - NumFuncdataoff uint32 - FuncdataoffOff uint32 - NumFile uint32 - FileOff uint32 - NumInlTree uint32 - InlTreeOff uint32 - Initialized bool -} - -func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { - var result FuncInfoLengths - - const numpcdataOff = 28 - result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:]) - result.PcdataOff = numpcdataOff + 4 - - numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1) - result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) - result.FuncdataoffOff = numfuncdataoffOff + 4 - - numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff - result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) - result.FileOff = numfileOff + 4 - - numinltreeOff := result.FileOff + 4*result.NumFile - result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:]) - result.InlTreeOff = numinltreeOff + 4 - - result.Initialized = true - - return result -} - -func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } - -func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) } - -func (*FuncInfo) ReadFuncID(b []byte) uint32 { return binary.LittleEndian.Uint32(b[8:]) } - -// return start and end offsets. -func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) { - return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:]) -} - -// return start and end offsets. -func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) { - return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:]) -} - -// return start and end offsets. -func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) { - return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:]) -} - -// return start and end offsets. -func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) { - return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:]) -} - -// return start and end offsets. -func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) { - return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:]) -} - -func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 { - return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:])) -} - -func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { - return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) -} - -func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode { - const inlTreeNodeSize = 4 * 6 - var result InlTreeNode - result.Read(b[inltreeoff+k*inlTreeNodeSize:]) - return result -} - -// InlTreeNode is the serialized form of FileInfo.InlTree. -type InlTreeNode struct { - Parent int32 - File CUFileIndex - Line int32 - Func SymRef - ParentPC int32 -} - -func (inl *InlTreeNode) Write(w *bytes.Buffer) { - var b [4]byte - writeUint32 := func(x uint32) { - binary.LittleEndian.PutUint32(b[:], x) - w.Write(b[:]) - } - writeUint32(uint32(inl.Parent)) - writeUint32(uint32(inl.File)) - writeUint32(uint32(inl.Line)) - writeUint32(inl.Func.PkgIdx) - writeUint32(inl.Func.SymIdx) - writeUint32(uint32(inl.ParentPC)) -} - -// Read an InlTreeNode from b, return the remaining bytes. -func (inl *InlTreeNode) Read(b []byte) []byte { - readUint32 := func() uint32 { - x := binary.LittleEndian.Uint32(b) - b = b[4:] - return x - } - inl.Parent = int32(readUint32()) - inl.File = CUFileIndex(readUint32()) - inl.Line = int32(readUint32()) - inl.Func = SymRef{readUint32(), readUint32()} - inl.ParentPC = int32(readUint32()) - return b -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/goobj/objfile.go b/vendor/github.com/twitchyliquid64/golang-asm/goobj/objfile.go deleted file mode 100644 index 3303549aa..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/goobj/objfile.go +++ /dev/null @@ -1,871 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This package defines the Go object file format, and provide "low-level" functions -// for reading and writing object files. - -// The object file is understood by the compiler, assembler, linker, and tools. They -// have "high level" code that operates on object files, handling application-specific -// logics, and use this package for the actual reading and writing. Specifically, the -// code below: -// -// - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile) -// - cmd/internal/objfile/goobj.go (used cmd/nm, cmd/objdump) -// - cmd/link/internal/loader package (used by cmd/link) -// -// If the object file format changes, they may (or may not) need to change. - -package goobj - -import ( - "bytes" - "github.com/twitchyliquid64/golang-asm/bio" - "crypto/sha1" - "encoding/binary" - "errors" - "fmt" - "github.com/twitchyliquid64/golang-asm/unsafeheader" - "io" - "unsafe" -) - -// New object file format. -// -// Header struct { -// Magic [...]byte // "\x00go116ld" -// Fingerprint [8]byte -// Flags uint32 -// Offsets [...]uint32 // byte offset of each block below -// } -// -// Strings [...]struct { -// Data [...]byte -// } -// -// Autolib [...]struct { // imported packages (for file loading) -// Pkg string -// Fingerprint [8]byte -// } -// -// PkgIndex [...]string // referenced packages by index -// -// Files [...]string -// -// SymbolDefs [...]struct { -// Name string -// ABI uint16 -// Type uint8 -// Flag uint8 -// Flag2 uint8 -// Size uint32 -// } -// Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions -// ... // same as SymbolDefs -// } -// HashedDefs [...]struct { // hashed (content-addressable) symbol definitions -// ... // same as SymbolDefs -// } -// NonPkgDefs [...]struct { // non-pkg symbol definitions -// ... // same as SymbolDefs -// } -// NonPkgRefs [...]struct { // non-pkg symbol references -// ... // same as SymbolDefs -// } -// -// RefFlags [...]struct { // referenced symbol flags -// Sym symRef -// Flag uint8 -// Flag2 uint8 -// } -// -// Hash64 [...][8]byte -// Hash [...][N]byte -// -// RelocIndex [...]uint32 // index to Relocs -// AuxIndex [...]uint32 // index to Aux -// DataIndex [...]uint32 // offset to Data -// -// Relocs [...]struct { -// Off int32 -// Size uint8 -// Type uint8 -// Add int64 -// Sym symRef -// } -// -// Aux [...]struct { -// Type uint8 -// Sym symRef -// } -// -// Data [...]byte -// Pcdata [...]byte -// -// // blocks only used by tools (objdump, nm) -// -// RefNames [...]struct { // referenced symbol names -// Sym symRef -// Name string -// // TODO: include ABI version as well? -// } -// -// string is encoded as is a uint32 length followed by a uint32 offset -// that points to the corresponding string bytes. -// -// symRef is struct { PkgIdx, SymIdx uint32 }. -// -// Slice type (e.g. []symRef) is encoded as a length prefix (uint32) -// followed by that number of elements. -// -// The types below correspond to the encoded data structure in the -// object file. - -// Symbol indexing. -// -// Each symbol is referenced with a pair of indices, { PkgIdx, SymIdx }, -// as the symRef struct above. -// -// PkgIdx is either a predeclared index (see PkgIdxNone below) or -// an index of an imported package. For the latter case, PkgIdx is the -// index of the package in the PkgIndex array. 0 is an invalid index. -// -// SymIdx is the index of the symbol in the given package. -// - If PkgIdx is PkgIdxSelf, SymIdx is the index of the symbol in the -// SymbolDefs array. -// - If PkgIdx is PkgIdxHashed64, SymIdx is the index of the symbol in the -// Hashed64Defs array. -// - If PkgIdx is PkgIdxHashed, SymIdx is the index of the symbol in the -// HashedDefs array. -// - If PkgIdx is PkgIdxNone, SymIdx is the index of the symbol in the -// NonPkgDefs array (could natually overflow to NonPkgRefs array). -// - Otherwise, SymIdx is the index of the symbol in some other package's -// SymbolDefs array. -// -// {0, 0} represents a nil symbol. Otherwise PkgIdx should not be 0. -// -// Hash contains the content hashes of content-addressable symbols, of -// which PkgIdx is PkgIdxHashed, in the same order of HashedDefs array. -// Hash64 is similar, for PkgIdxHashed64 symbols. -// -// RelocIndex, AuxIndex, and DataIndex contains indices/offsets to -// Relocs/Aux/Data blocks, one element per symbol, first for all the -// defined symbols, then all the defined hashed and non-package symbols, -// in the same order of SymbolDefs/Hashed64Defs/HashedDefs/NonPkgDefs -// arrays. For N total defined symbols, the array is of length N+1. The -// last element is the total number of relocations (aux symbols, data -// blocks, etc.). -// -// They can be accessed by index. For the i-th symbol, its relocations -// are the RelocIndex[i]-th (inclusive) to RelocIndex[i+1]-th (exclusive) -// elements in the Relocs array. Aux/Data are likewise. (The index is -// 0-based.) - -// Auxiliary symbols. -// -// Each symbol may (or may not) be associated with a number of auxiliary -// symbols. They are described in the Aux block. See Aux struct below. -// Currently a symbol's Gotype, FuncInfo, and associated DWARF symbols -// are auxiliary symbols. - -const stringRefSize = 8 // two uint32s - -type FingerprintType [8]byte - -func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} } - -// Package Index. -const ( - PkgIdxNone = (1<<31 - 1) - iota // Non-package symbols - PkgIdxHashed64 // Short hashed (content-addressable) symbols - PkgIdxHashed // Hashed (content-addressable) symbols - PkgIdxBuiltin // Predefined runtime symbols (ex: runtime.newobject) - PkgIdxSelf // Symbols defined in the current package - PkgIdxInvalid = 0 - // The index of other referenced packages starts from 1. -) - -// Blocks -const ( - BlkAutolib = iota - BlkPkgIdx - BlkFile - BlkSymdef - BlkHashed64def - BlkHasheddef - BlkNonpkgdef - BlkNonpkgref - BlkRefFlags - BlkHash64 - BlkHash - BlkRelocIdx - BlkAuxIdx - BlkDataIdx - BlkReloc - BlkAux - BlkData - BlkPcdata - BlkRefName - BlkEnd - NBlk -) - -// File header. -// TODO: probably no need to export this. -type Header struct { - Magic string - Fingerprint FingerprintType - Flags uint32 - Offsets [NBlk]uint32 -} - -const Magic = "\x00go116ld" - -func (h *Header) Write(w *Writer) { - w.RawString(h.Magic) - w.Bytes(h.Fingerprint[:]) - w.Uint32(h.Flags) - for _, x := range h.Offsets { - w.Uint32(x) - } -} - -func (h *Header) Read(r *Reader) error { - b := r.BytesAt(0, len(Magic)) - h.Magic = string(b) - if h.Magic != Magic { - return errors.New("wrong magic, not a Go object file") - } - off := uint32(len(h.Magic)) - copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint))) - off += 8 - h.Flags = r.uint32At(off) - off += 4 - for i := range h.Offsets { - h.Offsets[i] = r.uint32At(off) - off += 4 - } - return nil -} - -func (h *Header) Size() int { - return len(h.Magic) + 4 + 4*len(h.Offsets) -} - -// Autolib -type ImportedPkg struct { - Pkg string - Fingerprint FingerprintType -} - -const importedPkgSize = stringRefSize + 8 - -func (p *ImportedPkg) Write(w *Writer) { - w.StringRef(p.Pkg) - w.Bytes(p.Fingerprint[:]) -} - -// Symbol definition. -// -// Serialized format: -// Sym struct { -// Name string -// ABI uint16 -// Type uint8 -// Flag uint8 -// Flag2 uint8 -// Siz uint32 -// Align uint32 -// } -type Sym [SymSize]byte - -const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4 - -const SymABIstatic = ^uint16(0) - -const ( - ObjFlagShared = 1 << iota // this object is built with -shared - ObjFlagNeedNameExpansion // the linker needs to expand `"".` to package path in symbol names - ObjFlagFromAssembly // object is from asm src, not go -) - -// Sym.Flag -const ( - SymFlagDupok = 1 << iota - SymFlagLocal - SymFlagTypelink - SymFlagLeaf - SymFlagNoSplit - SymFlagReflectMethod - SymFlagGoType - SymFlagTopFrame -) - -// Sym.Flag2 -const ( - SymFlagUsedInIface = 1 << iota - SymFlagItab -) - -// Returns the length of the name of the symbol. -func (s *Sym) NameLen(r *Reader) int { - return int(binary.LittleEndian.Uint32(s[:])) -} - -func (s *Sym) Name(r *Reader) string { - len := binary.LittleEndian.Uint32(s[:]) - off := binary.LittleEndian.Uint32(s[4:]) - return r.StringAt(off, len) -} - -func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) } -func (s *Sym) Type() uint8 { return s[10] } -func (s *Sym) Flag() uint8 { return s[11] } -func (s *Sym) Flag2() uint8 { return s[12] } -func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) } -func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) } - -func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 } -func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 } -func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 } -func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 } -func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 } -func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 } -func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 } -func (s *Sym) TopFrame() bool { return s.Flag()&SymFlagTopFrame != 0 } -func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 } -func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 } - -func (s *Sym) SetName(x string, w *Writer) { - binary.LittleEndian.PutUint32(s[:], uint32(len(x))) - binary.LittleEndian.PutUint32(s[4:], w.stringOff(x)) -} - -func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) } -func (s *Sym) SetType(x uint8) { s[10] = x } -func (s *Sym) SetFlag(x uint8) { s[11] = x } -func (s *Sym) SetFlag2(x uint8) { s[12] = x } -func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) } -func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) } - -func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) } - -// for testing -func (s *Sym) fromBytes(b []byte) { copy(s[:], b) } - -// Symbol reference. -type SymRef struct { - PkgIdx uint32 - SymIdx uint32 -} - -// Hash64 -type Hash64Type [Hash64Size]byte - -const Hash64Size = 8 - -// Hash -type HashType [HashSize]byte - -const HashSize = sha1.Size - -// Relocation. -// -// Serialized format: -// Reloc struct { -// Off int32 -// Siz uint8 -// Type uint8 -// Add int64 -// Sym SymRef -// } -type Reloc [RelocSize]byte - -const RelocSize = 4 + 1 + 1 + 8 + 8 - -func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) } -func (r *Reloc) Siz() uint8 { return r[4] } -func (r *Reloc) Type() uint8 { return r[5] } -func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[6:])) } -func (r *Reloc) Sym() SymRef { - return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])} -} - -func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) } -func (r *Reloc) SetSiz(x uint8) { r[4] = x } -func (r *Reloc) SetType(x uint8) { r[5] = x } -func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[6:], uint64(x)) } -func (r *Reloc) SetSym(x SymRef) { - binary.LittleEndian.PutUint32(r[14:], x.PkgIdx) - binary.LittleEndian.PutUint32(r[18:], x.SymIdx) -} - -func (r *Reloc) Set(off int32, size uint8, typ uint8, add int64, sym SymRef) { - r.SetOff(off) - r.SetSiz(size) - r.SetType(typ) - r.SetAdd(add) - r.SetSym(sym) -} - -func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) } - -// for testing -func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) } - -// Aux symbol info. -// -// Serialized format: -// Aux struct { -// Type uint8 -// Sym SymRef -// } -type Aux [AuxSize]byte - -const AuxSize = 1 + 8 - -// Aux Type -const ( - AuxGotype = iota - AuxFuncInfo - AuxFuncdata - AuxDwarfInfo - AuxDwarfLoc - AuxDwarfRanges - AuxDwarfLines - - // TODO: more. Pcdata? -) - -func (a *Aux) Type() uint8 { return a[0] } -func (a *Aux) Sym() SymRef { - return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])} -} - -func (a *Aux) SetType(x uint8) { a[0] = x } -func (a *Aux) SetSym(x SymRef) { - binary.LittleEndian.PutUint32(a[1:], x.PkgIdx) - binary.LittleEndian.PutUint32(a[5:], x.SymIdx) -} - -func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) } - -// for testing -func (a *Aux) fromBytes(b []byte) { copy(a[:], b) } - -// Referenced symbol flags. -// -// Serialized format: -// RefFlags struct { -// Sym symRef -// Flag uint8 -// Flag2 uint8 -// } -type RefFlags [RefFlagsSize]byte - -const RefFlagsSize = 8 + 1 + 1 - -func (r *RefFlags) Sym() SymRef { - return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])} -} -func (r *RefFlags) Flag() uint8 { return r[8] } -func (r *RefFlags) Flag2() uint8 { return r[9] } - -func (r *RefFlags) SetSym(x SymRef) { - binary.LittleEndian.PutUint32(r[:], x.PkgIdx) - binary.LittleEndian.PutUint32(r[4:], x.SymIdx) -} -func (r *RefFlags) SetFlag(x uint8) { r[8] = x } -func (r *RefFlags) SetFlag2(x uint8) { r[9] = x } - -func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) } - -// Referenced symbol name. -// -// Serialized format: -// RefName struct { -// Sym symRef -// Name string -// } -type RefName [RefNameSize]byte - -const RefNameSize = 8 + stringRefSize - -func (n *RefName) Sym() SymRef { - return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])} -} -func (n *RefName) Name(r *Reader) string { - len := binary.LittleEndian.Uint32(n[8:]) - off := binary.LittleEndian.Uint32(n[12:]) - return r.StringAt(off, len) -} - -func (n *RefName) SetSym(x SymRef) { - binary.LittleEndian.PutUint32(n[:], x.PkgIdx) - binary.LittleEndian.PutUint32(n[4:], x.SymIdx) -} -func (n *RefName) SetName(x string, w *Writer) { - binary.LittleEndian.PutUint32(n[8:], uint32(len(x))) - binary.LittleEndian.PutUint32(n[12:], w.stringOff(x)) -} - -func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) } - -type Writer struct { - wr *bio.Writer - stringMap map[string]uint32 - off uint32 // running offset -} - -func NewWriter(wr *bio.Writer) *Writer { - return &Writer{wr: wr, stringMap: make(map[string]uint32)} -} - -func (w *Writer) AddString(s string) { - if _, ok := w.stringMap[s]; ok { - return - } - w.stringMap[s] = w.off - w.RawString(s) -} - -func (w *Writer) stringOff(s string) uint32 { - off, ok := w.stringMap[s] - if !ok { - panic(fmt.Sprintf("writeStringRef: string not added: %q", s)) - } - return off -} - -func (w *Writer) StringRef(s string) { - w.Uint32(uint32(len(s))) - w.Uint32(w.stringOff(s)) -} - -func (w *Writer) RawString(s string) { - w.wr.WriteString(s) - w.off += uint32(len(s)) -} - -func (w *Writer) Bytes(s []byte) { - w.wr.Write(s) - w.off += uint32(len(s)) -} - -func (w *Writer) Uint64(x uint64) { - var b [8]byte - binary.LittleEndian.PutUint64(b[:], x) - w.wr.Write(b[:]) - w.off += 8 -} - -func (w *Writer) Uint32(x uint32) { - var b [4]byte - binary.LittleEndian.PutUint32(b[:], x) - w.wr.Write(b[:]) - w.off += 4 -} - -func (w *Writer) Uint16(x uint16) { - var b [2]byte - binary.LittleEndian.PutUint16(b[:], x) - w.wr.Write(b[:]) - w.off += 2 -} - -func (w *Writer) Uint8(x uint8) { - w.wr.WriteByte(x) - w.off++ -} - -func (w *Writer) Offset() uint32 { - return w.off -} - -type Reader struct { - b []byte // mmapped bytes, if not nil - readonly bool // whether b is backed with read-only memory - - rd io.ReaderAt - start uint32 - h Header // keep block offsets -} - -func NewReaderFromBytes(b []byte, readonly bool) *Reader { - r := &Reader{b: b, readonly: readonly, rd: bytes.NewReader(b), start: 0} - err := r.h.Read(r) - if err != nil { - return nil - } - return r -} - -func (r *Reader) BytesAt(off uint32, len int) []byte { - if len == 0 { - return nil - } - end := int(off) + len - return r.b[int(off):end:end] -} - -func (r *Reader) uint64At(off uint32) uint64 { - b := r.BytesAt(off, 8) - return binary.LittleEndian.Uint64(b) -} - -func (r *Reader) int64At(off uint32) int64 { - return int64(r.uint64At(off)) -} - -func (r *Reader) uint32At(off uint32) uint32 { - b := r.BytesAt(off, 4) - return binary.LittleEndian.Uint32(b) -} - -func (r *Reader) int32At(off uint32) int32 { - return int32(r.uint32At(off)) -} - -func (r *Reader) uint16At(off uint32) uint16 { - b := r.BytesAt(off, 2) - return binary.LittleEndian.Uint16(b) -} - -func (r *Reader) uint8At(off uint32) uint8 { - b := r.BytesAt(off, 1) - return b[0] -} - -func (r *Reader) StringAt(off uint32, len uint32) string { - b := r.b[off : off+len] - if r.readonly { - return toString(b) // backed by RO memory, ok to make unsafe string - } - return string(b) -} - -func toString(b []byte) string { - if len(b) == 0 { - return "" - } - - var s string - hdr := (*unsafeheader.String)(unsafe.Pointer(&s)) - hdr.Data = unsafe.Pointer(&b[0]) - hdr.Len = len(b) - - return s -} - -func (r *Reader) StringRef(off uint32) string { - l := r.uint32At(off) - return r.StringAt(r.uint32At(off+4), l) -} - -func (r *Reader) Fingerprint() FingerprintType { - return r.h.Fingerprint -} - -func (r *Reader) Autolib() []ImportedPkg { - n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize - s := make([]ImportedPkg, n) - off := r.h.Offsets[BlkAutolib] - for i := range s { - s[i].Pkg = r.StringRef(off) - copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint))) - off += importedPkgSize - } - return s -} - -func (r *Reader) Pkglist() []string { - n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize - s := make([]string, n) - off := r.h.Offsets[BlkPkgIdx] - for i := range s { - s[i] = r.StringRef(off) - off += stringRefSize - } - return s -} - -func (r *Reader) NPkg() int { - return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize -} - -func (r *Reader) Pkg(i int) string { - off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize - return r.StringRef(off) -} - -func (r *Reader) NFile() int { - return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize -} - -func (r *Reader) File(i int) string { - off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize - return r.StringRef(off) -} - -func (r *Reader) NSym() int { - return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize -} - -func (r *Reader) NHashed64def() int { - return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize -} - -func (r *Reader) NHasheddef() int { - return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize -} - -func (r *Reader) NNonpkgdef() int { - return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize -} - -func (r *Reader) NNonpkgref() int { - return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize -} - -// SymOff returns the offset of the i-th symbol. -func (r *Reader) SymOff(i uint32) uint32 { - return r.h.Offsets[BlkSymdef] + uint32(i*SymSize) -} - -// Sym returns a pointer to the i-th symbol. -func (r *Reader) Sym(i uint32) *Sym { - off := r.SymOff(i) - return (*Sym)(unsafe.Pointer(&r.b[off])) -} - -// NRefFlags returns the number of referenced symbol flags. -func (r *Reader) NRefFlags() int { - return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize -} - -// RefFlags returns a pointer to the i-th referenced symbol flags. -// Note: here i is not a local symbol index, just a counter. -func (r *Reader) RefFlags(i int) *RefFlags { - off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize) - return (*RefFlags)(unsafe.Pointer(&r.b[off])) -} - -// Hash64 returns the i-th short hashed symbol's hash. -// Note: here i is the index of short hashed symbols, not all symbols -// (unlike other accessors). -func (r *Reader) Hash64(i uint32) uint64 { - off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size) - return r.uint64At(off) -} - -// Hash returns a pointer to the i-th hashed symbol's hash. -// Note: here i is the index of hashed symbols, not all symbols -// (unlike other accessors). -func (r *Reader) Hash(i uint32) *HashType { - off := r.h.Offsets[BlkHash] + uint32(i*HashSize) - return (*HashType)(unsafe.Pointer(&r.b[off])) -} - -// NReloc returns the number of relocations of the i-th symbol. -func (r *Reader) NReloc(i uint32) int { - relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4) - return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff)) -} - -// RelocOff returns the offset of the j-th relocation of the i-th symbol. -func (r *Reader) RelocOff(i uint32, j int) uint32 { - relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4) - relocIdx := r.uint32At(relocIdxOff) - return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize) -} - -// Reloc returns a pointer to the j-th relocation of the i-th symbol. -func (r *Reader) Reloc(i uint32, j int) *Reloc { - off := r.RelocOff(i, j) - return (*Reloc)(unsafe.Pointer(&r.b[off])) -} - -// Relocs returns a pointer to the relocations of the i-th symbol. -func (r *Reader) Relocs(i uint32) []Reloc { - off := r.RelocOff(i, 0) - n := r.NReloc(i) - return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] -} - -// NAux returns the number of aux symbols of the i-th symbol. -func (r *Reader) NAux(i uint32) int { - auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4 - return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff)) -} - -// AuxOff returns the offset of the j-th aux symbol of the i-th symbol. -func (r *Reader) AuxOff(i uint32, j int) uint32 { - auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4 - auxIdx := r.uint32At(auxIdxOff) - return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize) -} - -// Aux returns a pointer to the j-th aux symbol of the i-th symbol. -func (r *Reader) Aux(i uint32, j int) *Aux { - off := r.AuxOff(i, j) - return (*Aux)(unsafe.Pointer(&r.b[off])) -} - -// Auxs returns the aux symbols of the i-th symbol. -func (r *Reader) Auxs(i uint32) []Aux { - off := r.AuxOff(i, 0) - n := r.NAux(i) - return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n] -} - -// DataOff returns the offset of the i-th symbol's data. -func (r *Reader) DataOff(i uint32) uint32 { - dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 - return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff) -} - -// DataSize returns the size of the i-th symbol's data. -func (r *Reader) DataSize(i uint32) int { - dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 - return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff)) -} - -// Data returns the i-th symbol's data. -func (r *Reader) Data(i uint32) []byte { - dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 - base := r.h.Offsets[BlkData] - off := r.uint32At(dataIdxOff) - end := r.uint32At(dataIdxOff + 4) - return r.BytesAt(base+off, int(end-off)) -} - -// AuxDataBase returns the base offset of the aux data block. -func (r *Reader) PcdataBase() uint32 { - return r.h.Offsets[BlkPcdata] -} - -// NRefName returns the number of referenced symbol names. -func (r *Reader) NRefName() int { - return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize -} - -// RefName returns a pointer to the i-th referenced symbol name. -// Note: here i is not a local symbol index, just a counter. -func (r *Reader) RefName(i int) *RefName { - off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize) - return (*RefName)(unsafe.Pointer(&r.b[off])) -} - -// ReadOnly returns whether r.BytesAt returns read-only bytes. -func (r *Reader) ReadOnly() bool { - return r.readonly -} - -// Flags returns the flag bits read from the object file header. -func (r *Reader) Flags() uint32 { - return r.h.Flags -} - -func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 } -func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 } -func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 } diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go deleted file mode 100644 index a439da36a..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type ABI"; DO NOT EDIT. - -package obj - -import "strconv" - -const _ABI_name = "ABI0ABIInternalABICount" - -var _ABI_index = [...]uint8{0, 4, 15, 23} - -func (i ABI) String() string { - if i >= ABI(len(_ABI_index)-1) { - return "ABI(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _ABI_name[_ABI_index[i]:_ABI_index[i+1]] -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go deleted file mode 100644 index 71f0dd97a..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type AddrType"; DO NOT EDIT. - -package obj - -import "strconv" - -const _AddrType_name = "TYPE_NONETYPE_BRANCHTYPE_TEXTSIZETYPE_MEMTYPE_CONSTTYPE_FCONSTTYPE_SCONSTTYPE_REGTYPE_ADDRTYPE_SHIFTTYPE_REGREGTYPE_REGREG2TYPE_INDIRTYPE_REGLIST" - -var _AddrType_index = [...]uint8{0, 9, 20, 33, 41, 51, 62, 73, 81, 90, 100, 111, 123, 133, 145} - -func (i AddrType) String() string { - if i >= AddrType(len(_AddrType_index)-1) { - return "AddrType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _AddrType_name[_AddrType_index[i]:_AddrType_index[i+1]] -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go deleted file mode 100644 index 8f8b8dbc4..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go +++ /dev/null @@ -1,410 +0,0 @@ -// Inferno utils/5c/5.out.h -// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/5.out.h -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package arm - -import "github.com/twitchyliquid64/golang-asm/obj" - -//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p arm - -const ( - NSNAME = 8 - NSYM = 50 - NREG = 16 -) - -/* -1 disables use of REGARG */ -const ( - REGARG = -1 -) - -const ( - REG_R0 = obj.RBaseARM + iota // must be 16-aligned - REG_R1 - REG_R2 - REG_R3 - REG_R4 - REG_R5 - REG_R6 - REG_R7 - REG_R8 - REG_R9 - REG_R10 - REG_R11 - REG_R12 - REG_R13 - REG_R14 - REG_R15 - - REG_F0 // must be 16-aligned - REG_F1 - REG_F2 - REG_F3 - REG_F4 - REG_F5 - REG_F6 - REG_F7 - REG_F8 - REG_F9 - REG_F10 - REG_F11 - REG_F12 - REG_F13 - REG_F14 - REG_F15 - - REG_FPSR // must be 2-aligned - REG_FPCR - - REG_CPSR // must be 2-aligned - REG_SPSR - - REGRET = REG_R0 - /* compiler allocates R1 up as temps */ - /* compiler allocates register variables R3 up */ - /* compiler allocates external registers R10 down */ - REGEXT = REG_R10 - /* these two registers are declared in runtime.h */ - REGG = REGEXT - 0 - REGM = REGEXT - 1 - - REGCTXT = REG_R7 - REGTMP = REG_R11 - REGSP = REG_R13 - REGLINK = REG_R14 - REGPC = REG_R15 - - NFREG = 16 - /* compiler allocates register variables F0 up */ - /* compiler allocates external registers F7 down */ - FREGRET = REG_F0 - FREGEXT = REG_F7 - FREGTMP = REG_F15 -) - -// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf -var ARMDWARFRegisters = map[int16]int16{} - -func init() { - // f assigns dwarfregisters[from:to] = (base):(step*(to-from)+base) - f := func(from, to, base, step int16) { - for r := int16(from); r <= to; r++ { - ARMDWARFRegisters[r] = step*(r-from) + base - } - } - f(REG_R0, REG_R15, 0, 1) - f(REG_F0, REG_F15, 64, 2) // Use d0 through D15, aka S0, S2, ..., S30 -} - -// Special registers, after subtracting obj.RBaseARM, bit 9 indicates -// a special register and the low bits select the register. -const ( - REG_SPECIAL = obj.RBaseARM + 1<<9 + iota - REG_MB_SY - REG_MB_ST - REG_MB_ISH - REG_MB_ISHST - REG_MB_NSH - REG_MB_NSHST - REG_MB_OSH - REG_MB_OSHST - - MAXREG -) - -const ( - C_NONE = iota - C_REG - C_REGREG - C_REGREG2 - C_REGLIST - C_SHIFT /* register shift R>>x */ - C_SHIFTADDR /* memory address with shifted offset R>>x(R) */ - C_FREG - C_PSR - C_FCR - C_SPR /* REG_MB_SY */ - - C_RCON /* 0xff rotated */ - C_NCON /* ~RCON */ - C_RCON2A /* OR of two disjoint C_RCON constants */ - C_RCON2S /* subtraction of two disjoint C_RCON constants */ - C_SCON /* 0xffff */ - C_LCON - C_LCONADDR - C_ZFCON - C_SFCON - C_LFCON - - C_RACON - C_LACON - - C_SBRA - C_LBRA - - C_HAUTO /* halfword insn offset (-0xff to 0xff) */ - C_FAUTO /* float insn offset (0 to 0x3fc, word aligned) */ - C_HFAUTO /* both H and F */ - C_SAUTO /* -0xfff to 0xfff */ - C_LAUTO - - C_HOREG - C_FOREG - C_HFOREG - C_SOREG - C_ROREG - C_SROREG /* both nil and R */ - C_LOREG - - C_PC - C_SP - C_HREG - - C_ADDR /* reference to relocatable address */ - - // TLS "var" in local exec mode: will become a constant offset from - // thread local base that is ultimately chosen by the program linker. - C_TLS_LE - - // TLS "var" in initial exec mode: will become a memory address (chosen - // by the program linker) that the dynamic linker will fill with the - // offset from the thread local base. - C_TLS_IE - - C_TEXTSIZE - - C_GOK - - C_NCLASS /* must be the last */ -) - -const ( - AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota - AEOR - ASUB - ARSB - AADD - AADC - ASBC - ARSC - ATST - ATEQ - ACMP - ACMN - AORR - ABIC - - AMVN - - /* - * Do not reorder or fragment the conditional branch - * opcodes, or the predication code will break - */ - ABEQ - ABNE - ABCS - ABHS - ABCC - ABLO - ABMI - ABPL - ABVS - ABVC - ABHI - ABLS - ABGE - ABLT - ABGT - ABLE - - AMOVWD - AMOVWF - AMOVDW - AMOVFW - AMOVFD - AMOVDF - AMOVF - AMOVD - - ACMPF - ACMPD - AADDF - AADDD - ASUBF - ASUBD - AMULF - AMULD - ANMULF - ANMULD - AMULAF - AMULAD - ANMULAF - ANMULAD - AMULSF - AMULSD - ANMULSF - ANMULSD - AFMULAF - AFMULAD - AFNMULAF - AFNMULAD - AFMULSF - AFMULSD - AFNMULSF - AFNMULSD - ADIVF - ADIVD - ASQRTF - ASQRTD - AABSF - AABSD - ANEGF - ANEGD - - ASRL - ASRA - ASLL - AMULU - ADIVU - AMUL - AMMUL - ADIV - AMOD - AMODU - ADIVHW - ADIVUHW - - AMOVB - AMOVBS - AMOVBU - AMOVH - AMOVHS - AMOVHU - AMOVW - AMOVM - ASWPBU - ASWPW - - ARFE - ASWI - AMULA - AMULS - AMMULA - AMMULS - - AWORD - - AMULL - AMULAL - AMULLU - AMULALU - - ABX - ABXRET - ADWORD - - ALDREX - ASTREX - ALDREXD - ASTREXD - - ADMB - - APLD - - ACLZ - AREV - AREV16 - AREVSH - ARBIT - - AXTAB - AXTAH - AXTABU - AXTAHU - - ABFX - ABFXU - ABFC - ABFI - - AMULWT - AMULWB - AMULBB - AMULAWT - AMULAWB - AMULABB - - AMRC // MRC/MCR - - ALAST - - // aliases - AB = obj.AJMP - ABL = obj.ACALL -) - -/* scond byte */ -const ( - C_SCOND = (1 << 4) - 1 - C_SBIT = 1 << 4 - C_PBIT = 1 << 5 - C_WBIT = 1 << 6 - C_FBIT = 1 << 7 /* psr flags-only */ - C_UBIT = 1 << 7 /* up bit, unsigned bit */ - - // These constants are the ARM condition codes encodings, - // XORed with 14 so that C_SCOND_NONE has value 0, - // so that a zeroed Prog.scond means "always execute". - C_SCOND_XOR = 14 - - C_SCOND_EQ = 0 ^ C_SCOND_XOR - C_SCOND_NE = 1 ^ C_SCOND_XOR - C_SCOND_HS = 2 ^ C_SCOND_XOR - C_SCOND_LO = 3 ^ C_SCOND_XOR - C_SCOND_MI = 4 ^ C_SCOND_XOR - C_SCOND_PL = 5 ^ C_SCOND_XOR - C_SCOND_VS = 6 ^ C_SCOND_XOR - C_SCOND_VC = 7 ^ C_SCOND_XOR - C_SCOND_HI = 8 ^ C_SCOND_XOR - C_SCOND_LS = 9 ^ C_SCOND_XOR - C_SCOND_GE = 10 ^ C_SCOND_XOR - C_SCOND_LT = 11 ^ C_SCOND_XOR - C_SCOND_GT = 12 ^ C_SCOND_XOR - C_SCOND_LE = 13 ^ C_SCOND_XOR - C_SCOND_NONE = 14 ^ C_SCOND_XOR - C_SCOND_NV = 15 ^ C_SCOND_XOR - - /* D_SHIFT type */ - SHIFT_LL = 0 << 5 - SHIFT_LR = 1 << 5 - SHIFT_AR = 2 << 5 - SHIFT_RR = 3 << 5 -) diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go deleted file mode 100644 index 8a05133e9..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go +++ /dev/null @@ -1,144 +0,0 @@ -// Code generated by stringer -i a.out.go -o anames.go -p arm; DO NOT EDIT. - -package arm - -import "github.com/twitchyliquid64/golang-asm/obj" - -var Anames = []string{ - obj.A_ARCHSPECIFIC: "AND", - "EOR", - "SUB", - "RSB", - "ADD", - "ADC", - "SBC", - "RSC", - "TST", - "TEQ", - "CMP", - "CMN", - "ORR", - "BIC", - "MVN", - "BEQ", - "BNE", - "BCS", - "BHS", - "BCC", - "BLO", - "BMI", - "BPL", - "BVS", - "BVC", - "BHI", - "BLS", - "BGE", - "BLT", - "BGT", - "BLE", - "MOVWD", - "MOVWF", - "MOVDW", - "MOVFW", - "MOVFD", - "MOVDF", - "MOVF", - "MOVD", - "CMPF", - "CMPD", - "ADDF", - "ADDD", - "SUBF", - "SUBD", - "MULF", - "MULD", - "NMULF", - "NMULD", - "MULAF", - "MULAD", - "NMULAF", - "NMULAD", - "MULSF", - "MULSD", - "NMULSF", - "NMULSD", - "FMULAF", - "FMULAD", - "FNMULAF", - "FNMULAD", - "FMULSF", - "FMULSD", - "FNMULSF", - "FNMULSD", - "DIVF", - "DIVD", - "SQRTF", - "SQRTD", - "ABSF", - "ABSD", - "NEGF", - "NEGD", - "SRL", - "SRA", - "SLL", - "MULU", - "DIVU", - "MUL", - "MMUL", - "DIV", - "MOD", - "MODU", - "DIVHW", - "DIVUHW", - "MOVB", - "MOVBS", - "MOVBU", - "MOVH", - "MOVHS", - "MOVHU", - "MOVW", - "MOVM", - "SWPBU", - "SWPW", - "RFE", - "SWI", - "MULA", - "MULS", - "MMULA", - "MMULS", - "WORD", - "MULL", - "MULAL", - "MULLU", - "MULALU", - "BX", - "BXRET", - "DWORD", - "LDREX", - "STREX", - "LDREXD", - "STREXD", - "DMB", - "PLD", - "CLZ", - "REV", - "REV16", - "REVSH", - "RBIT", - "XTAB", - "XTAH", - "XTABU", - "XTAHU", - "BFX", - "BFXU", - "BFC", - "BFI", - "MULWT", - "MULWB", - "MULBB", - "MULAWT", - "MULAWB", - "MULABB", - "MRC", - "LAST", -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go deleted file mode 100644 index 78fcd55f7..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package arm - -var cnames5 = []string{ - "NONE", - "REG", - "REGREG", - "REGREG2", - "REGLIST", - "SHIFT", - "SHIFTADDR", - "FREG", - "PSR", - "FCR", - "SPR", - "RCON", - "NCON", - "RCON2A", - "RCON2S", - "SCON", - "LCON", - "LCONADDR", - "ZFCON", - "SFCON", - "LFCON", - "RACON", - "LACON", - "SBRA", - "LBRA", - "HAUTO", - "FAUTO", - "HFAUTO", - "SAUTO", - "LAUTO", - "HOREG", - "FOREG", - "HFOREG", - "SOREG", - "ROREG", - "SROREG", - "LOREG", - "PC", - "SP", - "HREG", - "ADDR", - "C_TLS_LE", - "C_TLS_IE", - "TEXTSIZE", - "GOK", - "NCLASS", - "SCOND = (1<<4)-1", - "SBIT = 1<<4", - "PBIT = 1<<5", - "WBIT = 1<<6", - "FBIT = 1<<7", - "UBIT = 1<<7", - "SCOND_XOR = 14", - "SCOND_EQ = 0 ^ C_SCOND_XOR", - "SCOND_NE = 1 ^ C_SCOND_XOR", - "SCOND_HS = 2 ^ C_SCOND_XOR", - "SCOND_LO = 3 ^ C_SCOND_XOR", - "SCOND_MI = 4 ^ C_SCOND_XOR", - "SCOND_PL = 5 ^ C_SCOND_XOR", - "SCOND_VS = 6 ^ C_SCOND_XOR", - "SCOND_VC = 7 ^ C_SCOND_XOR", - "SCOND_HI = 8 ^ C_SCOND_XOR", - "SCOND_LS = 9 ^ C_SCOND_XOR", - "SCOND_GE = 10 ^ C_SCOND_XOR", - "SCOND_LT = 11 ^ C_SCOND_XOR", - "SCOND_GT = 12 ^ C_SCOND_XOR", - "SCOND_LE = 13 ^ C_SCOND_XOR", - "SCOND_NONE = 14 ^ C_SCOND_XOR", - "SCOND_NV = 15 ^ C_SCOND_XOR", -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go deleted file mode 100644 index 924657fb3..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go +++ /dev/null @@ -1,3096 +0,0 @@ -// Inferno utils/5l/span.c -// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/span.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package arm - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/objabi" - "fmt" - "log" - "math" - "sort" -) - -// ctxt5 holds state while assembling a single function. -// Each function gets a fresh ctxt5. -// This allows for multiple functions to be safely concurrently assembled. -type ctxt5 struct { - ctxt *obj.Link - newprog obj.ProgAlloc - cursym *obj.LSym - printp *obj.Prog - blitrl *obj.Prog - elitrl *obj.Prog - autosize int64 - instoffset int64 - pc int64 - pool struct { - start uint32 - size uint32 - extra uint32 - } -} - -type Optab struct { - as obj.As - a1 uint8 - a2 int8 - a3 uint8 - type_ uint8 - size int8 - param int16 - flag int8 - pcrelsiz uint8 - scond uint8 // optional flags accepted by the instruction -} - -type Opcross [32][2][32]uint8 - -const ( - LFROM = 1 << 0 - LTO = 1 << 1 - LPOOL = 1 << 2 - LPCREL = 1 << 3 -) - -var optab = []Optab{ - /* struct Optab: - OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */ - {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0}, - {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, - {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0}, - {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, - {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0}, - {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0}, - {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0}, - {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, - {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0}, - {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT}, - {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0}, - {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, - {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0}, - {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, - {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored - {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0}, - {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0}, - {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0}, - {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0}, - {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0}, - {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT}, - {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT}, - {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT}, - {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT}, - {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0}, - {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0}, - {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, - {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, - {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0}, - {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0}, - {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, - {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0}, - {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, - {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0}, - {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0}, - {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0}, - {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0}, - {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0}, - {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0}, - {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0}, - {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0}, - {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, - {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0}, - {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0}, - {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0}, - {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0}, - {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, - {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, - {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT}, - {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT}, - {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0}, - {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0}, - {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0}, - {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0}, - {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT}, - {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3 - {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3 - {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0}, - {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0}, - {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT}, - {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0}, - {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0}, - {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT}, - {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0}, - {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0}, - {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0}, - {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0}, - {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0}, - {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0}, - {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0}, - {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0}, - {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0}, - {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, - {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, - {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0}, - {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0}, - {ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, - {ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, - {ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, - {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0}, - {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0}, - {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0}, - {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0}, - {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT}, - {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT}, - {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT}, - {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT}, - {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0}, - {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0}, - {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0}, - {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0}, - {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0}, - {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0}, - {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0}, - {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0}, - {AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT}, - {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0}, - {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0}, - {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0}, - {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, - {obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, // nop variants, see #40689 - {obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, - {obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, - {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL - {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL - {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0}, -} - -var mbOp = []struct { - reg int16 - enc uint32 -}{ - {REG_MB_SY, 15}, - {REG_MB_ST, 14}, - {REG_MB_ISH, 11}, - {REG_MB_ISHST, 10}, - {REG_MB_NSH, 7}, - {REG_MB_NSHST, 6}, - {REG_MB_OSH, 3}, - {REG_MB_OSHST, 2}, -} - -var oprange [ALAST & obj.AMask][]Optab - -var xcmp [C_GOK + 1][C_GOK + 1]bool - -var ( - deferreturn *obj.LSym - symdiv *obj.LSym - symdivu *obj.LSym - symmod *obj.LSym - symmodu *obj.LSym -) - -// Note about encoding: Prog.scond holds the condition encoding, -// but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0. -// The code that shifts the value << 28 has the responsibility -// for XORing with C_SCOND_XOR too. - -func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) { - if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 { - c.ctxt.Diag("invalid .S suffix: %v", p) - } - if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 { - c.ctxt.Diag("invalid .P suffix: %v", p) - } - if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 { - c.ctxt.Diag("invalid .W suffix: %v", p) - } - if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 { - c.ctxt.Diag("invalid .U suffix: %v", p) - } -} - -func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { - if ctxt.Retpoline { - ctxt.Diag("-spectre=ret not supported on arm") - ctxt.Retpoline = false // don't keep printing - } - - var p *obj.Prog - var op *obj.Prog - - p = cursym.Func.Text - if p == nil || p.Link == nil { // handle external functions and ELF section symbols - return - } - - if oprange[AAND&obj.AMask] == nil { - ctxt.Diag("arm ops not initialized, call arm.buildop first") - } - - c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4} - pc := int32(0) - - op = p - p = p.Link - var m int - var o *Optab - for ; p != nil || c.blitrl != nil; op, p = p, p.Link { - if p == nil { - if c.checkpool(op, pc) { - p = op - continue - } - - // can't happen: blitrl is not nil, but checkpool didn't flushpool - ctxt.Diag("internal inconsistency") - - break - } - - p.Pc = int64(pc) - o = c.oplook(p) - m = int(o.size) - - if m%4 != 0 || p.Pc%4 != 0 { - ctxt.Diag("!pc invalid: %v size=%d", p, m) - } - - // must check literal pool here in case p generates many instructions - if c.blitrl != nil { - // Emit the constant pool just before p if p - // would push us over the immediate size limit. - if c.checkpool(op, pc+int32(m)) { - // Back up to the instruction just - // before the pool and continue with - // the first instruction of the pool. - p = op - continue - } - } - - if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) { - ctxt.Diag("zero-width instruction\n%v", p) - continue - } - - switch o.flag & (LFROM | LTO | LPOOL) { - case LFROM: - c.addpool(p, &p.From) - - case LTO: - c.addpool(p, &p.To) - - case LPOOL: - if p.Scond&C_SCOND == C_SCOND_NONE { - c.flushpool(p, 0, 0) - } - } - - if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE { - c.flushpool(p, 0, 0) - } - - pc += int32(m) - } - - c.cursym.Size = int64(pc) - - /* - * if any procedure is large enough to - * generate a large SBRA branch, then - * generate extra passes putting branches - * around jmps to fix. this is rare. - */ - times := 0 - - var bflag int - var opc int32 - var out [6 + 3]uint32 - for { - bflag = 0 - pc = 0 - times++ - c.cursym.Func.Text.Pc = 0 // force re-layout the code. - for p = c.cursym.Func.Text; p != nil; p = p.Link { - o = c.oplook(p) - if int64(pc) > p.Pc { - p.Pc = int64(pc) - } - - /* very large branches - if(o->type == 6 && p->pcond) { - otxt = p->pcond->pc - c; - if(otxt < 0) - otxt = -otxt; - if(otxt >= (1L<<17) - 10) { - q = emallocz(sizeof(Prog)); - q->link = p->link; - p->link = q; - q->as = AB; - q->to.type = TYPE_BRANCH; - q->pcond = p->pcond; - p->pcond = q; - q = emallocz(sizeof(Prog)); - q->link = p->link; - p->link = q; - q->as = AB; - q->to.type = TYPE_BRANCH; - q->pcond = q->link->link; - bflag = 1; - } - } - */ - opc = int32(p.Pc) - m = int(o.size) - if p.Pc != int64(opc) { - bflag = 1 - } - - //print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times); - pc = int32(p.Pc + int64(m)) - - if m%4 != 0 || p.Pc%4 != 0 { - ctxt.Diag("pc invalid: %v size=%d", p, m) - } - - if m/4 > len(out) { - ctxt.Diag("instruction size too large: %d > %d", m/4, len(out)) - } - if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) { - if p.As == obj.ATEXT { - c.autosize = p.To.Offset + 4 - continue - } - - ctxt.Diag("zero-width instruction\n%v", p) - continue - } - } - - c.cursym.Size = int64(pc) - if bflag == 0 { - break - } - } - - if pc%4 != 0 { - ctxt.Diag("sym->size=%d, invalid", pc) - } - - /* - * lay out the code. all the pc-relative code references, - * even cross-function, are resolved now; - * only data references need to be relocated. - * with more work we could leave cross-function - * code references to be relocated too, and then - * perhaps we'd be able to parallelize the span loop above. - */ - - p = c.cursym.Func.Text - c.autosize = p.To.Offset + 4 - c.cursym.Grow(c.cursym.Size) - - bp := c.cursym.P - pc = int32(p.Pc) // even p->link might need extra padding - var v int - for p = p.Link; p != nil; p = p.Link { - c.pc = p.Pc - o = c.oplook(p) - opc = int32(p.Pc) - c.asmout(p, o, out[:]) - m = int(o.size) - - if m%4 != 0 || p.Pc%4 != 0 { - ctxt.Diag("final stage: pc invalid: %v size=%d", p, m) - } - - if int64(pc) > p.Pc { - ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p) - } - for int64(pc) != p.Pc { - // emit 0xe1a00000 (MOVW R0, R0) - bp[0] = 0x00 - bp = bp[1:] - - bp[0] = 0x00 - bp = bp[1:] - bp[0] = 0xa0 - bp = bp[1:] - bp[0] = 0xe1 - bp = bp[1:] - pc += 4 - } - - for i := 0; i < m/4; i++ { - v = int(out[i]) - bp[0] = byte(v) - bp = bp[1:] - bp[0] = byte(v >> 8) - bp = bp[1:] - bp[0] = byte(v >> 16) - bp = bp[1:] - bp[0] = byte(v >> 24) - bp = bp[1:] - } - - pc += int32(m) - } -} - -// checkpool flushes the literal pool when the first reference to -// it threatens to go out of range of a 12-bit PC-relative offset. -// -// nextpc is the tentative next PC at which the pool could be emitted. -// checkpool should be called *before* emitting the instruction that -// would cause the PC to reach nextpc. -// If nextpc is too far from the first pool reference, checkpool will -// flush the pool immediately after p. -// The caller should resume processing a p.Link. -func (c *ctxt5) checkpool(p *obj.Prog, nextpc int32) bool { - poolLast := nextpc - poolLast += 4 // the AB instruction to jump around the pool - poolLast += int32(c.pool.size) - 4 // the offset of the last pool entry - - refPC := int32(c.pool.start) // PC of the first pool reference - - v := poolLast - refPC - 8 // 12-bit PC-relative offset (see omvl) - - if c.pool.size >= 0xff0 || immaddr(v) == 0 { - return c.flushpool(p, 1, 0) - } else if p.Link == nil { - return c.flushpool(p, 2, 0) - } - return false -} - -func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool { - if c.blitrl != nil { - if skip != 0 { - if false && skip == 1 { - fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) - } - q := c.newprog() - q.As = AB - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(p.Link) - q.Link = c.blitrl - q.Pos = p.Pos - c.blitrl = q - } else if force == 0 && (p.Pc+int64(c.pool.size)-int64(c.pool.start) < 2048) { - return false - } - - // The line number for constant pool entries doesn't really matter. - // We set it to the line number of the preceding instruction so that - // there are no deltas to encode in the pc-line tables. - for q := c.blitrl; q != nil; q = q.Link { - q.Pos = p.Pos - } - - c.elitrl.Link = p.Link - p.Link = c.blitrl - - c.blitrl = nil /* BUG: should refer back to values until out-of-range */ - c.elitrl = nil - c.pool.size = 0 - c.pool.start = 0 - c.pool.extra = 0 - return true - } - - return false -} - -func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) { - t := c.newprog() - t.As = AWORD - - switch c.aclass(a) { - default: - t.To.Offset = a.Offset - t.To.Sym = a.Sym - t.To.Type = a.Type - t.To.Name = a.Name - - if c.ctxt.Flag_shared && t.To.Sym != nil { - t.Rel = p - } - - case C_SROREG, - C_LOREG, - C_ROREG, - C_FOREG, - C_SOREG, - C_HOREG, - C_FAUTO, - C_SAUTO, - C_LAUTO, - C_LACON: - t.To.Type = obj.TYPE_CONST - t.To.Offset = c.instoffset - } - - if t.Rel == nil { - for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ - if q.Rel == nil && q.To == t.To { - p.Pool = q - return - } - } - } - - q := c.newprog() - *q = *t - q.Pc = int64(c.pool.size) - - if c.blitrl == nil { - c.blitrl = q - c.pool.start = uint32(p.Pc) - } else { - c.elitrl.Link = q - } - c.elitrl = q - c.pool.size += 4 - - // Store the link to the pool entry in Pool. - p.Pool = q -} - -func (c *ctxt5) regoff(a *obj.Addr) int32 { - c.instoffset = 0 - c.aclass(a) - return int32(c.instoffset) -} - -func immrot(v uint32) int32 { - for i := 0; i < 16; i++ { - if v&^0xff == 0 { - return int32(uint32(int32(i)<<8) | v | 1<<25) - } - v = v<<2 | v>>30 - } - - return 0 -} - -// immrot2a returns bits encoding the immediate constant fields of two instructions, -// such that the encoded constants x, y satisfy x|y==v, x&y==0. -// Returns 0,0 if no such decomposition of v exists. -func immrot2a(v uint32) (uint32, uint32) { - for i := uint(1); i < 32; i++ { - m := uint32(1<= 0 && v <= 0xfff { - return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */ - } - if v >= -0xfff && v < 0 { - return -v&0xfff | 1<<24 /* pre indexing */ - } - return 0 -} - -func immfloat(v int32) bool { - return v&0xC03 == 0 /* offset will fit in floating-point load/store */ -} - -func immhalf(v int32) bool { - if v >= 0 && v <= 0xff { - return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */ - } - if v >= -0xff && v < 0 { - return -v&0xff|1<<24 != 0 /* pre indexing */ - } - return false -} - -func (c *ctxt5) aclass(a *obj.Addr) int { - switch a.Type { - case obj.TYPE_NONE: - return C_NONE - - case obj.TYPE_REG: - c.instoffset = 0 - if REG_R0 <= a.Reg && a.Reg <= REG_R15 { - return C_REG - } - if REG_F0 <= a.Reg && a.Reg <= REG_F15 { - return C_FREG - } - if a.Reg == REG_FPSR || a.Reg == REG_FPCR { - return C_FCR - } - if a.Reg == REG_CPSR || a.Reg == REG_SPSR { - return C_PSR - } - if a.Reg >= REG_SPECIAL { - return C_SPR - } - return C_GOK - - case obj.TYPE_REGREG: - return C_REGREG - - case obj.TYPE_REGREG2: - return C_REGREG2 - - case obj.TYPE_REGLIST: - return C_REGLIST - - case obj.TYPE_SHIFT: - if a.Reg == 0 { - // register shift R>>i - return C_SHIFT - } else { - // memory address with shifted offset R>>i(R) - return C_SHIFTADDR - } - - case obj.TYPE_MEM: - switch a.Name { - case obj.NAME_EXTERN, - obj.NAME_GOTREF, - obj.NAME_STATIC: - if a.Sym == nil || a.Sym.Name == "" { - fmt.Printf("null sym external\n") - return C_GOK - } - - c.instoffset = 0 // s.b. unused but just in case - if a.Sym.Type == objabi.STLSBSS { - if c.ctxt.Flag_shared { - return C_TLS_IE - } else { - return C_TLS_LE - } - } - - return C_ADDR - - case obj.NAME_AUTO: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-SP. - a.Reg = obj.REG_NONE - } - c.instoffset = c.autosize + a.Offset - if t := immaddr(int32(c.instoffset)); t != 0 { - if immhalf(int32(c.instoffset)) { - if immfloat(t) { - return C_HFAUTO - } - return C_HAUTO - } - - if immfloat(t) { - return C_FAUTO - } - return C_SAUTO - } - - return C_LAUTO - - case obj.NAME_PARAM: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-FP. - a.Reg = obj.REG_NONE - } - c.instoffset = c.autosize + a.Offset + 4 - if t := immaddr(int32(c.instoffset)); t != 0 { - if immhalf(int32(c.instoffset)) { - if immfloat(t) { - return C_HFAUTO - } - return C_HAUTO - } - - if immfloat(t) { - return C_FAUTO - } - return C_SAUTO - } - - return C_LAUTO - - case obj.NAME_NONE: - c.instoffset = a.Offset - if t := immaddr(int32(c.instoffset)); t != 0 { - if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */ - if immfloat(t) { - return C_HFOREG - } - return C_HOREG - } - - if immfloat(t) { - return C_FOREG /* n.b. that it will also satisfy immrot */ - } - if immrot(uint32(c.instoffset)) != 0 { - return C_SROREG - } - if immhalf(int32(c.instoffset)) { - return C_HOREG - } - return C_SOREG - } - - if immrot(uint32(c.instoffset)) != 0 { - return C_ROREG - } - return C_LOREG - } - - return C_GOK - - case obj.TYPE_FCONST: - if c.chipzero5(a.Val.(float64)) >= 0 { - return C_ZFCON - } - if c.chipfloat5(a.Val.(float64)) >= 0 { - return C_SFCON - } - return C_LFCON - - case obj.TYPE_TEXTSIZE: - return C_TEXTSIZE - - case obj.TYPE_CONST, - obj.TYPE_ADDR: - switch a.Name { - case obj.NAME_NONE: - c.instoffset = a.Offset - if a.Reg != 0 { - return c.aconsize() - } - - if immrot(uint32(c.instoffset)) != 0 { - return C_RCON - } - if immrot(^uint32(c.instoffset)) != 0 { - return C_NCON - } - if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 { - return C_SCON - } - if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 { - return C_RCON2A - } - if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 { - return C_RCON2S - } - return C_LCON - - case obj.NAME_EXTERN, - obj.NAME_GOTREF, - obj.NAME_STATIC: - s := a.Sym - if s == nil { - break - } - c.instoffset = 0 // s.b. unused but just in case - return C_LCONADDR - - case obj.NAME_AUTO: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-SP. - a.Reg = obj.REG_NONE - } - c.instoffset = c.autosize + a.Offset - return c.aconsize() - - case obj.NAME_PARAM: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-FP. - a.Reg = obj.REG_NONE - } - c.instoffset = c.autosize + a.Offset + 4 - return c.aconsize() - } - - return C_GOK - - case obj.TYPE_BRANCH: - return C_SBRA - } - - return C_GOK -} - -func (c *ctxt5) aconsize() int { - if immrot(uint32(c.instoffset)) != 0 { - return C_RACON - } - if immrot(uint32(-c.instoffset)) != 0 { - return C_RACON - } - return C_LACON -} - -func (c *ctxt5) oplook(p *obj.Prog) *Optab { - a1 := int(p.Optab) - if a1 != 0 { - return &optab[a1-1] - } - a1 = int(p.From.Class) - if a1 == 0 { - a1 = c.aclass(&p.From) + 1 - p.From.Class = int8(a1) - } - - a1-- - a3 := int(p.To.Class) - if a3 == 0 { - a3 = c.aclass(&p.To) + 1 - p.To.Class = int8(a3) - } - - a3-- - a2 := C_NONE - if p.Reg != 0 { - switch { - case REG_F0 <= p.Reg && p.Reg <= REG_F15: - a2 = C_FREG - case REG_R0 <= p.Reg && p.Reg <= REG_R15: - a2 = C_REG - default: - c.ctxt.Diag("invalid register in %v", p) - } - } - - // check illegal base register - switch a1 { - case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR: - if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg { - c.ctxt.Diag("illegal base register: %v", p) - } - default: - } - switch a3 { - case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR: - if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg { - c.ctxt.Diag("illegal base register: %v", p) - } - default: - } - - // If current instruction has a .S suffix (flags update), - // we must use the constant pool instead of splitting it. - if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 { - a1 = C_LCON - } - if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 { - a3 = C_LCON - } - - if false { /*debug['O']*/ - fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3)) - fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) - } - - ops := oprange[p.As&obj.AMask] - c1 := &xcmp[a1] - c3 := &xcmp[a3] - for i := range ops { - op := &ops[i] - if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] { - p.Optab = uint16(cap(optab) - cap(ops) + i + 1) - checkSuffix(c, p, op) - return op - } - } - - c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name) - if ops == nil { - ops = optab - } - return &ops[0] -} - -func cmp(a int, b int) bool { - if a == b { - return true - } - switch a { - case C_LCON: - if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S { - return true - } - - case C_LACON: - if b == C_RACON { - return true - } - - case C_LFCON: - if b == C_ZFCON || b == C_SFCON { - return true - } - - case C_HFAUTO: - return b == C_HAUTO || b == C_FAUTO - - case C_FAUTO, C_HAUTO: - return b == C_HFAUTO - - case C_SAUTO: - return cmp(C_HFAUTO, b) - - case C_LAUTO: - return cmp(C_SAUTO, b) - - case C_HFOREG: - return b == C_HOREG || b == C_FOREG - - case C_FOREG, C_HOREG: - return b == C_HFOREG - - case C_SROREG: - return cmp(C_SOREG, b) || cmp(C_ROREG, b) - - case C_SOREG, C_ROREG: - return b == C_SROREG || cmp(C_HFOREG, b) - - case C_LOREG: - return cmp(C_SROREG, b) - - case C_LBRA: - if b == C_SBRA { - return true - } - - case C_HREG: - return cmp(C_SP, b) || cmp(C_PC, b) - } - - return false -} - -type ocmp []Optab - -func (x ocmp) Len() int { - return len(x) -} - -func (x ocmp) Swap(i, j int) { - x[i], x[j] = x[j], x[i] -} - -func (x ocmp) Less(i, j int) bool { - p1 := &x[i] - p2 := &x[j] - n := int(p1.as) - int(p2.as) - if n != 0 { - return n < 0 - } - n = int(p1.a1) - int(p2.a1) - if n != 0 { - return n < 0 - } - n = int(p1.a2) - int(p2.a2) - if n != 0 { - return n < 0 - } - n = int(p1.a3) - int(p2.a3) - if n != 0 { - return n < 0 - } - return false -} - -func opset(a, b0 obj.As) { - oprange[a&obj.AMask] = oprange[b0] -} - -func buildop(ctxt *obj.Link) { - if oprange[AAND&obj.AMask] != nil { - // Already initialized; stop now. - // This happens in the cmd/asm tests, - // each of which re-initializes the arch. - return - } - - deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) - - symdiv = ctxt.Lookup("runtime._div") - symdivu = ctxt.Lookup("runtime._divu") - symmod = ctxt.Lookup("runtime._mod") - symmodu = ctxt.Lookup("runtime._modu") - - var n int - - for i := 0; i < C_GOK; i++ { - for n = 0; n < C_GOK; n++ { - if cmp(n, i) { - xcmp[i][n] = true - } - } - } - for n = 0; optab[n].as != obj.AXXX; n++ { - if optab[n].flag&LPCREL != 0 { - if ctxt.Flag_shared { - optab[n].size += int8(optab[n].pcrelsiz) - } else { - optab[n].flag &^= LPCREL - } - } - } - - sort.Sort(ocmp(optab[:n])) - for i := 0; i < n; i++ { - r := optab[i].as - r0 := r & obj.AMask - start := i - for optab[i].as == r { - i++ - } - oprange[r0] = optab[start:i] - i-- - - switch r { - default: - ctxt.Diag("unknown op in build: %v", r) - ctxt.DiagFlush() - log.Fatalf("bad code") - - case AADD: - opset(ASUB, r0) - opset(ARSB, r0) - opset(AADC, r0) - opset(ASBC, r0) - opset(ARSC, r0) - - case AORR: - opset(AEOR, r0) - opset(ABIC, r0) - - case ACMP: - opset(ATEQ, r0) - opset(ACMN, r0) - opset(ATST, r0) - - case AMVN: - break - - case ABEQ: - opset(ABNE, r0) - opset(ABCS, r0) - opset(ABHS, r0) - opset(ABCC, r0) - opset(ABLO, r0) - opset(ABMI, r0) - opset(ABPL, r0) - opset(ABVS, r0) - opset(ABVC, r0) - opset(ABHI, r0) - opset(ABLS, r0) - opset(ABGE, r0) - opset(ABLT, r0) - opset(ABGT, r0) - opset(ABLE, r0) - - case ASLL: - opset(ASRL, r0) - opset(ASRA, r0) - - case AMUL: - opset(AMULU, r0) - - case ADIV: - opset(AMOD, r0) - opset(AMODU, r0) - opset(ADIVU, r0) - - case ADIVHW: - opset(ADIVUHW, r0) - - case AMOVW, - AMOVB, - AMOVBS, - AMOVBU, - AMOVH, - AMOVHS, - AMOVHU: - break - - case ASWPW: - opset(ASWPBU, r0) - - case AB, - ABL, - ABX, - ABXRET, - obj.ADUFFZERO, - obj.ADUFFCOPY, - ASWI, - AWORD, - AMOVM, - ARFE, - obj.ATEXT: - break - - case AADDF: - opset(AADDD, r0) - opset(ASUBF, r0) - opset(ASUBD, r0) - opset(AMULF, r0) - opset(AMULD, r0) - opset(ANMULF, r0) - opset(ANMULD, r0) - opset(AMULAF, r0) - opset(AMULAD, r0) - opset(AMULSF, r0) - opset(AMULSD, r0) - opset(ANMULAF, r0) - opset(ANMULAD, r0) - opset(ANMULSF, r0) - opset(ANMULSD, r0) - opset(AFMULAF, r0) - opset(AFMULAD, r0) - opset(AFMULSF, r0) - opset(AFMULSD, r0) - opset(AFNMULAF, r0) - opset(AFNMULAD, r0) - opset(AFNMULSF, r0) - opset(AFNMULSD, r0) - opset(ADIVF, r0) - opset(ADIVD, r0) - - case ANEGF: - opset(ANEGD, r0) - opset(ASQRTF, r0) - opset(ASQRTD, r0) - opset(AMOVFD, r0) - opset(AMOVDF, r0) - opset(AABSF, r0) - opset(AABSD, r0) - - case ACMPF: - opset(ACMPD, r0) - - case AMOVF: - opset(AMOVD, r0) - - case AMOVFW: - opset(AMOVDW, r0) - - case AMOVWF: - opset(AMOVWD, r0) - - case AMULL: - opset(AMULAL, r0) - opset(AMULLU, r0) - opset(AMULALU, r0) - - case AMULWT: - opset(AMULWB, r0) - opset(AMULBB, r0) - opset(AMMUL, r0) - - case AMULAWT: - opset(AMULAWB, r0) - opset(AMULABB, r0) - opset(AMULS, r0) - opset(AMMULA, r0) - opset(AMMULS, r0) - - case ABFX: - opset(ABFXU, r0) - opset(ABFC, r0) - opset(ABFI, r0) - - case ACLZ: - opset(AREV, r0) - opset(AREV16, r0) - opset(AREVSH, r0) - opset(ARBIT, r0) - - case AXTAB: - opset(AXTAH, r0) - opset(AXTABU, r0) - opset(AXTAHU, r0) - - case ALDREX, - ASTREX, - ALDREXD, - ASTREXD, - ADMB, - APLD, - AAND, - AMULA, - obj.AUNDEF, - obj.AFUNCDATA, - obj.APCDATA, - obj.ANOP: - break - } - } -} - -func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) { - c.printp = p - o1 := uint32(0) - o2 := uint32(0) - o3 := uint32(0) - o4 := uint32(0) - o5 := uint32(0) - o6 := uint32(0) - if false { /*debug['P']*/ - fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) - } - switch o.type_ { - default: - c.ctxt.Diag("%v: unknown asm %d", p, o.type_) - - case 0: /* pseudo ops */ - if false { /*debug['G']*/ - fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name) - } - - case 1: /* op R,[R],R */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = 0 - } - if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN { - r = 0 - } else if r == 0 { - r = rt - } - o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - - case 2: /* movbu $I,[R],R */ - c.aclass(&p.From) - - o1 = c.oprrr(p, p.As, int(p.Scond)) - o1 |= uint32(immrot(uint32(c.instoffset))) - rt := int(p.To.Reg) - r := int(p.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = 0 - } - if p.As == AMOVW || p.As == AMVN { - r = 0 - } else if r == 0 { - r = rt - } - o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - - case 106: /* op $I,R,R where I can be decomposed into 2 immediates */ - c.aclass(&p.From) - r := int(p.Reg) - rt := int(p.To.Reg) - if r == 0 { - r = rt - } - x, y := immrot2a(uint32(c.instoffset)) - var as2 obj.As - switch p.As { - case AADD, ASUB, AORR, AEOR, ABIC: - as2 = p.As // ADD, SUB, ORR, EOR, BIC - case ARSB: - as2 = AADD // RSB -> RSB/ADD pair - case AADC: - as2 = AADD // ADC -> ADC/ADD pair - case ASBC: - as2 = ASUB // SBC -> SBC/SUB pair - case ARSC: - as2 = AADD // RSC -> RSC/ADD pair - default: - c.ctxt.Diag("unknown second op for %v", p) - } - o1 = c.oprrr(p, p.As, int(p.Scond)) - o2 = c.oprrr(p, as2, int(p.Scond)) - o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 - o1 |= x - o2 |= y - - case 107: /* op $I,R,R where I can be decomposed into 2 immediates */ - c.aclass(&p.From) - r := int(p.Reg) - rt := int(p.To.Reg) - if r == 0 { - r = rt - } - y, x := immrot2s(uint32(c.instoffset)) - var as2 obj.As - switch p.As { - case AADD: - as2 = ASUB // ADD -> ADD/SUB pair - case ASUB: - as2 = AADD // SUB -> SUB/ADD pair - case ARSB: - as2 = ASUB // RSB -> RSB/SUB pair - case AADC: - as2 = ASUB // ADC -> ADC/SUB pair - case ASBC: - as2 = AADD // SBC -> SBC/ADD pair - case ARSC: - as2 = ASUB // RSC -> RSC/SUB pair - default: - c.ctxt.Diag("unknown second op for %v", p) - } - o1 = c.oprrr(p, p.As, int(p.Scond)) - o2 = c.oprrr(p, as2, int(p.Scond)) - o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 - o1 |= y - o2 |= x - - case 3: /* add R<<[IR],[R],R */ - o1 = c.mov(p) - - case 4: /* MOVW $off(R), R -> add $off,[R],R */ - c.aclass(&p.From) - if c.instoffset < 0 { - o1 = c.oprrr(p, ASUB, int(p.Scond)) - o1 |= uint32(immrot(uint32(-c.instoffset))) - } else { - o1 = c.oprrr(p, AADD, int(p.Scond)) - o1 |= uint32(immrot(uint32(c.instoffset))) - } - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o1 |= (uint32(r) & 15) << 16 - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 5: /* bra s */ - o1 = c.opbra(p, p.As, int(p.Scond)) - - v := int32(-8) - if p.To.Sym != nil { - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - v += int32(p.To.Offset) - rel.Add = int64(o1) | (int64(v)>>2)&0xffffff - rel.Type = objabi.R_CALLARM - break - } - - if p.To.Target() != nil { - v = int32((p.To.Target().Pc - c.pc) - 8) - } - o1 |= (uint32(v) >> 2) & 0xffffff - - case 6: /* b ,O(R) -> add $O,R,PC */ - c.aclass(&p.To) - - o1 = c.oprrr(p, AADD, int(p.Scond)) - o1 |= uint32(immrot(uint32(c.instoffset))) - o1 |= (uint32(p.To.Reg) & 15) << 16 - o1 |= (REGPC & 15) << 12 - - case 7: /* bl (R) -> blx R */ - c.aclass(&p.To) - - if c.instoffset != 0 { - c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset) - } - o1 = c.oprrr(p, ABL, int(p.Scond)) - o1 |= (uint32(p.To.Reg) & 15) << 0 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 0 - rel.Type = objabi.R_CALLIND - - case 8: /* sll $c,[R],R -> mov (R<<$c),R */ - c.aclass(&p.From) - - o1 = c.oprrr(p, p.As, int(p.Scond)) - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - o1 |= (uint32(r) & 15) << 0 - o1 |= uint32((c.instoffset & 31) << 7) - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 9: /* sll R,[R],R -> mov (R< 31 || width <= 0 || (lsb+width) > 32 { - c.ctxt.Diag("%v: wrong width or LSB", p) - } - switch p.As { - case ABFX, ABFXU: // (width-1) is encoded - o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16 - case ABFC, ABFI: // MSB is encoded - o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16 - default: - c.ctxt.Diag("illegal combination: %v", p) - } - - case 20: /* mov/movb/movbu R,O(R) */ - c.aclass(&p.To) - - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) - - case 21: /* mov/movbu O(R),R -> lr */ - c.aclass(&p.From) - - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) - if p.As != AMOVW { - o1 |= 1 << 22 - } - - case 22: /* XTAB R@>i, [R], R */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - switch p.From.Offset &^ 0xf { - // only 0/8/16/24 bits rotation is accepted - case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7: - o1 |= uint32(p.From.Offset) & 0xc0f - default: - c.ctxt.Diag("illegal shift: %v", p) - } - rt := p.To.Reg - r := p.Reg - if r == 0 { - r = rt - } - o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16 - - case 23: /* MOVW/MOVB/MOVH R@>i, R */ - switch p.As { - case AMOVW: - o1 = c.mov(p) - case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH: - o1 = c.movxt(p) - default: - c.ctxt.Diag("illegal combination: %v", p) - } - - case 30: /* mov/movb/movbu R,L(R) */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) - if p.As != AMOVW { - o2 |= 1 << 22 - } - - case 31: /* mov/movbu L(R),R -> lr[b] */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) - if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { - o2 |= 1 << 22 - } - - case 34: /* mov $lacon,R */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - - o2 = c.oprrr(p, AADD, int(p.Scond)) - o2 |= REGTMP & 15 - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o2 |= (uint32(r) & 15) << 16 - if p.To.Type != obj.TYPE_NONE { - o2 |= (uint32(p.To.Reg) & 15) << 12 - } - - case 35: /* mov PSR,R */ - o1 = 2<<23 | 0xf<<16 | 0<<0 - - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= (uint32(p.From.Reg) & 1) << 22 - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 36: /* mov R,PSR */ - o1 = 2<<23 | 0x2cf<<12 | 0<<4 - - if p.Scond&C_FBIT != 0 { - o1 ^= 0x010 << 12 - } - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= (uint32(p.To.Reg) & 1) << 22 - o1 |= (uint32(p.From.Reg) & 15) << 0 - - case 37: /* mov $con,PSR */ - c.aclass(&p.From) - - o1 = 2<<23 | 0x2cf<<12 | 0<<4 - if p.Scond&C_FBIT != 0 { - o1 ^= 0x010 << 12 - } - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= uint32(immrot(uint32(c.instoffset))) - o1 |= (uint32(p.To.Reg) & 1) << 22 - o1 |= (uint32(p.From.Reg) & 15) << 0 - - case 38, 39: - switch o.type_ { - case 38: /* movm $con,oreg -> stm */ - o1 = 0x4 << 25 - - o1 |= uint32(p.From.Offset & 0xffff) - o1 |= (uint32(p.To.Reg) & 15) << 16 - c.aclass(&p.To) - - case 39: /* movm oreg,$con -> ldm */ - o1 = 0x4<<25 | 1<<20 - - o1 |= uint32(p.To.Offset & 0xffff) - o1 |= (uint32(p.From.Reg) & 15) << 16 - c.aclass(&p.From) - } - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in MOVM; %v", p) - } - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - if p.Scond&C_PBIT != 0 { - o1 |= 1 << 24 - } - if p.Scond&C_UBIT != 0 { - o1 |= 1 << 23 - } - if p.Scond&C_WBIT != 0 { - o1 |= 1 << 21 - } - - case 40: /* swp oreg,reg,reg */ - c.aclass(&p.From) - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in SWP") - } - o1 = 0x2<<23 | 0x9<<4 - if p.As != ASWPW { - o1 |= 1 << 22 - } - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.Reg) & 15) << 0 - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */ - o1 = 0xe8fd8000 - - case 50: /* floating point store */ - v := c.regoff(&p.To) - - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p) - - case 51: /* floating point load */ - v := c.regoff(&p.From) - - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20 - - case 52: /* floating point store, int32 offset UGLY */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 - o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) - - case 53: /* floating point load, int32 offset UGLY */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 - o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 - - case 54: /* floating point arith */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if r == 0 { - switch p.As { - case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD, - AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD: - c.ctxt.Diag("illegal combination: %v", p) - default: - r = rt - } - } - - o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - - case 55: /* negf freg, freg */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - - o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12 - - case 56: /* move to FP[CS]R */ - o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4 - - o1 |= (uint32(p.From.Reg) & 15) << 12 - - case 57: /* move from FP[CS]R */ - o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4 - - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 58: /* movbu R,R */ - o1 = c.oprrr(p, AAND, int(p.Scond)) - - o1 |= uint32(immrot(0xff)) - rt := int(p.To.Reg) - r := int(p.From.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = 0 - } - if r == 0 { - r = rt - } - o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - - case 59: /* movw/bu R< ldr indexed */ - if p.From.Reg == 0 { - c.ctxt.Diag("source operand is not a memory address: %v", p) - break - } - if p.From.Offset&(1<<4) != 0 { - c.ctxt.Diag("bad shift in LDR") - break - } - o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) - if p.As == AMOVBU { - o1 |= 1 << 22 - } - - case 60: /* movb R(R),R -> ldrsb indexed */ - if p.From.Reg == 0 { - c.ctxt.Diag("source operand is not a memory address: %v", p) - break - } - if p.From.Offset&(^0xf) != 0 { - c.ctxt.Diag("bad shift: %v", p) - break - } - o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) - switch p.As { - case AMOVB, AMOVBS: - o1 ^= 1<<5 | 1<<6 - case AMOVH, AMOVHS: - o1 ^= 1 << 6 - default: - } - if p.Scond&C_UBIT != 0 { - o1 &^= 1 << 23 - } - - case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ - if p.To.Reg == 0 { - c.ctxt.Diag("MOV to shifter operand") - } - o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond)) - if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { - o1 |= 1 << 22 - } - - case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */ - if p.To.Reg == 0 { - c.ctxt.Diag("MOV to shifter operand") - } - if p.To.Offset&(^0xf) != 0 { - c.ctxt.Diag("bad shift: %v", p) - } - o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond)) - o1 ^= 1 << 20 - if p.Scond&C_UBIT != 0 { - o1 &^= 1 << 23 - } - - /* reloc ops */ - case 64: /* mov/movb/movbu R,addr */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond)) - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - case 65: /* mov/movbu addr,R */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond)) - if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { - o2 |= 1 << 22 - } - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - case 101: /* movw tlsvar,R, local exec*/ - o1 = c.omvl(p, &p.From, int(p.To.Reg)) - - case 102: /* movw tlsvar,R, initial exec*/ - o1 = c.omvl(p, &p.From, int(p.To.Reg)) - o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond)) - - case 103: /* word tlsvar, local exec */ - if p.To.Sym == nil { - c.ctxt.Diag("nil sym in tls %v", p) - } - if p.To.Offset != 0 { - c.ctxt.Diag("offset against tls var in %v", p) - } - // This case happens with words generated in the PC stream as part of - // the literal c.pool. - rel := obj.Addrel(c.cursym) - - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - rel.Type = objabi.R_TLS_LE - o1 = 0 - - case 104: /* word tlsvar, initial exec */ - if p.To.Sym == nil { - c.ctxt.Diag("nil sym in tls %v", p) - } - if p.To.Offset != 0 { - c.ctxt.Diag("offset against tls var in %v", p) - } - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - rel.Type = objabi.R_TLS_IE - rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz) - - case 68: /* floating point store -> ADDR */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - case 69: /* floating point load <- ADDR */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - /* ArmV4 ops: */ - case 70: /* movh/movhu R,O(R) -> strh */ - c.aclass(&p.To) - - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) - - case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ - c.aclass(&p.From) - - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) - if p.As == AMOVB || p.As == AMOVBS { - o1 ^= 1<<5 | 1<<6 - } else if p.As == AMOVH || p.As == AMOVHS { - o1 ^= (1 << 6) - } - - case 72: /* movh/movhu R,L(R) -> strh */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) - - case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) - if p.As == AMOVB || p.As == AMOVBS { - o2 ^= 1<<5 | 1<<6 - } else if p.As == AMOVH || p.As == AMOVHS { - o2 ^= (1 << 6) - } - - case 74: /* bx $I */ - c.ctxt.Diag("ABX $I") - - case 75: /* bx O(R) */ - c.aclass(&p.To) - - if c.instoffset != 0 { - c.ctxt.Diag("non-zero offset in ABX") - } - - /* - o1 = c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR - o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R - */ - // p->to.reg may be REGLINK - o1 = c.oprrr(p, AADD, int(p.Scond)) - - o1 |= uint32(immrot(uint32(c.instoffset))) - o1 |= (uint32(p.To.Reg) & 15) << 16 - o1 |= (REGTMP & 15) << 12 - o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR - o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp - - case 76: /* bx O(R) when returning from fn*/ - c.ctxt.Diag("ABXRET") - - case 77: /* ldrex oreg,reg */ - c.aclass(&p.From) - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in LDREX") - } - o1 = 0x19<<20 | 0xf9f - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 78: /* strex reg,oreg,reg */ - c.aclass(&p.From) - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in STREX") - } - if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg { - c.ctxt.Diag("cannot use same register as both source and destination: %v", p) - } - o1 = 0x18<<20 | 0xf90 - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.Reg) & 15) << 0 - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 80: /* fmov zfcon,freg */ - if p.As == AMOVD { - o1 = 0xeeb00b00 // VMOV imm 64 - o2 = c.oprrr(p, ASUBD, int(p.Scond)) - } else { - o1 = 0x0eb00a00 // VMOV imm 32 - o2 = c.oprrr(p, ASUBF, int(p.Scond)) - } - - v := int32(0x70) // 1.0 - r := (int(p.To.Reg) & 15) << 0 - - // movf $1.0, r - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - o1 |= (uint32(r) & 15) << 12 - o1 |= (uint32(v) & 0xf) << 0 - o1 |= (uint32(v) & 0xf0) << 12 - - // subf r,r,r - o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12 - - case 81: /* fmov sfcon,freg */ - o1 = 0x0eb00a00 // VMOV imm 32 - if p.As == AMOVD { - o1 = 0xeeb00b00 // VMOV imm 64 - } - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= (uint32(p.To.Reg) & 15) << 12 - v := int32(c.chipfloat5(p.From.Val.(float64))) - o1 |= (uint32(v) & 0xf) << 0 - o1 |= (uint32(v) & 0xf0) << 12 - - case 82: /* fcmp freg,freg, */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0 - o2 = 0x0ef1fa10 // VMRS R15 - o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 83: /* fcmp freg,, */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16 - o2 = 0x0ef1fa10 // VMRS R15 - o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 84: /* movfw freg,freg - truncate float-to-fix */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 0 - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 85: /* movwf freg,freg - fix-to-float */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 0 - o1 |= (uint32(p.To.Reg) & 15) << 12 - - // macro for movfw freg,FTMP; movw FTMP,reg - case 86: /* movfw freg,reg - truncate float-to-fix */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 0 - o1 |= (FREGTMP & 15) << 12 - o2 = c.oprrr(p, -AMOVFW, int(p.Scond)) - o2 |= (FREGTMP & 15) << 16 - o2 |= (uint32(p.To.Reg) & 15) << 12 - - // macro for movw reg,FTMP; movwf FTMP,freg - case 87: /* movwf reg,freg - fix-to-float */ - o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 12 - o1 |= (FREGTMP & 15) << 16 - o2 = c.oprrr(p, p.As, int(p.Scond)) - o2 |= (FREGTMP & 15) << 0 - o2 |= (uint32(p.To.Reg) & 15) << 12 - - case 88: /* movw reg,freg */ - o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 12 - o1 |= (uint32(p.To.Reg) & 15) << 16 - - case 89: /* movw freg,reg */ - o1 = c.oprrr(p, -AMOVFW, int(p.Scond)) - - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.To.Reg) & 15) << 12 - - case 91: /* ldrexd oreg,reg */ - c.aclass(&p.From) - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in LDREX") - } - o1 = 0x1b<<20 | 0xf9f - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 92: /* strexd reg,oreg,reg */ - c.aclass(&p.From) - - if c.instoffset != 0 { - c.ctxt.Diag("offset must be zero in STREX") - } - if p.Reg&1 != 0 { - c.ctxt.Diag("source register must be even in STREXD: %v", p) - } - if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 { - c.ctxt.Diag("cannot use same register as both source and destination: %v", p) - } - o1 = 0x1a<<20 | 0xf90 - o1 |= (uint32(p.From.Reg) & 15) << 16 - o1 |= (uint32(p.Reg) & 15) << 0 - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - - case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ - o1 = c.omvl(p, &p.From, REGTMP) - - if o1 == 0 { - break - } - o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond)) - if p.As == AMOVB || p.As == AMOVBS { - o2 ^= 1<<5 | 1<<6 - } else if p.As == AMOVH || p.As == AMOVHS { - o2 ^= (1 << 6) - } - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - case 94: /* movh/movhu R,addr -> strh */ - o1 = c.omvl(p, &p.To, REGTMP) - - if o1 == 0 { - break - } - o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond)) - if o.flag&LPCREL != 0 { - o3 = o2 - o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 - } - - case 95: /* PLD off(reg) */ - o1 = 0xf5d0f000 - - o1 |= (uint32(p.From.Reg) & 15) << 16 - if p.From.Offset < 0 { - o1 &^= (1 << 23) - o1 |= uint32((-p.From.Offset) & 0xfff) - } else { - o1 |= uint32(p.From.Offset & 0xfff) - } - - // This is supposed to be something that stops execution. - // It's not supposed to be reached, ever, but if it is, we'd - // like to be able to tell how we got there. Assemble as - // 0xf7fabcfd which is guaranteed to raise undefined instruction - // exception. - case 96: /* UNDEF */ - o1 = 0xf7fabcfd - - case 97: /* CLZ Rm, Rd */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.To.Reg) & 15) << 12 - o1 |= (uint32(p.From.Reg) & 15) << 0 - - case 98: /* MULW{T,B} Rs, Rm, Rd */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.To.Reg) & 15) << 16 - o1 |= (uint32(p.From.Reg) & 15) << 8 - o1 |= (uint32(p.Reg) & 15) << 0 - - case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - - o1 |= (uint32(p.To.Reg) & 15) << 16 - o1 |= (uint32(p.From.Reg) & 15) << 8 - o1 |= (uint32(p.Reg) & 15) << 0 - o1 |= uint32((p.To.Offset & 15) << 12) - - case 105: /* divhw r,[r,]r */ - o1 = c.oprrr(p, p.As, int(p.Scond)) - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if r == 0 { - r = rt - } - o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 - - case 110: /* dmb [mbop | $con] */ - o1 = 0xf57ff050 - mbop := uint32(0) - - switch c.aclass(&p.From) { - case C_SPR: - for _, f := range mbOp { - if f.reg == p.From.Reg { - mbop = f.enc - break - } - } - case C_RCON: - for _, f := range mbOp { - enc := uint32(c.instoffset) - if f.enc == enc { - mbop = enc - break - } - } - case C_NONE: - mbop = 0xf - } - - if mbop == 0 { - c.ctxt.Diag("illegal mb option:\n%v", p) - } - o1 |= mbop - } - - out[0] = o1 - out[1] = o2 - out[2] = o3 - out[3] = o4 - out[4] = o5 - out[5] = o6 -} - -func (c *ctxt5) movxt(p *obj.Prog) uint32 { - o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - switch p.As { - case AMOVB, AMOVBS: - o1 |= 0x6af<<16 | 0x7<<4 - case AMOVH, AMOVHS: - o1 |= 0x6bf<<16 | 0x7<<4 - case AMOVBU: - o1 |= 0x6ef<<16 | 0x7<<4 - case AMOVHU: - o1 |= 0x6ff<<16 | 0x7<<4 - default: - c.ctxt.Diag("illegal combination: %v", p) - } - switch p.From.Offset &^ 0xf { - // only 0/8/16/24 bits rotation is accepted - case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7: - o1 |= uint32(p.From.Offset) & 0xc0f - default: - c.ctxt.Diag("illegal shift: %v", p) - } - o1 |= (uint32(p.To.Reg) & 15) << 12 - return o1 -} - -func (c *ctxt5) mov(p *obj.Prog) uint32 { - c.aclass(&p.From) - o1 := c.oprrr(p, p.As, int(p.Scond)) - o1 |= uint32(p.From.Offset) - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = 0 - } - r := int(p.Reg) - if p.As == AMOVW || p.As == AMVN { - r = 0 - } else if r == 0 { - r = rt - } - o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 - return o1 -} - -func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { - o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 - if sc&C_SBIT != 0 { - o |= 1 << 20 - } - switch a { - case ADIVHW: - return o | 0x71<<20 | 0xf<<12 | 0x1<<4 - case ADIVUHW: - return o | 0x73<<20 | 0xf<<12 | 0x1<<4 - case AMMUL: - return o | 0x75<<20 | 0xf<<12 | 0x1<<4 - case AMULS: - return o | 0x6<<20 | 0x9<<4 - case AMMULA: - return o | 0x75<<20 | 0x1<<4 - case AMMULS: - return o | 0x75<<20 | 0xd<<4 - case AMULU, AMUL: - return o | 0x0<<21 | 0x9<<4 - case AMULA: - return o | 0x1<<21 | 0x9<<4 - case AMULLU: - return o | 0x4<<21 | 0x9<<4 - case AMULL: - return o | 0x6<<21 | 0x9<<4 - case AMULALU: - return o | 0x5<<21 | 0x9<<4 - case AMULAL: - return o | 0x7<<21 | 0x9<<4 - case AAND: - return o | 0x0<<21 - case AEOR: - return o | 0x1<<21 - case ASUB: - return o | 0x2<<21 - case ARSB: - return o | 0x3<<21 - case AADD: - return o | 0x4<<21 - case AADC: - return o | 0x5<<21 - case ASBC: - return o | 0x6<<21 - case ARSC: - return o | 0x7<<21 - case ATST: - return o | 0x8<<21 | 1<<20 - case ATEQ: - return o | 0x9<<21 | 1<<20 - case ACMP: - return o | 0xa<<21 | 1<<20 - case ACMN: - return o | 0xb<<21 | 1<<20 - case AORR: - return o | 0xc<<21 - - case AMOVB, AMOVH, AMOVW: - if sc&(C_PBIT|C_WBIT) != 0 { - c.ctxt.Diag("invalid .P/.W suffix: %v", p) - } - return o | 0xd<<21 - case ABIC: - return o | 0xe<<21 - case AMVN: - return o | 0xf<<21 - case ASLL: - return o | 0xd<<21 | 0<<5 - case ASRL: - return o | 0xd<<21 | 1<<5 - case ASRA: - return o | 0xd<<21 | 2<<5 - case ASWI: - return o | 0xf<<24 - - case AADDD: - return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4 - case AADDF: - return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4 - case ASUBD: - return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4 - case ASUBF: - return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4 - case AMULD: - return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4 - case AMULF: - return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4 - case ANMULD: - return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4 - case ANMULF: - return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4 - case AMULAD: - return o | 0xe<<24 | 0xb<<8 - case AMULAF: - return o | 0xe<<24 | 0xa<<8 - case AMULSD: - return o | 0xe<<24 | 0xb<<8 | 0x4<<4 - case AMULSF: - return o | 0xe<<24 | 0xa<<8 | 0x4<<4 - case ANMULAD: - return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4 - case ANMULAF: - return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4 - case ANMULSD: - return o | 0xe<<24 | 0x1<<20 | 0xb<<8 - case ANMULSF: - return o | 0xe<<24 | 0x1<<20 | 0xa<<8 - case AFMULAD: - return o | 0xe<<24 | 0xa<<20 | 0xb<<8 - case AFMULAF: - return o | 0xe<<24 | 0xa<<20 | 0xa<<8 - case AFMULSD: - return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4 - case AFMULSF: - return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4 - case AFNMULAD: - return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4 - case AFNMULAF: - return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4 - case AFNMULSD: - return o | 0xe<<24 | 0x9<<20 | 0xb<<8 - case AFNMULSF: - return o | 0xe<<24 | 0x9<<20 | 0xa<<8 - case ADIVD: - return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4 - case ADIVF: - return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4 - case ASQRTD: - return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4 - case ASQRTF: - return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4 - case AABSD: - return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4 - case AABSF: - return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4 - case ANEGD: - return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4 - case ANEGF: - return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4 - case ACMPD: - return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4 - case ACMPF: - return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4 - - case AMOVF: - return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4 - case AMOVD: - return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4 - - case AMOVDF: - return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof - case AMOVFD: - return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof - - case AMOVWF: - if sc&C_UBIT == 0 { - o |= 1 << 7 /* signed */ - } - return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double - - case AMOVWD: - if sc&C_UBIT == 0 { - o |= 1 << 7 /* signed */ - } - return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double - - case AMOVFW: - if sc&C_UBIT == 0 { - o |= 1 << 16 /* signed */ - } - return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc - - case AMOVDW: - if sc&C_UBIT == 0 { - o |= 1 << 16 /* signed */ - } - return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc - - case -AMOVWF: // copy WtoF - return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4 - - case -AMOVFW: // copy FtoW - return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4 - - case -ACMP: // cmp imm - return o | 0x3<<24 | 0x5<<20 - - case ABFX: - return o | 0x3d<<21 | 0x5<<4 - - case ABFXU: - return o | 0x3f<<21 | 0x5<<4 - - case ABFC: - return o | 0x3e<<21 | 0x1f - - case ABFI: - return o | 0x3e<<21 | 0x1<<4 - - case AXTAB: - return o | 0x6a<<20 | 0x7<<4 - - case AXTAH: - return o | 0x6b<<20 | 0x7<<4 - - case AXTABU: - return o | 0x6e<<20 | 0x7<<4 - - case AXTAHU: - return o | 0x6f<<20 | 0x7<<4 - - // CLZ doesn't support .nil - case ACLZ: - return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4 - - case AREV: - return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4 - - case AREV16: - return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4 - - case AREVSH: - return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4 - - case ARBIT: - return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4 - - case AMULWT: - return o&(0xf<<28) | 0x12<<20 | 0xe<<4 - - case AMULWB: - return o&(0xf<<28) | 0x12<<20 | 0xa<<4 - - case AMULBB: - return o&(0xf<<28) | 0x16<<20 | 0x8<<4 - - case AMULAWT: - return o&(0xf<<28) | 0x12<<20 | 0xc<<4 - - case AMULAWB: - return o&(0xf<<28) | 0x12<<20 | 0x8<<4 - - case AMULABB: - return o&(0xf<<28) | 0x10<<20 | 0x8<<4 - - case ABL: // BLX REG - return o&(0xf<<28) | 0x12fff3<<4 - } - - c.ctxt.Diag("%v: bad rrr %d", p, a) - return 0 -} - -func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 { - sc &= C_SCOND - sc ^= C_SCOND_XOR - if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY { - return uint32(sc)<<28 | 0x5<<25 | 0x1<<24 - } - if sc != 0xe { - c.ctxt.Diag("%v: .COND on bcond instruction", p) - } - switch a { - case ABEQ: - return 0x0<<28 | 0x5<<25 - case ABNE: - return 0x1<<28 | 0x5<<25 - case ABCS: - return 0x2<<28 | 0x5<<25 - case ABHS: - return 0x2<<28 | 0x5<<25 - case ABCC: - return 0x3<<28 | 0x5<<25 - case ABLO: - return 0x3<<28 | 0x5<<25 - case ABMI: - return 0x4<<28 | 0x5<<25 - case ABPL: - return 0x5<<28 | 0x5<<25 - case ABVS: - return 0x6<<28 | 0x5<<25 - case ABVC: - return 0x7<<28 | 0x5<<25 - case ABHI: - return 0x8<<28 | 0x5<<25 - case ABLS: - return 0x9<<28 | 0x5<<25 - case ABGE: - return 0xa<<28 | 0x5<<25 - case ABLT: - return 0xb<<28 | 0x5<<25 - case ABGT: - return 0xc<<28 | 0x5<<25 - case ABLE: - return 0xd<<28 | 0x5<<25 - case AB: - return 0xe<<28 | 0x5<<25 - } - - c.ctxt.Diag("%v: bad bra %v", p, a) - return 0 -} - -func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 { - o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 - if sc&C_PBIT == 0 { - o |= 1 << 24 - } - if sc&C_UBIT == 0 { - o |= 1 << 23 - } - if sc&C_WBIT != 0 { - o |= 1 << 21 - } - o |= 1<<26 | 1<<20 - if v < 0 { - if sc&C_UBIT != 0 { - c.ctxt.Diag(".U on neg offset") - } - v = -v - o ^= 1 << 23 - } - - if v >= 1<<12 || v < 0 { - c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) - } - o |= uint32(v) - o |= (uint32(b) & 15) << 16 - o |= (uint32(r) & 15) << 12 - return o -} - -func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 { - o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 - if sc&C_PBIT == 0 { - o |= 1 << 24 - } - if sc&C_WBIT != 0 { - o |= 1 << 21 - } - o |= 1<<23 | 1<<20 | 0xb<<4 - if v < 0 { - v = -v - o ^= 1 << 23 - } - - if v >= 1<<8 || v < 0 { - c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) - } - o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22 - o |= (uint32(b) & 15) << 16 - o |= (uint32(r) & 15) << 12 - return o -} - -func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 { - o := c.olr(v, b, r, sc) ^ (1 << 20) - if a != AMOVW { - o |= 1 << 22 - } - return o -} - -func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 { - o := c.olhr(v, b, r, sc) ^ (1 << 20) - return o -} - -func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 { - return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20) -} - -func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 { - return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20) -} - -func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 { - return c.olr(int32(i), b, r, sc) ^ (1 << 25) -} - -func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 { - return c.olhr(int32(i), b, r, sc) ^ (1 << 22) -} - -func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 { - o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 - if sc&C_PBIT == 0 { - o |= 1 << 24 - } - if sc&C_WBIT != 0 { - o |= 1 << 21 - } - o |= 6<<25 | 1<<24 | 1<<23 | 10<<8 - if v < 0 { - v = -v - o ^= 1 << 23 - } - - if v&3 != 0 { - c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p) - } else if v >= 1<<10 || v < 0 { - c.ctxt.Diag("literal span too large: %d\n%v", v, p) - } - o |= (uint32(v) >> 2) & 0xFF - o |= (uint32(b) & 15) << 16 - o |= (uint32(r) & 15) << 12 - - switch a { - default: - c.ctxt.Diag("bad fst %v", a) - fallthrough - - case AMOVD: - o |= 1 << 8 - fallthrough - - case AMOVF: - break - } - - return o -} - -// MOVW $"lower 16-bit", Reg -func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 { - o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= 0x30 << 20 - o1 |= (uint32(dr) & 15) << 12 - o1 |= uint32(a.Offset) & 0x0fff - o1 |= (uint32(a.Offset) & 0xf000) << 4 - return o1 -} - -// MVN $C_NCON, Reg -> MOVW $C_RCON, Reg -func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 { - o1 := c.oprrr(p, AMOVW, int(p.Scond)) - o1 |= (uint32(dr) & 15) << 12 - v := immrot(^uint32(a.Offset)) - if v == 0 { - c.ctxt.Diag("%v: missing literal", p) - return 0 - } - o1 |= uint32(v) - return o1 -} - -func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 { - var o1 uint32 - if p.Pool == nil { - c.aclass(a) - v := immrot(^uint32(c.instoffset)) - if v == 0 { - c.ctxt.Diag("%v: missing literal", p) - return 0 - } - - o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND) - o1 |= uint32(v) - o1 |= (uint32(dr) & 15) << 12 - } else { - v := int32(p.Pool.Pc - p.Pc - 8) - o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND) - } - - return o1 -} - -func (c *ctxt5) chipzero5(e float64) int { - // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. - if objabi.GOARM < 7 || math.Float64bits(e) != 0 { - return -1 - } - return 0 -} - -func (c *ctxt5) chipfloat5(e float64) int { - // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. - if objabi.GOARM < 7 { - return -1 - } - - ei := math.Float64bits(e) - l := uint32(ei) - h := uint32(ei >> 32) - - if l != 0 || h&0xffff != 0 { - return -1 - } - h1 := h & 0x7fc00000 - if h1 != 0x40000000 && h1 != 0x3fc00000 { - return -1 - } - n := 0 - - // sign bit (a) - if h&0x80000000 != 0 { - n |= 1 << 7 - } - - // exp sign bit (b) - if h1 == 0x3fc00000 { - n |= 1 << 6 - } - - // rest of exp and mantissa (cd-efgh) - n |= int((h >> 16) & 0x3f) - - //print("match %.8lux %.8lux %d\n", l, h, n); - return n -} - -func nocache(p *obj.Prog) { - p.Optab = 0 - p.From.Class = 0 - if p.GetFrom3() != nil { - p.GetFrom3().Class = 0 - } - p.To.Class = 0 -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go deleted file mode 100644 index 30e03001a..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go +++ /dev/null @@ -1,124 +0,0 @@ -// Inferno utils/5c/list.c -// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/list.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package arm - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "fmt" -) - -func init() { - obj.RegisterRegister(obj.RBaseARM, MAXREG, rconv) - obj.RegisterOpcode(obj.ABaseARM, Anames) - obj.RegisterRegisterList(obj.RegListARMLo, obj.RegListARMHi, rlconv) - obj.RegisterOpSuffix("arm", obj.CConvARM) -} - -func rconv(r int) string { - if r == 0 { - return "NONE" - } - if r == REGG { - // Special case. - return "g" - } - if REG_R0 <= r && r <= REG_R15 { - return fmt.Sprintf("R%d", r-REG_R0) - } - if REG_F0 <= r && r <= REG_F15 { - return fmt.Sprintf("F%d", r-REG_F0) - } - - switch r { - case REG_FPSR: - return "FPSR" - - case REG_FPCR: - return "FPCR" - - case REG_CPSR: - return "CPSR" - - case REG_SPSR: - return "SPSR" - - case REG_MB_SY: - return "MB_SY" - case REG_MB_ST: - return "MB_ST" - case REG_MB_ISH: - return "MB_ISH" - case REG_MB_ISHST: - return "MB_ISHST" - case REG_MB_NSH: - return "MB_NSH" - case REG_MB_NSHST: - return "MB_NSHST" - case REG_MB_OSH: - return "MB_OSH" - case REG_MB_OSHST: - return "MB_OSHST" - } - - return fmt.Sprintf("Rgok(%d)", r-obj.RBaseARM) -} - -func DRconv(a int) string { - s := "C_??" - if a >= C_NONE && a <= C_NCLASS { - s = cnames5[a] - } - var fp string - fp += s - return fp -} - -func rlconv(list int64) string { - str := "" - for i := 0; i < 16; i++ { - if list&(1<, C13, C0, 3 specially. - case AMRC: - if p.To.Offset&0xffff0fff == 0xee1d0f70 { - // Because the instruction might be rewritten to a BL which returns in R0 - // the register must be zero. - if p.To.Offset&0xf000 != 0 { - ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line()) - } - - if objabi.GOARM < 7 { - // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension. - if progedit_tlsfallback == nil { - progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback") - } - - // MOVW LR, R11 - p.As = AMOVW - - p.From.Type = obj.TYPE_REG - p.From.Reg = REGLINK - p.To.Type = obj.TYPE_REG - p.To.Reg = REGTMP - - // BL runtime.read_tls_fallback(SB) - p = obj.Appendp(p, newprog) - - p.As = ABL - p.To.Type = obj.TYPE_BRANCH - p.To.Sym = progedit_tlsfallback - p.To.Offset = 0 - - // MOVW R11, LR - p = obj.Appendp(p, newprog) - - p.As = AMOVW - p.From.Type = obj.TYPE_REG - p.From.Reg = REGTMP - p.To.Type = obj.TYPE_REG - p.To.Reg = REGLINK - break - } - } - - // Otherwise, MRC/MCR instructions need no further treatment. - p.As = AWORD - } - - // Rewrite float constants to values stored in memory. - switch p.As { - case AMOVF: - if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { - f32 := float32(p.From.Val.(float64)) - p.From.Type = obj.TYPE_MEM - p.From.Sym = ctxt.Float32Sym(f32) - p.From.Name = obj.NAME_EXTERN - p.From.Offset = 0 - } - - case AMOVD: - if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { - p.From.Type = obj.TYPE_MEM - p.From.Sym = ctxt.Float64Sym(p.From.Val.(float64)) - p.From.Name = obj.NAME_EXTERN - p.From.Offset = 0 - } - } - - if ctxt.Flag_dynlink { - c.rewriteToUseGot(p) - } -} - -// Rewrite p, if necessary, to access global data via the global offset table. -func (c *ctxt5) rewriteToUseGot(p *obj.Prog) { - if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { - // ADUFFxxx $offset - // becomes - // MOVW runtime.duffxxx@GOT, R9 - // ADD $offset, R9 - // CALL (R9) - var sym *obj.LSym - if p.As == obj.ADUFFZERO { - sym = c.ctxt.Lookup("runtime.duffzero") - } else { - sym = c.ctxt.Lookup("runtime.duffcopy") - } - offset := p.To.Offset - p.As = AMOVW - p.From.Type = obj.TYPE_MEM - p.From.Name = obj.NAME_GOTREF - p.From.Sym = sym - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R9 - p.To.Name = obj.NAME_NONE - p.To.Offset = 0 - p.To.Sym = nil - p1 := obj.Appendp(p, c.newprog) - p1.As = AADD - p1.From.Type = obj.TYPE_CONST - p1.From.Offset = offset - p1.To.Type = obj.TYPE_REG - p1.To.Reg = REG_R9 - p2 := obj.Appendp(p1, c.newprog) - p2.As = obj.ACALL - p2.To.Type = obj.TYPE_MEM - p2.To.Reg = REG_R9 - return - } - - // We only care about global data: NAME_EXTERN means a global - // symbol in the Go sense, and p.Sym.Local is true for a few - // internally defined symbols. - if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { - // MOVW $sym, Rx becomes MOVW sym@GOT, Rx - // MOVW $sym+, Rx becomes MOVW sym@GOT, Rx; ADD , Rx - if p.As != AMOVW { - c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) - } - if p.To.Type != obj.TYPE_REG { - c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p) - } - p.From.Type = obj.TYPE_MEM - p.From.Name = obj.NAME_GOTREF - if p.From.Offset != 0 { - q := obj.Appendp(p, c.newprog) - q.As = AADD - q.From.Type = obj.TYPE_CONST - q.From.Offset = p.From.Offset - q.To = p.To - p.From.Offset = 0 - } - } - if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { - c.ctxt.Diag("don't know how to handle %v with -dynlink", p) - } - var source *obj.Addr - // MOVx sym, Ry becomes MOVW sym@GOT, R9; MOVx (R9), Ry - // MOVx Ry, sym becomes MOVW sym@GOT, R9; MOVx Ry, (R9) - // An addition may be inserted between the two MOVs if there is an offset. - if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { - if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { - c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) - } - source = &p.From - } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { - source = &p.To - } else { - return - } - if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { - return - } - if source.Sym.Type == objabi.STLSBSS { - return - } - if source.Type != obj.TYPE_MEM { - c.ctxt.Diag("don't know how to handle %v with -dynlink", p) - } - p1 := obj.Appendp(p, c.newprog) - p2 := obj.Appendp(p1, c.newprog) - - p1.As = AMOVW - p1.From.Type = obj.TYPE_MEM - p1.From.Sym = source.Sym - p1.From.Name = obj.NAME_GOTREF - p1.To.Type = obj.TYPE_REG - p1.To.Reg = REG_R9 - - p2.As = p.As - p2.From = p.From - p2.To = p.To - if p.From.Name == obj.NAME_EXTERN { - p2.From.Reg = REG_R9 - p2.From.Name = obj.NAME_NONE - p2.From.Sym = nil - } else if p.To.Name == obj.NAME_EXTERN { - p2.To.Reg = REG_R9 - p2.To.Name = obj.NAME_NONE - p2.To.Sym = nil - } else { - return - } - obj.Nopout(p) -} - -// Prog.mark -const ( - FOLL = 1 << 0 - LABEL = 1 << 1 - LEAF = 1 << 2 -) - -func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { - autosize := int32(0) - - if cursym.Func.Text == nil || cursym.Func.Text.Link == nil { - return - } - - c := ctxt5{ctxt: ctxt, cursym: cursym, newprog: newprog} - - p := c.cursym.Func.Text - autoffset := int32(p.To.Offset) - if autoffset == -4 { - // Historical way to mark NOFRAME. - p.From.Sym.Set(obj.AttrNoFrame, true) - autoffset = 0 - } - if autoffset < 0 || autoffset%4 != 0 { - c.ctxt.Diag("frame size %d not 0 or a positive multiple of 4", autoffset) - } - if p.From.Sym.NoFrame() { - if autoffset != 0 { - c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", autoffset) - } - } - - cursym.Func.Locals = autoffset - cursym.Func.Args = p.To.Val.(int32) - - /* - * find leaf subroutines - */ - for p := cursym.Func.Text; p != nil; p = p.Link { - switch p.As { - case obj.ATEXT: - p.Mark |= LEAF - - case ADIV, ADIVU, AMOD, AMODU: - cursym.Func.Text.Mark &^= LEAF - - case ABL, - ABX, - obj.ADUFFZERO, - obj.ADUFFCOPY: - cursym.Func.Text.Mark &^= LEAF - } - } - - var q2 *obj.Prog - for p := cursym.Func.Text; p != nil; p = p.Link { - o := p.As - switch o { - case obj.ATEXT: - autosize = autoffset - - if p.Mark&LEAF != 0 && autosize == 0 { - // A leaf function with no locals has no frame. - p.From.Sym.Set(obj.AttrNoFrame, true) - } - - if !p.From.Sym.NoFrame() { - // If there is a stack frame at all, it includes - // space to save the LR. - autosize += 4 - } - - if autosize == 0 && cursym.Func.Text.Mark&LEAF == 0 { - // A very few functions that do not return to their caller - // are not identified as leaves but still have no frame. - if ctxt.Debugvlog { - ctxt.Logf("save suppressed in: %s\n", cursym.Name) - } - - cursym.Func.Text.Mark |= LEAF - } - - // FP offsets need an updated p.To.Offset. - p.To.Offset = int64(autosize) - 4 - - if cursym.Func.Text.Mark&LEAF != 0 { - cursym.Set(obj.AttrLeaf, true) - if p.From.Sym.NoFrame() { - break - } - } - - if !p.From.Sym.NoSplit() { - p = c.stacksplit(p, autosize) // emit split check - } - - // MOVW.W R14,$-autosize(SP) - p = obj.Appendp(p, c.newprog) - - p.As = AMOVW - p.Scond |= C_WBIT - p.From.Type = obj.TYPE_REG - p.From.Reg = REGLINK - p.To.Type = obj.TYPE_MEM - p.To.Offset = int64(-autosize) - p.To.Reg = REGSP - p.Spadj = autosize - - if cursym.Func.Text.From.Sym.Wrapper() { - // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame - // - // MOVW g_panic(g), R1 - // CMP $0, R1 - // B.NE checkargp - // end: - // NOP - // ... function ... - // checkargp: - // MOVW panic_argp(R1), R2 - // ADD $(autosize+4), R13, R3 - // CMP R2, R3 - // B.NE end - // ADD $4, R13, R4 - // MOVW R4, panic_argp(R1) - // B end - // - // The NOP is needed to give the jumps somewhere to land. - // It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes. - - p = obj.Appendp(p, newprog) - p.As = AMOVW - p.From.Type = obj.TYPE_MEM - p.From.Reg = REGG - p.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R1 - - p = obj.Appendp(p, newprog) - p.As = ACMP - p.From.Type = obj.TYPE_CONST - p.From.Offset = 0 - p.Reg = REG_R1 - - // B.NE checkargp - bne := obj.Appendp(p, newprog) - bne.As = ABNE - bne.To.Type = obj.TYPE_BRANCH - - // end: NOP - end := obj.Appendp(bne, newprog) - end.As = obj.ANOP - - // find end of function - var last *obj.Prog - for last = end; last.Link != nil; last = last.Link { - } - - // MOVW panic_argp(R1), R2 - mov := obj.Appendp(last, newprog) - mov.As = AMOVW - mov.From.Type = obj.TYPE_MEM - mov.From.Reg = REG_R1 - mov.From.Offset = 0 // Panic.argp - mov.To.Type = obj.TYPE_REG - mov.To.Reg = REG_R2 - - // B.NE branch target is MOVW above - bne.To.SetTarget(mov) - - // ADD $(autosize+4), R13, R3 - p = obj.Appendp(mov, newprog) - p.As = AADD - p.From.Type = obj.TYPE_CONST - p.From.Offset = int64(autosize) + 4 - p.Reg = REG_R13 - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R3 - - // CMP R2, R3 - p = obj.Appendp(p, newprog) - p.As = ACMP - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R2 - p.Reg = REG_R3 - - // B.NE end - p = obj.Appendp(p, newprog) - p.As = ABNE - p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(end) - - // ADD $4, R13, R4 - p = obj.Appendp(p, newprog) - p.As = AADD - p.From.Type = obj.TYPE_CONST - p.From.Offset = 4 - p.Reg = REG_R13 - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 - - // MOVW R4, panic_argp(R1) - p = obj.Appendp(p, newprog) - p.As = AMOVW - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R4 - p.To.Type = obj.TYPE_MEM - p.To.Reg = REG_R1 - p.To.Offset = 0 // Panic.argp - - // B end - p = obj.Appendp(p, newprog) - p.As = AB - p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(end) - - // reset for subsequent passes - p = end - } - - case obj.ARET: - nocache(p) - if cursym.Func.Text.Mark&LEAF != 0 { - if autosize == 0 { - p.As = AB - p.From = obj.Addr{} - if p.To.Sym != nil { // retjmp - p.To.Type = obj.TYPE_BRANCH - } else { - p.To.Type = obj.TYPE_MEM - p.To.Offset = 0 - p.To.Reg = REGLINK - } - - break - } - } - - p.As = AMOVW - p.Scond |= C_PBIT - p.From.Type = obj.TYPE_MEM - p.From.Offset = int64(autosize) - p.From.Reg = REGSP - p.To.Type = obj.TYPE_REG - p.To.Reg = REGPC - - // If there are instructions following - // this ARET, they come from a branch - // with the same stackframe, so no spadj. - if p.To.Sym != nil { // retjmp - p.To.Reg = REGLINK - q2 = obj.Appendp(p, newprog) - q2.As = AB - q2.To.Type = obj.TYPE_BRANCH - q2.To.Sym = p.To.Sym - p.To.Sym = nil - p = q2 - } - - case AADD: - if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { - p.Spadj = int32(-p.From.Offset) - } - - case ASUB: - if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { - p.Spadj = int32(p.From.Offset) - } - - case ADIV, ADIVU, AMOD, AMODU: - if cursym.Func.Text.From.Sym.NoSplit() { - ctxt.Diag("cannot divide in NOSPLIT function") - } - const debugdivmod = false - if debugdivmod { - break - } - if p.From.Type != obj.TYPE_REG { - break - } - if p.To.Type != obj.TYPE_REG { - break - } - - // Make copy because we overwrite p below. - q1 := *p - if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP { - ctxt.Diag("div already using REGTMP: %v", p) - } - - /* MOV m(g),REGTMP */ - p.As = AMOVW - p.Pos = q1.Pos - p.From.Type = obj.TYPE_MEM - p.From.Reg = REGG - p.From.Offset = 6 * 4 // offset of g.m - p.Reg = 0 - p.To.Type = obj.TYPE_REG - p.To.Reg = REGTMP - - /* MOV a,m_divmod(REGTMP) */ - p = obj.Appendp(p, newprog) - p.As = AMOVW - p.Pos = q1.Pos - p.From.Type = obj.TYPE_REG - p.From.Reg = q1.From.Reg - p.To.Type = obj.TYPE_MEM - p.To.Reg = REGTMP - p.To.Offset = 8 * 4 // offset of m.divmod - - /* MOV b, R8 */ - p = obj.Appendp(p, newprog) - p.As = AMOVW - p.Pos = q1.Pos - p.From.Type = obj.TYPE_REG - p.From.Reg = q1.Reg - if q1.Reg == 0 { - p.From.Reg = q1.To.Reg - } - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R8 - p.To.Offset = 0 - - /* CALL appropriate */ - p = obj.Appendp(p, newprog) - p.As = ABL - p.Pos = q1.Pos - p.To.Type = obj.TYPE_BRANCH - switch o { - case ADIV: - p.To.Sym = symdiv - case ADIVU: - p.To.Sym = symdivu - case AMOD: - p.To.Sym = symmod - case AMODU: - p.To.Sym = symmodu - } - - /* MOV REGTMP, b */ - p = obj.Appendp(p, newprog) - p.As = AMOVW - p.Pos = q1.Pos - p.From.Type = obj.TYPE_REG - p.From.Reg = REGTMP - p.From.Offset = 0 - p.To.Type = obj.TYPE_REG - p.To.Reg = q1.To.Reg - - case AMOVW: - if (p.Scond&C_WBIT != 0) && p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP { - p.Spadj = int32(-p.To.Offset) - } - if (p.Scond&C_PBIT != 0) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP && p.To.Reg != REGPC { - p.Spadj = int32(-p.From.Offset) - } - if p.From.Type == obj.TYPE_ADDR && p.From.Reg == REGSP && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { - p.Spadj = int32(-p.From.Offset) - } - - case obj.AGETCALLERPC: - if cursym.Leaf() { - /* MOVW LR, Rd */ - p.As = AMOVW - p.From.Type = obj.TYPE_REG - p.From.Reg = REGLINK - } else { - /* MOVW (RSP), Rd */ - p.As = AMOVW - p.From.Type = obj.TYPE_MEM - p.From.Reg = REGSP - } - } - } -} - -func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { - // MOVW g_stackguard(g), R1 - p = obj.Appendp(p, c.newprog) - - p.As = AMOVW - p.From.Type = obj.TYPE_MEM - p.From.Reg = REGG - p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0 - if c.cursym.CFunc() { - p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1 - } - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R1 - - // Mark the stack bound check and morestack call async nonpreemptible. - // If we get preempted here, when resumed the preemption request is - // cleared, but we'll still call morestack, which will double the stack - // unnecessarily. See issue #35470. - p = c.ctxt.StartUnsafePoint(p, c.newprog) - - if framesize <= objabi.StackSmall { - // small stack: SP < stackguard - // CMP stackguard, SP - p = obj.Appendp(p, c.newprog) - - p.As = ACMP - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.Reg = REGSP - } else if framesize <= objabi.StackBig { - // large stack: SP-framesize < stackguard-StackSmall - // MOVW $-(framesize-StackSmall)(SP), R2 - // CMP stackguard, R2 - p = obj.Appendp(p, c.newprog) - - p.As = AMOVW - p.From.Type = obj.TYPE_ADDR - p.From.Reg = REGSP - p.From.Offset = -(int64(framesize) - objabi.StackSmall) - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 - - p = obj.Appendp(p, c.newprog) - p.As = ACMP - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.Reg = REG_R2 - } else { - // Such a large stack we need to protect against wraparound - // if SP is close to zero. - // SP-stackguard+StackGuard < framesize + (StackGuard-StackSmall) - // The +StackGuard on both sides is required to keep the left side positive: - // SP is allowed to be slightly below stackguard. See stack.h. - // CMP $StackPreempt, R1 - // MOVW.NE $StackGuard(SP), R2 - // SUB.NE R1, R2 - // MOVW.NE $(framesize+(StackGuard-StackSmall)), R3 - // CMP.NE R3, R2 - p = obj.Appendp(p, c.newprog) - - p.As = ACMP - p.From.Type = obj.TYPE_CONST - p.From.Offset = int64(uint32(objabi.StackPreempt & (1<<32 - 1))) - p.Reg = REG_R1 - - p = obj.Appendp(p, c.newprog) - p.As = AMOVW - p.From.Type = obj.TYPE_ADDR - p.From.Reg = REGSP - p.From.Offset = int64(objabi.StackGuard) - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 - p.Scond = C_SCOND_NE - - p = obj.Appendp(p, c.newprog) - p.As = ASUB - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 - p.Scond = C_SCOND_NE - - p = obj.Appendp(p, c.newprog) - p.As = AMOVW - p.From.Type = obj.TYPE_ADDR - p.From.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall) - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R3 - p.Scond = C_SCOND_NE - - p = obj.Appendp(p, c.newprog) - p.As = ACMP - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 - p.Reg = REG_R2 - p.Scond = C_SCOND_NE - } - - // BLS call-to-morestack - bls := obj.Appendp(p, c.newprog) - bls.As = ABLS - bls.To.Type = obj.TYPE_BRANCH - - end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1) - - var last *obj.Prog - for last = c.cursym.Func.Text; last.Link != nil; last = last.Link { - } - - // Now we are at the end of the function, but logically - // we are still in function prologue. We need to fix the - // SP data and PCDATA. - spfix := obj.Appendp(last, c.newprog) - spfix.As = obj.ANOP - spfix.Spadj = -framesize - - pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog) - pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog) - - // MOVW LR, R3 - movw := obj.Appendp(pcdata, c.newprog) - movw.As = AMOVW - movw.From.Type = obj.TYPE_REG - movw.From.Reg = REGLINK - movw.To.Type = obj.TYPE_REG - movw.To.Reg = REG_R3 - - bls.To.SetTarget(movw) - - // BL runtime.morestack - call := obj.Appendp(movw, c.newprog) - call.As = obj.ACALL - call.To.Type = obj.TYPE_BRANCH - morestack := "runtime.morestack" - switch { - case c.cursym.CFunc(): - morestack = "runtime.morestackc" - case !c.cursym.Func.Text.From.Sym.NeedCtxt(): - morestack = "runtime.morestack_noctxt" - } - call.To.Sym = c.ctxt.Lookup(morestack) - - pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1) - - // B start - b := obj.Appendp(pcdata, c.newprog) - b.As = obj.AJMP - b.To.Type = obj.TYPE_BRANCH - b.To.SetTarget(c.cursym.Func.Text.Link) - b.Spadj = +framesize - - return end -} - -var unaryDst = map[obj.As]bool{ - ASWI: true, - AWORD: true, -} - -var Linkarm = obj.LinkArch{ - Arch: sys.ArchARM, - Init: buildop, - Preprocess: preprocess, - Assemble: span5, - Progedit: progedit, - UnaryDst: unaryDst, - DWARFRegisters: ARMDWARFRegisters, -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go deleted file mode 100644 index 04c084ea2..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go +++ /dev/null @@ -1,1033 +0,0 @@ -// cmd/7c/7.out.h from Vita Nuova. -// https://code.google.com/p/ken-cc/source/browse/src/cmd/7c/7.out.h -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package arm64 - -import "github.com/twitchyliquid64/golang-asm/obj" - -const ( - NSNAME = 8 - NSYM = 50 - NREG = 32 /* number of general registers */ - NFREG = 32 /* number of floating point registers */ -) - -// General purpose registers, kept in the low bits of Prog.Reg. -const ( - // integer - REG_R0 = obj.RBaseARM64 + iota - REG_R1 - REG_R2 - REG_R3 - REG_R4 - REG_R5 - REG_R6 - REG_R7 - REG_R8 - REG_R9 - REG_R10 - REG_R11 - REG_R12 - REG_R13 - REG_R14 - REG_R15 - REG_R16 - REG_R17 - REG_R18 - REG_R19 - REG_R20 - REG_R21 - REG_R22 - REG_R23 - REG_R24 - REG_R25 - REG_R26 - REG_R27 - REG_R28 - REG_R29 - REG_R30 - REG_R31 - - // scalar floating point - REG_F0 - REG_F1 - REG_F2 - REG_F3 - REG_F4 - REG_F5 - REG_F6 - REG_F7 - REG_F8 - REG_F9 - REG_F10 - REG_F11 - REG_F12 - REG_F13 - REG_F14 - REG_F15 - REG_F16 - REG_F17 - REG_F18 - REG_F19 - REG_F20 - REG_F21 - REG_F22 - REG_F23 - REG_F24 - REG_F25 - REG_F26 - REG_F27 - REG_F28 - REG_F29 - REG_F30 - REG_F31 - - // SIMD - REG_V0 - REG_V1 - REG_V2 - REG_V3 - REG_V4 - REG_V5 - REG_V6 - REG_V7 - REG_V8 - REG_V9 - REG_V10 - REG_V11 - REG_V12 - REG_V13 - REG_V14 - REG_V15 - REG_V16 - REG_V17 - REG_V18 - REG_V19 - REG_V20 - REG_V21 - REG_V22 - REG_V23 - REG_V24 - REG_V25 - REG_V26 - REG_V27 - REG_V28 - REG_V29 - REG_V30 - REG_V31 - - // The EQ in - // CSET EQ, R0 - // is encoded as TYPE_REG, even though it's not really a register. - COND_EQ - COND_NE - COND_HS - COND_LO - COND_MI - COND_PL - COND_VS - COND_VC - COND_HI - COND_LS - COND_GE - COND_LT - COND_GT - COND_LE - COND_AL - COND_NV - - REG_RSP = REG_V31 + 32 // to differentiate ZR/SP, REG_RSP&0x1f = 31 -) - -// bits 0-4 indicates register: Vn -// bits 5-8 indicates arrangement: -const ( - REG_ARNG = obj.RBaseARM64 + 1<<10 + iota<<9 // Vn. - REG_ELEM // Vn.[index] - REG_ELEM_END -) - -// Not registers, but flags that can be combined with regular register -// constants to indicate extended register conversion. When checking, -// you should subtract obj.RBaseARM64 first. From this difference, bit 11 -// indicates extended register, bits 8-10 select the conversion mode. -// REG_LSL is the index shift specifier, bit 9 indicates shifted offset register. -const REG_LSL = obj.RBaseARM64 + 1<<9 -const REG_EXT = obj.RBaseARM64 + 1<<11 - -const ( - REG_UXTB = REG_EXT + iota<<8 - REG_UXTH - REG_UXTW - REG_UXTX - REG_SXTB - REG_SXTH - REG_SXTW - REG_SXTX -) - -// Special registers, after subtracting obj.RBaseARM64, bit 12 indicates -// a special register and the low bits select the register. -// SYSREG_END is the last item in the automatically generated system register -// declaration, and it is defined in the sysRegEnc.go file. -const ( - REG_SPECIAL = obj.RBaseARM64 + 1<<12 - REG_DAIFSet = SYSREG_END + iota - REG_DAIFClr - REG_PLDL1KEEP - REG_PLDL1STRM - REG_PLDL2KEEP - REG_PLDL2STRM - REG_PLDL3KEEP - REG_PLDL3STRM - REG_PLIL1KEEP - REG_PLIL1STRM - REG_PLIL2KEEP - REG_PLIL2STRM - REG_PLIL3KEEP - REG_PLIL3STRM - REG_PSTL1KEEP - REG_PSTL1STRM - REG_PSTL2KEEP - REG_PSTL2STRM - REG_PSTL3KEEP - REG_PSTL3STRM -) - -// Register assignments: -// -// compiler allocates R0 up as temps -// compiler allocates register variables R7-R25 -// compiler allocates external registers R26 down -// -// compiler allocates register variables F7-F26 -// compiler allocates external registers F26 down -const ( - REGMIN = REG_R7 // register variables allocated from here to REGMAX - REGRT1 = REG_R16 // ARM64 IP0, external linker may use as a scrach register in trampoline - REGRT2 = REG_R17 // ARM64 IP1, external linker may use as a scrach register in trampoline - REGPR = REG_R18 // ARM64 platform register, unused in the Go toolchain - REGMAX = REG_R25 - - REGCTXT = REG_R26 // environment for closures - REGTMP = REG_R27 // reserved for liblink - REGG = REG_R28 // G - REGFP = REG_R29 // frame pointer, unused in the Go toolchain - REGLINK = REG_R30 - - // ARM64 uses R31 as both stack pointer and zero register, - // depending on the instruction. To differentiate RSP from ZR, - // we use a different numeric value for REGZERO and REGSP. - REGZERO = REG_R31 - REGSP = REG_RSP - - FREGRET = REG_F0 - FREGMIN = REG_F7 // first register variable - FREGMAX = REG_F26 // last register variable for 7g only - FREGEXT = REG_F26 // first external register -) - -// http://infocenter.arm.com/help/topic/com.arm.doc.ecm0665627/abi_sve_aadwarf_100985_0000_00_en.pdf -var ARM64DWARFRegisters = map[int16]int16{ - REG_R0: 0, - REG_R1: 1, - REG_R2: 2, - REG_R3: 3, - REG_R4: 4, - REG_R5: 5, - REG_R6: 6, - REG_R7: 7, - REG_R8: 8, - REG_R9: 9, - REG_R10: 10, - REG_R11: 11, - REG_R12: 12, - REG_R13: 13, - REG_R14: 14, - REG_R15: 15, - REG_R16: 16, - REG_R17: 17, - REG_R18: 18, - REG_R19: 19, - REG_R20: 20, - REG_R21: 21, - REG_R22: 22, - REG_R23: 23, - REG_R24: 24, - REG_R25: 25, - REG_R26: 26, - REG_R27: 27, - REG_R28: 28, - REG_R29: 29, - REG_R30: 30, - - // floating point - REG_F0: 64, - REG_F1: 65, - REG_F2: 66, - REG_F3: 67, - REG_F4: 68, - REG_F5: 69, - REG_F6: 70, - REG_F7: 71, - REG_F8: 72, - REG_F9: 73, - REG_F10: 74, - REG_F11: 75, - REG_F12: 76, - REG_F13: 77, - REG_F14: 78, - REG_F15: 79, - REG_F16: 80, - REG_F17: 81, - REG_F18: 82, - REG_F19: 83, - REG_F20: 84, - REG_F21: 85, - REG_F22: 86, - REG_F23: 87, - REG_F24: 88, - REG_F25: 89, - REG_F26: 90, - REG_F27: 91, - REG_F28: 92, - REG_F29: 93, - REG_F30: 94, - REG_F31: 95, - - // SIMD - REG_V0: 64, - REG_V1: 65, - REG_V2: 66, - REG_V3: 67, - REG_V4: 68, - REG_V5: 69, - REG_V6: 70, - REG_V7: 71, - REG_V8: 72, - REG_V9: 73, - REG_V10: 74, - REG_V11: 75, - REG_V12: 76, - REG_V13: 77, - REG_V14: 78, - REG_V15: 79, - REG_V16: 80, - REG_V17: 81, - REG_V18: 82, - REG_V19: 83, - REG_V20: 84, - REG_V21: 85, - REG_V22: 86, - REG_V23: 87, - REG_V24: 88, - REG_V25: 89, - REG_V26: 90, - REG_V27: 91, - REG_V28: 92, - REG_V29: 93, - REG_V30: 94, - REG_V31: 95, -} - -const ( - BIG = 2048 - 8 -) - -const ( - /* mark flags */ - LABEL = 1 << iota - LEAF - FLOAT - BRANCH - LOAD - FCMP - SYNC - LIST - FOLL - NOSCHED -) - -const ( - // optab is sorted based on the order of these constants - // and the first match is chosen. - // The more specific class needs to come earlier. - C_NONE = iota - C_REG // R0..R30 - C_RSP // R0..R30, RSP - C_FREG // F0..F31 - C_VREG // V0..V31 - C_PAIR // (Rn, Rm) - C_SHIFT // Rn<<2 - C_EXTREG // Rn.UXTB[<<3] - C_SPR // REG_NZCV - C_COND // EQ, NE, etc - C_ARNG // Vn. - C_ELEM // Vn.[index] - C_LIST // [V1, V2, V3] - - C_ZCON // $0 or ZR - C_ABCON0 // could be C_ADDCON0 or C_BITCON - C_ADDCON0 // 12-bit unsigned, unshifted - C_ABCON // could be C_ADDCON or C_BITCON - C_AMCON // could be C_ADDCON or C_MOVCON - C_ADDCON // 12-bit unsigned, shifted left by 0 or 12 - C_MBCON // could be C_MOVCON or C_BITCON - C_MOVCON // generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 - C_BITCON // bitfield and logical immediate masks - C_ADDCON2 // 24-bit constant - C_LCON // 32-bit constant - C_MOVCON2 // a constant that can be loaded with one MOVZ/MOVN and one MOVK - C_MOVCON3 // a constant that can be loaded with one MOVZ/MOVN and two MOVKs - C_VCON // 64-bit constant - C_FCON // floating-point constant - C_VCONADDR // 64-bit memory address - - C_AACON // ADDCON offset in auto constant $a(FP) - C_AACON2 // 24-bit offset in auto constant $a(FP) - C_LACON // 32-bit offset in auto constant $a(FP) - C_AECON // ADDCON offset in extern constant $e(SB) - - // TODO(aram): only one branch class should be enough - C_SBRA // for TYPE_BRANCH - C_LBRA - - C_ZAUTO // 0(RSP) - C_NSAUTO_8 // -256 <= x < 0, 0 mod 8 - C_NSAUTO_4 // -256 <= x < 0, 0 mod 4 - C_NSAUTO // -256 <= x < 0 - C_NPAUTO // -512 <= x < 0, 0 mod 8 - C_NAUTO4K // -4095 <= x < 0 - C_PSAUTO_8 // 0 to 255, 0 mod 8 - C_PSAUTO_4 // 0 to 255, 0 mod 4 - C_PSAUTO // 0 to 255 - C_PPAUTO // 0 to 504, 0 mod 8 - C_UAUTO4K_8 // 0 to 4095, 0 mod 8 - C_UAUTO4K_4 // 0 to 4095, 0 mod 4 - C_UAUTO4K_2 // 0 to 4095, 0 mod 2 - C_UAUTO4K // 0 to 4095 - C_UAUTO8K_8 // 0 to 8190, 0 mod 8 - C_UAUTO8K_4 // 0 to 8190, 0 mod 4 - C_UAUTO8K // 0 to 8190, 0 mod 2 - C_UAUTO16K_8 // 0 to 16380, 0 mod 8 - C_UAUTO16K // 0 to 16380, 0 mod 4 - C_UAUTO32K // 0 to 32760, 0 mod 8 - C_LAUTO // any other 32-bit constant - - C_SEXT1 // 0 to 4095, direct - C_SEXT2 // 0 to 8190 - C_SEXT4 // 0 to 16380 - C_SEXT8 // 0 to 32760 - C_SEXT16 // 0 to 65520 - C_LEXT - - C_ZOREG // 0(R) - C_NSOREG_8 // must mirror C_NSAUTO_8, etc - C_NSOREG_4 - C_NSOREG - C_NPOREG - C_NOREG4K - C_PSOREG_8 - C_PSOREG_4 - C_PSOREG - C_PPOREG - C_UOREG4K_8 - C_UOREG4K_4 - C_UOREG4K_2 - C_UOREG4K - C_UOREG8K_8 - C_UOREG8K_4 - C_UOREG8K - C_UOREG16K_8 - C_UOREG16K - C_UOREG32K - C_LOREG - - C_ADDR // TODO(aram): explain difference from C_VCONADDR - - // The GOT slot for a symbol in -dynlink mode. - C_GOTADDR - - // TLS "var" in local exec mode: will become a constant offset from - // thread local base that is ultimately chosen by the program linker. - C_TLS_LE - - // TLS "var" in initial exec mode: will become a memory address (chosen - // by the program linker) that the dynamic linker will fill with the - // offset from the thread local base. - C_TLS_IE - - C_ROFF // register offset (including register extended) - - C_GOK - C_TEXTSIZE - C_NCLASS // must be last -) - -const ( - C_XPRE = 1 << 6 // match arm.C_WBIT, so Prog.String know how to print it - C_XPOST = 1 << 5 // match arm.C_PBIT, so Prog.String know how to print it -) - -//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p arm64 - -const ( - AADC = obj.ABaseARM64 + obj.A_ARCHSPECIFIC + iota - AADCS - AADCSW - AADCW - AADD - AADDS - AADDSW - AADDW - AADR - AADRP - AAND - AANDS - AANDSW - AANDW - AASR - AASRW - AAT - ABFI - ABFIW - ABFM - ABFMW - ABFXIL - ABFXILW - ABIC - ABICS - ABICSW - ABICW - ABRK - ACBNZ - ACBNZW - ACBZ - ACBZW - ACCMN - ACCMNW - ACCMP - ACCMPW - ACINC - ACINCW - ACINV - ACINVW - ACLREX - ACLS - ACLSW - ACLZ - ACLZW - ACMN - ACMNW - ACMP - ACMPW - ACNEG - ACNEGW - ACRC32B - ACRC32CB - ACRC32CH - ACRC32CW - ACRC32CX - ACRC32H - ACRC32W - ACRC32X - ACSEL - ACSELW - ACSET - ACSETM - ACSETMW - ACSETW - ACSINC - ACSINCW - ACSINV - ACSINVW - ACSNEG - ACSNEGW - ADC - ADCPS1 - ADCPS2 - ADCPS3 - ADMB - ADRPS - ADSB - AEON - AEONW - AEOR - AEORW - AERET - AEXTR - AEXTRW - AHINT - AHLT - AHVC - AIC - AISB - ALDADDAB - ALDADDAD - ALDADDAH - ALDADDAW - ALDADDALB - ALDADDALD - ALDADDALH - ALDADDALW - ALDADDB - ALDADDD - ALDADDH - ALDADDW - ALDADDLB - ALDADDLD - ALDADDLH - ALDADDLW - ALDANDAB - ALDANDAD - ALDANDAH - ALDANDAW - ALDANDALB - ALDANDALD - ALDANDALH - ALDANDALW - ALDANDB - ALDANDD - ALDANDH - ALDANDW - ALDANDLB - ALDANDLD - ALDANDLH - ALDANDLW - ALDAR - ALDARB - ALDARH - ALDARW - ALDAXP - ALDAXPW - ALDAXR - ALDAXRB - ALDAXRH - ALDAXRW - ALDEORAB - ALDEORAD - ALDEORAH - ALDEORAW - ALDEORALB - ALDEORALD - ALDEORALH - ALDEORALW - ALDEORB - ALDEORD - ALDEORH - ALDEORW - ALDEORLB - ALDEORLD - ALDEORLH - ALDEORLW - ALDORAB - ALDORAD - ALDORAH - ALDORAW - ALDORALB - ALDORALD - ALDORALH - ALDORALW - ALDORB - ALDORD - ALDORH - ALDORW - ALDORLB - ALDORLD - ALDORLH - ALDORLW - ALDP - ALDPW - ALDPSW - ALDXR - ALDXRB - ALDXRH - ALDXRW - ALDXP - ALDXPW - ALSL - ALSLW - ALSR - ALSRW - AMADD - AMADDW - AMNEG - AMNEGW - AMOVK - AMOVKW - AMOVN - AMOVNW - AMOVZ - AMOVZW - AMRS - AMSR - AMSUB - AMSUBW - AMUL - AMULW - AMVN - AMVNW - ANEG - ANEGS - ANEGSW - ANEGW - ANGC - ANGCS - ANGCSW - ANGCW - ANOOP - AORN - AORNW - AORR - AORRW - APRFM - APRFUM - ARBIT - ARBITW - AREM - AREMW - AREV - AREV16 - AREV16W - AREV32 - AREVW - AROR - ARORW - ASBC - ASBCS - ASBCSW - ASBCW - ASBFIZ - ASBFIZW - ASBFM - ASBFMW - ASBFX - ASBFXW - ASDIV - ASDIVW - ASEV - ASEVL - ASMADDL - ASMC - ASMNEGL - ASMSUBL - ASMULH - ASMULL - ASTXR - ASTXRB - ASTXRH - ASTXP - ASTXPW - ASTXRW - ASTLP - ASTLPW - ASTLR - ASTLRB - ASTLRH - ASTLRW - ASTLXP - ASTLXPW - ASTLXR - ASTLXRB - ASTLXRH - ASTLXRW - ASTP - ASTPW - ASUB - ASUBS - ASUBSW - ASUBW - ASVC - ASXTB - ASXTBW - ASXTH - ASXTHW - ASXTW - ASYS - ASYSL - ATBNZ - ATBZ - ATLBI - ATST - ATSTW - AUBFIZ - AUBFIZW - AUBFM - AUBFMW - AUBFX - AUBFXW - AUDIV - AUDIVW - AUMADDL - AUMNEGL - AUMSUBL - AUMULH - AUMULL - AUREM - AUREMW - AUXTB - AUXTH - AUXTW - AUXTBW - AUXTHW - AWFE - AWFI - AYIELD - AMOVB - AMOVBU - AMOVH - AMOVHU - AMOVW - AMOVWU - AMOVD - AMOVNP - AMOVNPW - AMOVP - AMOVPD - AMOVPQ - AMOVPS - AMOVPSW - AMOVPW - ASWPAD - ASWPAW - ASWPAH - ASWPAB - ASWPALD - ASWPALW - ASWPALH - ASWPALB - ASWPD - ASWPW - ASWPH - ASWPB - ASWPLD - ASWPLW - ASWPLH - ASWPLB - ABEQ - ABNE - ABCS - ABHS - ABCC - ABLO - ABMI - ABPL - ABVS - ABVC - ABHI - ABLS - ABGE - ABLT - ABGT - ABLE - AFABSD - AFABSS - AFADDD - AFADDS - AFCCMPD - AFCCMPED - AFCCMPS - AFCCMPES - AFCMPD - AFCMPED - AFCMPES - AFCMPS - AFCVTSD - AFCVTDS - AFCVTZSD - AFCVTZSDW - AFCVTZSS - AFCVTZSSW - AFCVTZUD - AFCVTZUDW - AFCVTZUS - AFCVTZUSW - AFDIVD - AFDIVS - AFLDPD - AFLDPS - AFMOVD - AFMOVS - AFMOVQ - AFMULD - AFMULS - AFNEGD - AFNEGS - AFSQRTD - AFSQRTS - AFSTPD - AFSTPS - AFSUBD - AFSUBS - ASCVTFD - ASCVTFS - ASCVTFWD - ASCVTFWS - AUCVTFD - AUCVTFS - AUCVTFWD - AUCVTFWS - AWORD - ADWORD - AFCSELS - AFCSELD - AFMAXS - AFMINS - AFMAXD - AFMIND - AFMAXNMS - AFMAXNMD - AFNMULS - AFNMULD - AFRINTNS - AFRINTND - AFRINTPS - AFRINTPD - AFRINTMS - AFRINTMD - AFRINTZS - AFRINTZD - AFRINTAS - AFRINTAD - AFRINTXS - AFRINTXD - AFRINTIS - AFRINTID - AFMADDS - AFMADDD - AFMSUBS - AFMSUBD - AFNMADDS - AFNMADDD - AFNMSUBS - AFNMSUBD - AFMINNMS - AFMINNMD - AFCVTDH - AFCVTHS - AFCVTHD - AFCVTSH - AAESD - AAESE - AAESIMC - AAESMC - ASHA1C - ASHA1H - ASHA1M - ASHA1P - ASHA1SU0 - ASHA1SU1 - ASHA256H - ASHA256H2 - ASHA256SU0 - ASHA256SU1 - ASHA512H - ASHA512H2 - ASHA512SU0 - ASHA512SU1 - AVADD - AVADDP - AVAND - AVBIF - AVCMEQ - AVCNT - AVEOR - AVMOV - AVLD1 - AVLD2 - AVLD3 - AVLD4 - AVLD1R - AVLD2R - AVLD3R - AVLD4R - AVORR - AVREV16 - AVREV32 - AVREV64 - AVST1 - AVST2 - AVST3 - AVST4 - AVDUP - AVADDV - AVMOVI - AVUADDLV - AVSUB - AVFMLA - AVFMLS - AVPMULL - AVPMULL2 - AVEXT - AVRBIT - AVUSHR - AVUSHLL - AVUSHLL2 - AVUXTL - AVUXTL2 - AVUZP1 - AVUZP2 - AVSHL - AVSRI - AVBSL - AVBIT - AVTBL - AVZIP1 - AVZIP2 - AVCMTST - ALAST - AB = obj.AJMP - ABL = obj.ACALL -) - -const ( - // shift types - SHIFT_LL = 0 << 22 - SHIFT_LR = 1 << 22 - SHIFT_AR = 2 << 22 -) - -// Arrangement for ARM64 SIMD instructions -const ( - // arrangement types - ARNG_8B = iota - ARNG_16B - ARNG_1D - ARNG_4H - ARNG_8H - ARNG_2S - ARNG_4S - ARNG_2D - ARNG_1Q - ARNG_B - ARNG_H - ARNG_S - ARNG_D -) diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go deleted file mode 100644 index 0ce620a9e..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go +++ /dev/null @@ -1,512 +0,0 @@ -// Code generated by stringer -i a.out.go -o anames.go -p arm64; DO NOT EDIT. - -package arm64 - -import "github.com/twitchyliquid64/golang-asm/obj" - -var Anames = []string{ - obj.A_ARCHSPECIFIC: "ADC", - "ADCS", - "ADCSW", - "ADCW", - "ADD", - "ADDS", - "ADDSW", - "ADDW", - "ADR", - "ADRP", - "AND", - "ANDS", - "ANDSW", - "ANDW", - "ASR", - "ASRW", - "AT", - "BFI", - "BFIW", - "BFM", - "BFMW", - "BFXIL", - "BFXILW", - "BIC", - "BICS", - "BICSW", - "BICW", - "BRK", - "CBNZ", - "CBNZW", - "CBZ", - "CBZW", - "CCMN", - "CCMNW", - "CCMP", - "CCMPW", - "CINC", - "CINCW", - "CINV", - "CINVW", - "CLREX", - "CLS", - "CLSW", - "CLZ", - "CLZW", - "CMN", - "CMNW", - "CMP", - "CMPW", - "CNEG", - "CNEGW", - "CRC32B", - "CRC32CB", - "CRC32CH", - "CRC32CW", - "CRC32CX", - "CRC32H", - "CRC32W", - "CRC32X", - "CSEL", - "CSELW", - "CSET", - "CSETM", - "CSETMW", - "CSETW", - "CSINC", - "CSINCW", - "CSINV", - "CSINVW", - "CSNEG", - "CSNEGW", - "DC", - "DCPS1", - "DCPS2", - "DCPS3", - "DMB", - "DRPS", - "DSB", - "EON", - "EONW", - "EOR", - "EORW", - "ERET", - "EXTR", - "EXTRW", - "HINT", - "HLT", - "HVC", - "IC", - "ISB", - "LDADDAB", - "LDADDAD", - "LDADDAH", - "LDADDAW", - "LDADDALB", - "LDADDALD", - "LDADDALH", - "LDADDALW", - "LDADDB", - "LDADDD", - "LDADDH", - "LDADDW", - "LDADDLB", - "LDADDLD", - "LDADDLH", - "LDADDLW", - "LDANDAB", - "LDANDAD", - "LDANDAH", - "LDANDAW", - "LDANDALB", - "LDANDALD", - "LDANDALH", - "LDANDALW", - "LDANDB", - "LDANDD", - "LDANDH", - "LDANDW", - "LDANDLB", - "LDANDLD", - "LDANDLH", - "LDANDLW", - "LDAR", - "LDARB", - "LDARH", - "LDARW", - "LDAXP", - "LDAXPW", - "LDAXR", - "LDAXRB", - "LDAXRH", - "LDAXRW", - "LDEORAB", - "LDEORAD", - "LDEORAH", - "LDEORAW", - "LDEORALB", - "LDEORALD", - "LDEORALH", - "LDEORALW", - "LDEORB", - "LDEORD", - "LDEORH", - "LDEORW", - "LDEORLB", - "LDEORLD", - "LDEORLH", - "LDEORLW", - "LDORAB", - "LDORAD", - "LDORAH", - "LDORAW", - "LDORALB", - "LDORALD", - "LDORALH", - "LDORALW", - "LDORB", - "LDORD", - "LDORH", - "LDORW", - "LDORLB", - "LDORLD", - "LDORLH", - "LDORLW", - "LDP", - "LDPW", - "LDPSW", - "LDXR", - "LDXRB", - "LDXRH", - "LDXRW", - "LDXP", - "LDXPW", - "LSL", - "LSLW", - "LSR", - "LSRW", - "MADD", - "MADDW", - "MNEG", - "MNEGW", - "MOVK", - "MOVKW", - "MOVN", - "MOVNW", - "MOVZ", - "MOVZW", - "MRS", - "MSR", - "MSUB", - "MSUBW", - "MUL", - "MULW", - "MVN", - "MVNW", - "NEG", - "NEGS", - "NEGSW", - "NEGW", - "NGC", - "NGCS", - "NGCSW", - "NGCW", - "NOOP", - "ORN", - "ORNW", - "ORR", - "ORRW", - "PRFM", - "PRFUM", - "RBIT", - "RBITW", - "REM", - "REMW", - "REV", - "REV16", - "REV16W", - "REV32", - "REVW", - "ROR", - "RORW", - "SBC", - "SBCS", - "SBCSW", - "SBCW", - "SBFIZ", - "SBFIZW", - "SBFM", - "SBFMW", - "SBFX", - "SBFXW", - "SDIV", - "SDIVW", - "SEV", - "SEVL", - "SMADDL", - "SMC", - "SMNEGL", - "SMSUBL", - "SMULH", - "SMULL", - "STXR", - "STXRB", - "STXRH", - "STXP", - "STXPW", - "STXRW", - "STLP", - "STLPW", - "STLR", - "STLRB", - "STLRH", - "STLRW", - "STLXP", - "STLXPW", - "STLXR", - "STLXRB", - "STLXRH", - "STLXRW", - "STP", - "STPW", - "SUB", - "SUBS", - "SUBSW", - "SUBW", - "SVC", - "SXTB", - "SXTBW", - "SXTH", - "SXTHW", - "SXTW", - "SYS", - "SYSL", - "TBNZ", - "TBZ", - "TLBI", - "TST", - "TSTW", - "UBFIZ", - "UBFIZW", - "UBFM", - "UBFMW", - "UBFX", - "UBFXW", - "UDIV", - "UDIVW", - "UMADDL", - "UMNEGL", - "UMSUBL", - "UMULH", - "UMULL", - "UREM", - "UREMW", - "UXTB", - "UXTH", - "UXTW", - "UXTBW", - "UXTHW", - "WFE", - "WFI", - "YIELD", - "MOVB", - "MOVBU", - "MOVH", - "MOVHU", - "MOVW", - "MOVWU", - "MOVD", - "MOVNP", - "MOVNPW", - "MOVP", - "MOVPD", - "MOVPQ", - "MOVPS", - "MOVPSW", - "MOVPW", - "SWPAD", - "SWPAW", - "SWPAH", - "SWPAB", - "SWPALD", - "SWPALW", - "SWPALH", - "SWPALB", - "SWPD", - "SWPW", - "SWPH", - "SWPB", - "SWPLD", - "SWPLW", - "SWPLH", - "SWPLB", - "BEQ", - "BNE", - "BCS", - "BHS", - "BCC", - "BLO", - "BMI", - "BPL", - "BVS", - "BVC", - "BHI", - "BLS", - "BGE", - "BLT", - "BGT", - "BLE", - "FABSD", - "FABSS", - "FADDD", - "FADDS", - "FCCMPD", - "FCCMPED", - "FCCMPS", - "FCCMPES", - "FCMPD", - "FCMPED", - "FCMPES", - "FCMPS", - "FCVTSD", - "FCVTDS", - "FCVTZSD", - "FCVTZSDW", - "FCVTZSS", - "FCVTZSSW", - "FCVTZUD", - "FCVTZUDW", - "FCVTZUS", - "FCVTZUSW", - "FDIVD", - "FDIVS", - "FLDPD", - "FLDPS", - "FMOVD", - "FMOVS", - "FMOVQ", - "FMULD", - "FMULS", - "FNEGD", - "FNEGS", - "FSQRTD", - "FSQRTS", - "FSTPD", - "FSTPS", - "FSUBD", - "FSUBS", - "SCVTFD", - "SCVTFS", - "SCVTFWD", - "SCVTFWS", - "UCVTFD", - "UCVTFS", - "UCVTFWD", - "UCVTFWS", - "WORD", - "DWORD", - "FCSELS", - "FCSELD", - "FMAXS", - "FMINS", - "FMAXD", - "FMIND", - "FMAXNMS", - "FMAXNMD", - "FNMULS", - "FNMULD", - "FRINTNS", - "FRINTND", - "FRINTPS", - "FRINTPD", - "FRINTMS", - "FRINTMD", - "FRINTZS", - "FRINTZD", - "FRINTAS", - "FRINTAD", - "FRINTXS", - "FRINTXD", - "FRINTIS", - "FRINTID", - "FMADDS", - "FMADDD", - "FMSUBS", - "FMSUBD", - "FNMADDS", - "FNMADDD", - "FNMSUBS", - "FNMSUBD", - "FMINNMS", - "FMINNMD", - "FCVTDH", - "FCVTHS", - "FCVTHD", - "FCVTSH", - "AESD", - "AESE", - "AESIMC", - "AESMC", - "SHA1C", - "SHA1H", - "SHA1M", - "SHA1P", - "SHA1SU0", - "SHA1SU1", - "SHA256H", - "SHA256H2", - "SHA256SU0", - "SHA256SU1", - "SHA512H", - "SHA512H2", - "SHA512SU0", - "SHA512SU1", - "VADD", - "VADDP", - "VAND", - "VBIF", - "VCMEQ", - "VCNT", - "VEOR", - "VMOV", - "VLD1", - "VLD2", - "VLD3", - "VLD4", - "VLD1R", - "VLD2R", - "VLD3R", - "VLD4R", - "VORR", - "VREV16", - "VREV32", - "VREV64", - "VST1", - "VST2", - "VST3", - "VST4", - "VDUP", - "VADDV", - "VMOVI", - "VUADDLV", - "VSUB", - "VFMLA", - "VFMLS", - "VPMULL", - "VPMULL2", - "VEXT", - "VRBIT", - "VUSHR", - "VUSHLL", - "VUSHLL2", - "VUXTL", - "VUXTL2", - "VUZP1", - "VUZP2", - "VSHL", - "VSRI", - "VBSL", - "VBIT", - "VTBL", - "VZIP1", - "VZIP2", - "VCMTST", - "LAST", -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go deleted file mode 100644 index 96c9f788d..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package arm64 - -// This order should be strictly consistent to that in a.out.go -var cnames7 = []string{ - "NONE", - "REG", - "RSP", - "FREG", - "VREG", - "PAIR", - "SHIFT", - "EXTREG", - "SPR", - "COND", - "ARNG", - "ELEM", - "LIST", - "ZCON", - "ABCON0", - "ADDCON0", - "ABCON", - "AMCON", - "ADDCON", - "MBCON", - "MOVCON", - "BITCON", - "ADDCON2", - "LCON", - "MOVCON2", - "MOVCON3", - "VCON", - "FCON", - "VCONADDR", - "AACON", - "AACON2", - "LACON", - "AECON", - "SBRA", - "LBRA", - "ZAUTO", - "NSAUTO_8", - "NSAUTO_4", - "NSAUTO", - "NPAUTO", - "NAUTO4K", - "PSAUTO_8", - "PSAUTO_4", - "PSAUTO", - "PPAUTO", - "UAUTO4K_8", - "UAUTO4K_4", - "UAUTO4K_2", - "UAUTO4K", - "UAUTO8K_8", - "UAUTO8K_4", - "UAUTO8K", - "UAUTO16K_8", - "UAUTO16K", - "UAUTO32K", - "LAUTO", - "SEXT1", - "SEXT2", - "SEXT4", - "SEXT8", - "SEXT16", - "LEXT", - "ZOREG", - "NSOREG_8", - "NSOREG_4", - "NSOREG", - "NPOREG", - "NOREG4K", - "PSOREG_8", - "PSOREG_4", - "PSOREG", - "PPOREG", - "UOREG4K_8", - "UOREG4K_4", - "UOREG4K_2", - "UOREG4K", - "UOREG8K_8", - "UOREG8K_4", - "UOREG8K", - "UOREG16K_8", - "UOREG16K", - "UOREG32K", - "LOREG", - "ADDR", - "GOTADDR", - "TLS_LE", - "TLS_IE", - "ROFF", - "GOK", - "TEXTSIZE", - "NCLASS", -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go deleted file mode 100644 index 2bbb64b9d..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go +++ /dev/null @@ -1,7140 +0,0 @@ -// cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova. -// https://code.google.com/p/ken-cc/source/browse/ -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package arm64 - -import ( - "github.com/twitchyliquid64/golang-asm/obj" - "github.com/twitchyliquid64/golang-asm/objabi" - "fmt" - "log" - "math" - "sort" -) - -// ctxt7 holds state while assembling a single function. -// Each function gets a fresh ctxt7. -// This allows for multiple functions to be safely concurrently assembled. -type ctxt7 struct { - ctxt *obj.Link - newprog obj.ProgAlloc - cursym *obj.LSym - blitrl *obj.Prog - elitrl *obj.Prog - autosize int32 - extrasize int32 - instoffset int64 - pc int64 - pool struct { - start uint32 - size uint32 - } -} - -const ( - funcAlign = 16 -) - -const ( - REGFROM = 1 -) - -type Optab struct { - as obj.As - a1 uint8 - a2 uint8 - a3 uint8 - a4 uint8 - type_ int8 - size int8 - param int16 - flag int8 - scond uint16 -} - -func IsAtomicInstruction(as obj.As) bool { - _, ok := atomicInstructions[as] - return ok -} - -// known field values of an instruction. -var atomicInstructions = map[obj.As]uint32{ - ALDADDAD: 3<<30 | 0x1c5<<21 | 0x00<<10, - ALDADDAW: 2<<30 | 0x1c5<<21 | 0x00<<10, - ALDADDAH: 1<<30 | 0x1c5<<21 | 0x00<<10, - ALDADDAB: 0<<30 | 0x1c5<<21 | 0x00<<10, - ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10, - ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10, - ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10, - ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10, - ALDADDD: 3<<30 | 0x1c1<<21 | 0x00<<10, - ALDADDW: 2<<30 | 0x1c1<<21 | 0x00<<10, - ALDADDH: 1<<30 | 0x1c1<<21 | 0x00<<10, - ALDADDB: 0<<30 | 0x1c1<<21 | 0x00<<10, - ALDADDLD: 3<<30 | 0x1c3<<21 | 0x00<<10, - ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10, - ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10, - ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10, - ALDANDAD: 3<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAW: 2<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAH: 1<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAB: 0<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDALD: 3<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALW: 2<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALH: 1<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALB: 0<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDD: 3<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDW: 2<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDH: 1<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDB: 0<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDLD: 3<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLW: 2<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLH: 1<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLB: 0<<30 | 0x1c3<<21 | 0x04<<10, - ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10, - ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10, - ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10, - ALDEORAB: 0<<30 | 0x1c5<<21 | 0x08<<10, - ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10, - ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10, - ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10, - ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10, - ALDEORD: 3<<30 | 0x1c1<<21 | 0x08<<10, - ALDEORW: 2<<30 | 0x1c1<<21 | 0x08<<10, - ALDEORH: 1<<30 | 0x1c1<<21 | 0x08<<10, - ALDEORB: 0<<30 | 0x1c1<<21 | 0x08<<10, - ALDEORLD: 3<<30 | 0x1c3<<21 | 0x08<<10, - ALDEORLW: 2<<30 | 0x1c3<<21 | 0x08<<10, - ALDEORLH: 1<<30 | 0x1c3<<21 | 0x08<<10, - ALDEORLB: 0<<30 | 0x1c3<<21 | 0x08<<10, - ALDORAD: 3<<30 | 0x1c5<<21 | 0x0c<<10, - ALDORAW: 2<<30 | 0x1c5<<21 | 0x0c<<10, - ALDORAH: 1<<30 | 0x1c5<<21 | 0x0c<<10, - ALDORAB: 0<<30 | 0x1c5<<21 | 0x0c<<10, - ALDORALD: 3<<30 | 0x1c7<<21 | 0x0c<<10, - ALDORALW: 2<<30 | 0x1c7<<21 | 0x0c<<10, - ALDORALH: 1<<30 | 0x1c7<<21 | 0x0c<<10, - ALDORALB: 0<<30 | 0x1c7<<21 | 0x0c<<10, - ALDORD: 3<<30 | 0x1c1<<21 | 0x0c<<10, - ALDORW: 2<<30 | 0x1c1<<21 | 0x0c<<10, - ALDORH: 1<<30 | 0x1c1<<21 | 0x0c<<10, - ALDORB: 0<<30 | 0x1c1<<21 | 0x0c<<10, - ALDORLD: 3<<30 | 0x1c3<<21 | 0x0c<<10, - ALDORLW: 2<<30 | 0x1c3<<21 | 0x0c<<10, - ALDORLH: 1<<30 | 0x1c3<<21 | 0x0c<<10, - ALDORLB: 0<<30 | 0x1c3<<21 | 0x0c<<10, - ASWPAD: 3<<30 | 0x1c5<<21 | 0x20<<10, - ASWPAW: 2<<30 | 0x1c5<<21 | 0x20<<10, - ASWPAH: 1<<30 | 0x1c5<<21 | 0x20<<10, - ASWPAB: 0<<30 | 0x1c5<<21 | 0x20<<10, - ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10, - ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10, - ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10, - ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10, - ASWPD: 3<<30 | 0x1c1<<21 | 0x20<<10, - ASWPW: 2<<30 | 0x1c1<<21 | 0x20<<10, - ASWPH: 1<<30 | 0x1c1<<21 | 0x20<<10, - ASWPB: 0<<30 | 0x1c1<<21 | 0x20<<10, - ASWPLD: 3<<30 | 0x1c3<<21 | 0x20<<10, - ASWPLW: 2<<30 | 0x1c3<<21 | 0x20<<10, - ASWPLH: 1<<30 | 0x1c3<<21 | 0x20<<10, - ASWPLB: 0<<30 | 0x1c3<<21 | 0x20<<10, -} - -var oprange [ALAST & obj.AMask][]Optab - -var xcmp [C_NCLASS][C_NCLASS]bool - -const ( - S32 = 0 << 31 - S64 = 1 << 31 - Sbit = 1 << 29 - LSL0_32 = 2 << 13 - LSL0_64 = 3 << 13 -) - -func OPDP2(x uint32) uint32 { - return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 -} - -func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { - return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 -} - -func OPBcc(x uint32) uint32 { - return 0x2A<<25 | 0<<24 | 0<<4 | x&15 -} - -func OPBLR(x uint32) uint32 { - /* x=0, JMP; 1, CALL; 2, RET */ - return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 -} - -func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { - return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt -} - -func SYSHINT(x uint32) uint32 { - return SYSOP(0, 0, 3, 2, 0, x, 0x1F) -} - -func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { - return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 -} - -func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 { - return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22 -} - -func LD2STR(o uint32) uint32 { - return o &^ (3 << 22) -} - -func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { - return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 -} - -func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { - return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 -} - -func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { - return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 -} - -func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { - return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 -} - -func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { - return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 -} - -func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { - return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15 -} - -func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { - return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 -} - -func ADR(p uint32, o uint32, rt uint32) uint32 { - return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 -} - -func OPBIT(x uint32) uint32 { - return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 -} - -func MOVCONST(d int64, s int, rt int) uint32 { - return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31) -} - -const ( - // Optab.flag - LFROM = 1 << 0 // p.From uses constant pool - LTO = 1 << 1 // p.To uses constant pool - NOTUSETMP = 1 << 2 // p expands to multiple instructions, but does NOT use REGTMP -) - -var optab = []Optab{ - /* struct Optab: - OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */ - {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, - - /* arithmetic operations */ - {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, - {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, - {ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0}, - {ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, - {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0}, - {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0}, - {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0}, - {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, - {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, - {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, - {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, - {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, - {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, - {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0}, - {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0}, - {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0}, - {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0}, - {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0}, - {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0}, - {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0}, - {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0}, - {ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0}, - {ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0}, - {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0}, - {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, - {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0}, - {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, - {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, - {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, - {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, - {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, - {AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, - {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, - {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, - {AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0}, - {AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, - {AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0}, - {AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0}, - {ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - - {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0}, - {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, - {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, - {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, - {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, - {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0}, - {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0}, - {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0}, - - /* logical operations */ - {AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, - {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, - {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, - {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, - {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, - {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, - {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, - {AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, - {AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, - {AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, - {AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, - {ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0}, - {AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0}, - {AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0}, - {AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0}, - {AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0}, - {AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0}, - {AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0}, - {AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0}, - {AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0}, - {AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0}, - {AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0}, - {AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0}, - {AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0}, - {ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0}, - {ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0}, - {ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0}, - {AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, - {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0}, - {AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */ - {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */ - /* TODO: MVN C_SHIFT */ - - /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ - {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, - {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, - {AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, - {AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, - {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0}, - {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0}, - {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, NOTUSETMP, 0}, - {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, NOTUSETMP, 0}, - - {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0}, - {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0}, - {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0}, - - /* load long effective stack address (load int32 offset and add) */ - {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0}, - - // Move a large constant to a Vn. - {AFMOVQ, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0}, - {AFMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0}, - {AFMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0}, - - /* jump operations */ - {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, - {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, - {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, - {ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, - {ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, - {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, - {obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, - {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, - {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0}, - {ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0}, - {ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0}, - {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, - - // get a PC-relative address - {AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0}, - {AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0}, - - {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0}, - {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, - {ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0}, - {ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0}, - {AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0}, - {ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, - {ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0}, - {ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0}, - {ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0}, - {ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0}, - {ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, - {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, - {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, - {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0}, - {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0}, - {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0}, - {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0}, - {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0}, - {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0}, - {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0}, - {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, - {AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, - {AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, - {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, - {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, - {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0}, - {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0}, - {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0}, - - {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, - {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, - {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, - {AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, - {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, - {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, - {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, - {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0}, - {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0}, - {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0}, - {AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0}, - {AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0}, - {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, - {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0}, - {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0}, - {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, - {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0}, - {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0}, - {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0}, - {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, - {AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0}, - {AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0}, - - /* conditional operations */ - {ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0}, - {ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0}, - {ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0}, - {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0}, - {ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0}, - {ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0}, - {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0}, - - /* scaled 12-bit unsigned displacement store */ - {AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, - - {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, - - /* unscaled 9-bit signed displacement store */ - {AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - - {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, - - /* scaled 12-bit unsigned displacement load */ - {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - - {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, - {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, - {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, - {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, - - /* unscaled 9-bit signed displacement load */ - {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, - {AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, - - {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, - {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, - {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, - {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, - - /* long displacement store */ - {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - - {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, - - /* long displacement load */ - {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, - {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, - {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, - {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, - {AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, - {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, - {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, - {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, - {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, - {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, - - {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, - {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, - {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, - {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, - - /* pre/post-indexed load (unscaled, signed 9-bit offset) */ - {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, - {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, - {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, - {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, - {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, - {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, - {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, - - {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, - {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, - {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, - {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, - {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, - {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, - {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, - - /* pre/post-indexed store (unscaled, signed 9-bit offset) */ - {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, - - {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, - - /* load with shifted or extended register offset */ - {AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, - {AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, - {AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, - {AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, - {AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, - {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, - {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, - - /* store with extended register offset */ - {AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - {AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - {AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - {AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, - - /* pre/post-indexed/signed-offset load/store register pair - (unscaled, signed 10-bit quad-aligned and long offset) */ - {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, - {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, - {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, - {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, - {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, - {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, - {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, - {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, - {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, - {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, - {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, - {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, - {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, - {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, - {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, - {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, - {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, - {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, - {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, - {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, - {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, - {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, - {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, - {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, - {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, - {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, - {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, - - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, - - // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4 - {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, - {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, - {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, - {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, - {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, - {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, - {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, - {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, - {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, - {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, - {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, - {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, - {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, - {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, - {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, - {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, - {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, - {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, - {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, - {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, - {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, - {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, - {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, - {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, - {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, - {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, - {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, - - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, - - {ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG - {ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG - {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, - {ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, - {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, - {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0}, - {ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE - {ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG - {ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG - {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, - - /* VLD[1-4]/VST[1-4] */ - {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0}, - {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, - {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, - {AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0}, - {AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, - {AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, - {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, - {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, - {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0}, - {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, - {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, - {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, - {AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, - {AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, - {AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, - {AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, - {AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, - {AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, - {AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, - {AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, - {AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, - {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST}, - {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST}, - {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0}, - - /* special */ - {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, - {AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, - {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, - {AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, - {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, - {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, - {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0}, - {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0}, - {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0}, - {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0}, - {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0}, - {ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0}, - {ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0}, - - /* encryption instructions */ - {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code - {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability - {ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, - {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, - {ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, - {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0}, - {ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, - {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, - {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0}, - - {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, - {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0}, - {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, - {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, - {obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689 - {obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, - {obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, - {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL - {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL - {obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // align code - - {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, -} - -/* - * valid pstate field values, and value to use in instruction - */ -var pstatefield = []struct { - reg int16 - enc uint32 -}{ - {REG_SPSel, 0<<16 | 4<<12 | 5<<5}, - {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5}, - {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, -} - -var prfopfield = []struct { - reg int16 - enc uint32 -}{ - {REG_PLDL1KEEP, 0}, - {REG_PLDL1STRM, 1}, - {REG_PLDL2KEEP, 2}, - {REG_PLDL2STRM, 3}, - {REG_PLDL3KEEP, 4}, - {REG_PLDL3STRM, 5}, - {REG_PLIL1KEEP, 8}, - {REG_PLIL1STRM, 9}, - {REG_PLIL2KEEP, 10}, - {REG_PLIL2STRM, 11}, - {REG_PLIL3KEEP, 12}, - {REG_PLIL3STRM, 13}, - {REG_PSTL1KEEP, 16}, - {REG_PSTL1STRM, 17}, - {REG_PSTL2KEEP, 18}, - {REG_PSTL2STRM, 19}, - {REG_PSTL3KEEP, 20}, - {REG_PSTL3STRM, 21}, -} - -// Used for padinng NOOP instruction -const OP_NOOP = 0xd503201f - -// align code to a certain length by padding bytes. -func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int { - if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) { - ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue) - } - return int(-pc & (alignedValue - 1)) -} - -func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { - if ctxt.Retpoline { - ctxt.Diag("-spectre=ret not supported on arm64") - ctxt.Retpoline = false // don't keep printing - } - - p := cursym.Func.Text - if p == nil || p.Link == nil { // handle external functions and ELF section symbols - return - } - - if oprange[AAND&obj.AMask] == nil { - ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") - } - - c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)} - p.To.Offset &= 0xffffffff // extrasize is no longer needed - - bflag := 1 - pc := int64(0) - p.Pc = pc - var m int - var o *Optab - for p = p.Link; p != nil; p = p.Link { - if p.As == ADWORD && (pc&7) != 0 { - pc += 4 - } - p.Pc = pc - o = c.oplook(p) - m = int(o.size) - if m == 0 { - switch p.As { - case obj.APCALIGN: - alignedValue := p.From.Offset - m = pcAlignPadLength(pc, alignedValue, ctxt) - // Update the current text symbol alignment value. - if int32(alignedValue) > cursym.Func.Align { - cursym.Func.Align = int32(alignedValue) - } - break - case obj.ANOP, obj.AFUNCDATA, obj.APCDATA: - continue - default: - c.ctxt.Diag("zero-width instruction\n%v", p) - } - } - switch o.flag & (LFROM | LTO) { - case LFROM: - c.addpool(p, &p.From) - - case LTO: - c.addpool(p, &p.To) - break - } - - if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ - c.checkpool(p, 0) - } - pc += int64(m) - if c.blitrl != nil { - c.checkpool(p, 1) - } - } - - c.cursym.Size = pc - - /* - * if any procedure is large enough to - * generate a large SBRA branch, then - * generate extra passes putting branches - * around jmps to fix. this is rare. - */ - for bflag != 0 { - bflag = 0 - pc = 0 - for p = c.cursym.Func.Text.Link; p != nil; p = p.Link { - if p.As == ADWORD && (pc&7) != 0 { - pc += 4 - } - p.Pc = pc - o = c.oplook(p) - - /* very large branches */ - if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.To.Target() != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like - otxt := p.To.Target().Pc - pc - var toofar bool - switch o.type_ { - case 7, 39: // branch instruction encodes 19 bits - toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10 - case 40: // branch instruction encodes 14 bits - toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10 - } - if toofar { - q := c.newprog() - q.Link = p.Link - p.Link = q - q.As = AB - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(p.To.Target()) - p.To.SetTarget(q) - q = c.newprog() - q.Link = p.Link - p.Link = q - q.As = AB - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(q.Link.Link) - bflag = 1 - } - } - m = int(o.size) - - if m == 0 { - switch p.As { - case obj.APCALIGN: - alignedValue := p.From.Offset - m = pcAlignPadLength(pc, alignedValue, ctxt) - break - case obj.ANOP, obj.AFUNCDATA, obj.APCDATA: - continue - default: - c.ctxt.Diag("zero-width instruction\n%v", p) - } - } - - pc += int64(m) - } - } - - pc += -pc & (funcAlign - 1) - c.cursym.Size = pc - - /* - * lay out the code, emitting code and data relocations. - */ - c.cursym.Grow(c.cursym.Size) - bp := c.cursym.P - psz := int32(0) - var i int - var out [6]uint32 - for p := c.cursym.Func.Text.Link; p != nil; p = p.Link { - c.pc = p.Pc - o = c.oplook(p) - - // need to align DWORDs on 8-byte boundary. The ISA doesn't - // require it, but the various 64-bit loads we generate assume it. - if o.as == ADWORD && psz%8 != 0 { - bp[3] = 0 - bp[2] = bp[3] - bp[1] = bp[2] - bp[0] = bp[1] - bp = bp[4:] - psz += 4 - } - - if int(o.size) > 4*len(out) { - log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) - } - if p.As == obj.APCALIGN { - alignedValue := p.From.Offset - v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt) - for i = 0; i < int(v/4); i++ { - // emit ANOOP instruction by the padding size - c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP) - bp = bp[4:] - psz += 4 - } - } else { - c.asmout(p, o, out[:]) - for i = 0; i < int(o.size/4); i++ { - c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) - bp = bp[4:] - psz += 4 - } - } - } - - // Mark nonpreemptible instruction sequences. - // We use REGTMP as a scratch register during call injection, - // so instruction sequences that use REGTMP are unsafe to - // preempt asynchronously. - obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable) -} - -// isUnsafePoint returns whether p is an unsafe point. -func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool { - // If p explicitly uses REGTMP, it's unsafe to preempt, because the - // preemption sequence clobbers REGTMP. - return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP -} - -// isRestartable returns whether p is a multi-instruction sequence that, -// if preempted, can be restarted. -func (c *ctxt7) isRestartable(p *obj.Prog) bool { - if c.isUnsafePoint(p) { - return false - } - // If p is a multi-instruction sequence with uses REGTMP inserted by - // the assembler in order to materialize a large constant/offset, we - // can restart p (at the start of the instruction sequence), recompute - // the content of REGTMP, upon async preemption. Currently, all cases - // of assembler-inserted REGTMP fall into this category. - // If p doesn't use REGTMP, it can be simply preempted, so we don't - // mark it. - o := c.oplook(p) - return o.size > 4 && o.flag&NOTUSETMP == 0 -} - -/* - * when the first reference to the literal pool threatens - * to go out of range of a 1Mb PC-relative offset - * drop the pool now, and branch round it. - */ -func (c *ctxt7) checkpool(p *obj.Prog, skip int) { - if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) { - c.flushpool(p, skip) - } else if p.Link == nil { - c.flushpool(p, 2) - } -} - -func (c *ctxt7) flushpool(p *obj.Prog, skip int) { - if c.blitrl != nil { - if skip != 0 { - if c.ctxt.Debugvlog && skip == 1 { - fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) - } - q := c.newprog() - q.As = AB - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(p.Link) - q.Link = c.blitrl - q.Pos = p.Pos - c.blitrl = q - } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp { - return - } - - // The line number for constant pool entries doesn't really matter. - // We set it to the line number of the preceding instruction so that - // there are no deltas to encode in the pc-line tables. - for q := c.blitrl; q != nil; q = q.Link { - q.Pos = p.Pos - } - - c.elitrl.Link = p.Link - p.Link = c.blitrl - - c.blitrl = nil /* BUG: should refer back to values until out-of-range */ - c.elitrl = nil - c.pool.size = 0 - c.pool.start = 0 - } -} - -/* - * MOVD foo(SB), R is actually - * MOVD addr, REGTMP - * MOVD REGTMP, R - * where addr is the address of the DWORD containing the address of foo. - * - * TODO: hash - */ -func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) { - cls := c.aclass(a) - lit := c.instoffset - t := c.newprog() - t.As = AWORD - sz := 4 - - if a.Type == obj.TYPE_CONST { - if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) { - // out of range -0x80000000 ~ 0xffffffff, must store 64-bit - t.As = ADWORD - sz = 8 - } // else store 32-bit - } else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) { - // conservative: don't know if we want signed or unsigned extension. - // in case of ambiguity, store 64-bit - t.As = ADWORD - sz = 8 - } - - switch cls { - // TODO(aram): remove. - default: - if a.Name != obj.NAME_EXTERN { - fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p) - } - - t.To.Offset = a.Offset - t.To.Sym = a.Sym - t.To.Type = a.Type - t.To.Name = a.Name - - /* This is here because MOV uint12<<12, R is disabled in optab. - Because of this, we need to load the constant from memory. */ - case C_ADDCON: - fallthrough - - case C_ZAUTO, - C_PSAUTO, - C_PSAUTO_8, - C_PSAUTO_4, - C_PPAUTO, - C_UAUTO4K_8, - C_UAUTO4K_4, - C_UAUTO4K_2, - C_UAUTO4K, - C_UAUTO8K_8, - C_UAUTO8K_4, - C_UAUTO8K, - C_UAUTO16K_8, - C_UAUTO16K, - C_UAUTO32K, - C_NSAUTO_8, - C_NSAUTO_4, - C_NSAUTO, - C_NPAUTO, - C_NAUTO4K, - C_LAUTO, - C_PPOREG, - C_PSOREG, - C_PSOREG_4, - C_PSOREG_8, - C_UOREG4K_8, - C_UOREG4K_4, - C_UOREG4K_2, - C_UOREG4K, - C_UOREG8K_8, - C_UOREG8K_4, - C_UOREG8K, - C_UOREG16K_8, - C_UOREG16K, - C_UOREG32K, - C_NSOREG_8, - C_NSOREG_4, - C_NSOREG, - C_NPOREG, - C_NOREG4K, - C_LOREG, - C_LACON, - C_ADDCON2, - C_LCON, - C_VCON: - if a.Name == obj.NAME_EXTERN { - fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p) - } - - t.To.Type = obj.TYPE_CONST - t.To.Offset = lit - break - } - - for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ - if q.To == t.To { - p.Pool = q - return - } - } - - q := c.newprog() - *q = *t - q.Pc = int64(c.pool.size) - if c.blitrl == nil { - c.blitrl = q - c.pool.start = uint32(p.Pc) - } else { - c.elitrl.Link = q - } - c.elitrl = q - c.pool.size = -c.pool.size & (funcAlign - 1) - c.pool.size += uint32(sz) - p.Pool = q -} - -func (c *ctxt7) regoff(a *obj.Addr) uint32 { - c.instoffset = 0 - c.aclass(a) - return uint32(c.instoffset) -} - -func isSTLXRop(op obj.As) bool { - switch op { - case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH, - ASTXR, ASTXRW, ASTXRB, ASTXRH: - return true - } - return false -} - -func isSTXPop(op obj.As) bool { - switch op { - case ASTXP, ASTLXP, ASTXPW, ASTLXPW: - return true - } - return false -} - -func isANDop(op obj.As) bool { - switch op { - case AAND, AORR, AEOR, AANDS, ATST, - ABIC, AEON, AORN, ABICS: - return true - } - return false -} - -func isANDWop(op obj.As) bool { - switch op { - case AANDW, AORRW, AEORW, AANDSW, ATSTW, - ABICW, AEONW, AORNW, ABICSW: - return true - } - return false -} - -func isADDop(op obj.As) bool { - switch op { - case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP: - return true - } - return false -} - -func isADDWop(op obj.As) bool { - switch op { - case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW: - return true - } - return false -} - -func isRegShiftOrExt(a *obj.Addr) bool { - return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0 -} - -// Maximum PC-relative displacement. -// The actual limit is ±2²⁰, but we are conservative -// to avoid needing to recompute the literal pool flush points -// as span-dependent jumps are enlarged. -const maxPCDisp = 512 * 1024 - -// ispcdisp reports whether v is a valid PC-relative displacement. -func ispcdisp(v int32) bool { - return -maxPCDisp < v && v < maxPCDisp && v&3 == 0 -} - -func isaddcon(v int64) bool { - /* uimm12 or uimm24? */ - if v < 0 { - return false - } - if (v & 0xFFF) == 0 { - v >>= 12 - } - return v <= 0xFFF -} - -func isaddcon2(v int64) bool { - return 0 <= v && v <= 0xFFFFFF -} - -// isbitcon reports whether a constant can be encoded into a logical instruction. -// bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64, -// which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones. -// special cases: 0 and -1 are not bitcon. -// this function needs to run against virtually all the constants, so it needs to be fast. -// for this reason, bitcon testing and bitcon encoding are separate functions. -func isbitcon(x uint64) bool { - if x == 1<<64-1 || x == 0 { - return false - } - // determine the period and sign-extend a unit to 64 bits - switch { - case x != x>>32|x<<32: - // period is 64 - // nothing to do - case x != x>>16|x<<48: - // period is 32 - x = uint64(int64(int32(x))) - case x != x>>8|x<<56: - // period is 16 - x = uint64(int64(int16(x))) - case x != x>>4|x<<60: - // period is 8 - x = uint64(int64(int8(x))) - default: - // period is 4 or 2, always true - // 0001, 0010, 0100, 1000 -- 0001 rotate - // 0011, 0110, 1100, 1001 -- 0011 rotate - // 0111, 1011, 1101, 1110 -- 0111 rotate - // 0101, 1010 -- 01 rotate, repeat - return true - } - return sequenceOfOnes(x) || sequenceOfOnes(^x) -} - -// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros -func sequenceOfOnes(x uint64) bool { - y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2 - y += x - return (y-1)&y == 0 -} - -// bitconEncode returns the encoding of a bitcon used in logical instructions -// x is known to be a bitcon -// a bitcon is a sequence of n ones at low bits (i.e. 1<>32|x<<32: - period = 64 - case x != x>>16|x<<48: - period = 32 - x = uint64(int64(int32(x))) - case x != x>>8|x<<56: - period = 16 - x = uint64(int64(int16(x))) - case x != x>>4|x<<60: - period = 8 - x = uint64(int64(int8(x))) - case x != x>>2|x<<62: - period = 4 - x = uint64(int64(x<<60) >> 60) - default: - period = 2 - x = uint64(int64(x<<62) >> 62) - } - neg := false - if int64(x) < 0 { - x = ^x - neg = true - } - y := x & -x // lowest set bit of x. - s := log2(y) - n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits - if neg { - // ^x is a sequence of n ones left shifted by s bits - // adjust n, s for x - s = n + s - n = period - n - } - - N := uint32(0) - if mode == 64 && period == 64 { - N = 1 - } - R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate - S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period - return N<<22 | R<<16 | S<<10 -} - -func log2(x uint64) uint32 { - if x == 0 { - panic("log2 of 0") - } - n := uint32(0) - if x >= 1<<32 { - x >>= 32 - n += 32 - } - if x >= 1<<16 { - x >>= 16 - n += 16 - } - if x >= 1<<8 { - x >>= 8 - n += 8 - } - if x >= 1<<4 { - x >>= 4 - n += 4 - } - if x >= 1<<2 { - x >>= 2 - n += 2 - } - if x >= 1<<1 { - x >>= 1 - n += 1 - } - return n -} - -func autoclass(l int64) int { - if l == 0 { - return C_ZAUTO - } - - if l < 0 { - if l >= -256 && (l&7) == 0 { - return C_NSAUTO_8 - } - if l >= -256 && (l&3) == 0 { - return C_NSAUTO_4 - } - if l >= -256 { - return C_NSAUTO - } - if l >= -512 && (l&7) == 0 { - return C_NPAUTO - } - if l >= -4095 { - return C_NAUTO4K - } - return C_LAUTO - } - - if l <= 255 { - if (l & 7) == 0 { - return C_PSAUTO_8 - } - if (l & 3) == 0 { - return C_PSAUTO_4 - } - return C_PSAUTO - } - if l <= 504 && l&7 == 0 { - return C_PPAUTO - } - if l <= 4095 { - if l&7 == 0 { - return C_UAUTO4K_8 - } - if l&3 == 0 { - return C_UAUTO4K_4 - } - if l&1 == 0 { - return C_UAUTO4K_2 - } - return C_UAUTO4K - } - if l <= 8190 { - if l&7 == 0 { - return C_UAUTO8K_8 - } - if l&3 == 0 { - return C_UAUTO8K_4 - } - if l&1 == 0 { - return C_UAUTO8K - } - } - if l <= 16380 { - if l&7 == 0 { - return C_UAUTO16K_8 - } - if l&3 == 0 { - return C_UAUTO16K - } - } - if l <= 32760 && (l&7) == 0 { - return C_UAUTO32K - } - return C_LAUTO -} - -func oregclass(l int64) int { - return autoclass(l) - C_ZAUTO + C_ZOREG -} - -/* - * given an offset v and a class c (see above) - * return the offset value to use in the instruction, - * scaled if necessary - */ -func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 { - s := 0 - if cls >= C_SEXT1 && cls <= C_SEXT16 { - s = cls - C_SEXT1 - } else { - switch cls { - case C_UAUTO4K, C_UOREG4K, C_ZOREG: - s = 0 - case C_UAUTO8K, C_UOREG8K: - s = 1 - case C_UAUTO16K, C_UOREG16K: - s = 2 - case C_UAUTO32K, C_UOREG32K: - s = 3 - default: - c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p) - } - } - vs := v >> uint(s) - if vs<= REG_ARNG && r < REG_ELEM: - return C_ARNG - case r >= REG_ELEM && r < REG_ELEM_END: - return C_ELEM - case r >= REG_UXTB && r < REG_SPECIAL: - return C_EXTREG - case r >= REG_SPECIAL: - return C_SPR - } - return C_GOK -} - -// con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit, -// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it. -func (c *ctxt7) con32class(a *obj.Addr) int { - v := uint32(a.Offset) - if v == 0 { - return C_ZCON - } - if isaddcon(int64(v)) { - if v <= 0xFFF { - if isbitcon(uint64(a.Offset)) { - return C_ABCON0 - } - return C_ADDCON0 - } - if isbitcon(uint64(a.Offset)) { - return C_ABCON - } - if movcon(int64(v)) >= 0 { - return C_AMCON - } - if movcon(int64(^v)) >= 0 { - return C_AMCON - } - return C_ADDCON - } - - t := movcon(int64(v)) - if t >= 0 { - if isbitcon(uint64(a.Offset)) { - return C_MBCON - } - return C_MOVCON - } - - t = movcon(int64(^v)) - if t >= 0 { - if isbitcon(uint64(a.Offset)) { - return C_MBCON - } - return C_MOVCON - } - - if isbitcon(uint64(a.Offset)) { - return C_BITCON - } - - if 0 <= v && v <= 0xffffff { - return C_ADDCON2 - } - return C_LCON -} - -// con64class reclassifies the constant of C_VCON and C_LCON class. -func (c *ctxt7) con64class(a *obj.Addr) int { - zeroCount := 0 - negCount := 0 - for i := uint(0); i < 4; i++ { - immh := uint32(a.Offset >> (i * 16) & 0xffff) - if immh == 0 { - zeroCount++ - } else if immh == 0xffff { - negCount++ - } - } - if zeroCount >= 3 || negCount >= 3 { - return C_MOVCON - } else if zeroCount == 2 || negCount == 2 { - return C_MOVCON2 - } else if zeroCount == 1 || negCount == 1 { - return C_MOVCON3 - } else { - return C_VCON - } -} - -func (c *ctxt7) aclass(a *obj.Addr) int { - switch a.Type { - case obj.TYPE_NONE: - return C_NONE - - case obj.TYPE_REG: - return rclass(a.Reg) - - case obj.TYPE_REGREG: - return C_PAIR - - case obj.TYPE_SHIFT: - return C_SHIFT - - case obj.TYPE_REGLIST: - return C_LIST - - case obj.TYPE_MEM: - // The base register should be an integer register. - if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) { - break - } - switch a.Name { - case obj.NAME_EXTERN, obj.NAME_STATIC: - if a.Sym == nil { - break - } - c.instoffset = a.Offset - if a.Sym != nil { // use relocation - if a.Sym.Type == objabi.STLSBSS { - if c.ctxt.Flag_shared { - return C_TLS_IE - } else { - return C_TLS_LE - } - } - return C_ADDR - } - return C_LEXT - - case obj.NAME_GOTREF: - return C_GOTADDR - - case obj.NAME_AUTO: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-SP. - a.Reg = obj.REG_NONE - } - // The frame top 8 or 16 bytes are for FP - c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) - return autoclass(c.instoffset) - - case obj.NAME_PARAM: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-FP. - a.Reg = obj.REG_NONE - } - c.instoffset = int64(c.autosize) + a.Offset + 8 - return autoclass(c.instoffset) - - case obj.NAME_NONE: - if a.Index != 0 { - if a.Offset != 0 { - if isRegShiftOrExt(a) { - // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2). - return C_ROFF - } - return C_GOK - } - // register offset, (Rn)(Rm) - return C_ROFF - } - c.instoffset = a.Offset - return oregclass(c.instoffset) - } - return C_GOK - - case obj.TYPE_FCONST: - return C_FCON - - case obj.TYPE_TEXTSIZE: - return C_TEXTSIZE - - case obj.TYPE_CONST, obj.TYPE_ADDR: - switch a.Name { - case obj.NAME_NONE: - c.instoffset = a.Offset - if a.Reg != 0 && a.Reg != REGZERO { - break - } - v := c.instoffset - if v == 0 { - return C_ZCON - } - if isaddcon(v) { - if v <= 0xFFF { - if isbitcon(uint64(v)) { - return C_ABCON0 - } - return C_ADDCON0 - } - if isbitcon(uint64(v)) { - return C_ABCON - } - if movcon(v) >= 0 { - return C_AMCON - } - if movcon(^v) >= 0 { - return C_AMCON - } - return C_ADDCON - } - - t := movcon(v) - if t >= 0 { - if isbitcon(uint64(v)) { - return C_MBCON - } - return C_MOVCON - } - - t = movcon(^v) - if t >= 0 { - if isbitcon(uint64(v)) { - return C_MBCON - } - return C_MOVCON - } - - if isbitcon(uint64(v)) { - return C_BITCON - } - - if 0 <= v && v <= 0xffffff { - return C_ADDCON2 - } - - if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { - return C_LCON - } - return C_VCON - - case obj.NAME_EXTERN, obj.NAME_STATIC: - if a.Sym == nil { - return C_GOK - } - if a.Sym.Type == objabi.STLSBSS { - c.ctxt.Diag("taking address of TLS variable is not supported") - } - c.instoffset = a.Offset - return C_VCONADDR - - case obj.NAME_AUTO: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-SP. - a.Reg = obj.REG_NONE - } - // The frame top 8 or 16 bytes are for FP - c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) - - case obj.NAME_PARAM: - if a.Reg == REGSP { - // unset base register for better printing, since - // a.Offset is still relative to pseudo-FP. - a.Reg = obj.REG_NONE - } - c.instoffset = int64(c.autosize) + a.Offset + 8 - default: - return C_GOK - } - cf := c.instoffset - if isaddcon(cf) || isaddcon(-cf) { - return C_AACON - } - if isaddcon2(cf) { - return C_AACON2 - } - - return C_LACON - - case obj.TYPE_BRANCH: - return C_SBRA - } - - return C_GOK -} - -func oclass(a *obj.Addr) int { - return int(a.Class) - 1 -} - -func (c *ctxt7) oplook(p *obj.Prog) *Optab { - a1 := int(p.Optab) - if a1 != 0 { - return &optab[a1-1] - } - a1 = int(p.From.Class) - if a1 == 0 { - a0 := c.aclass(&p.From) - // do not break C_ADDCON2 when S bit is set - if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 { - a0 = C_LCON - } - a1 = a0 + 1 - p.From.Class = int8(a1) - // more specific classification of 32-bit integers - if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE { - if p.As == AMOVW || isADDWop(p.As) { - ra0 := c.con32class(&p.From) - // do not break C_ADDCON2 when S bit is set - if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 { - ra0 = C_LCON - } - a1 = ra0 + 1 - p.From.Class = int8(a1) - } - if isANDWop(p.As) && a0 != C_BITCON { - // For 32-bit logical instruction with constant, - // the BITCON test is special in that it looks at - // the 64-bit which has the high 32-bit as a copy - // of the low 32-bit. We have handled that and - // don't pass it to con32class. - a1 = c.con32class(&p.From) + 1 - p.From.Class = int8(a1) - } - if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) { - a1 = c.con64class(&p.From) + 1 - p.From.Class = int8(a1) - } - } - } - - a1-- - a3 := C_NONE + 1 - if p.GetFrom3() != nil { - a3 = int(p.GetFrom3().Class) - if a3 == 0 { - a3 = c.aclass(p.GetFrom3()) + 1 - p.GetFrom3().Class = int8(a3) - } - } - - a3-- - a4 := int(p.To.Class) - if a4 == 0 { - a4 = c.aclass(&p.To) + 1 - p.To.Class = int8(a4) - } - - a4-- - a2 := C_NONE - if p.Reg != 0 { - a2 = rclass(p.Reg) - } - - if false { - fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4) - fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) - } - - ops := oprange[p.As&obj.AMask] - c1 := &xcmp[a1] - c2 := &xcmp[a2] - c3 := &xcmp[a3] - c4 := &xcmp[a4] - c5 := &xcmp[p.Scond>>5] - for i := range ops { - op := &ops[i] - if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] { - p.Optab = uint16(cap(optab) - cap(ops) + i + 1) - return op - } - } - - c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type) - // Turn illegal instruction into an UNDEF, avoid crashing in asmout - return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0} -} - -func cmp(a int, b int) bool { - if a == b { - return true - } - switch a { - case C_RSP: - if b == C_REG { - return true - } - - case C_REG: - if b == C_ZCON { - return true - } - - case C_ADDCON0: - if b == C_ZCON || b == C_ABCON0 { - return true - } - - case C_ADDCON: - if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON { - return true - } - - case C_BITCON: - if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { - return true - } - - case C_MOVCON: - if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON { - return true - } - - case C_ADDCON2: - if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 { - return true - } - - case C_LCON: - if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON { - return true - } - - case C_MOVCON2: - return cmp(C_LCON, b) - - case C_VCON: - return cmp(C_LCON, b) - - case C_LACON: - if b == C_AACON || b == C_AACON2 { - return true - } - - case C_SEXT2: - if b == C_SEXT1 { - return true - } - - case C_SEXT4: - if b == C_SEXT1 || b == C_SEXT2 { - return true - } - - case C_SEXT8: - if b >= C_SEXT1 && b <= C_SEXT4 { - return true - } - - case C_SEXT16: - if b >= C_SEXT1 && b <= C_SEXT8 { - return true - } - - case C_LEXT: - if b >= C_SEXT1 && b <= C_SEXT16 { - return true - } - - case C_NSAUTO_4: - if b == C_NSAUTO_8 { - return true - } - - case C_NSAUTO: - switch b { - case C_NSAUTO_4, C_NSAUTO_8: - return true - } - - case C_NPAUTO: - switch b { - case C_NSAUTO_8: - return true - } - - case C_NAUTO4K: - switch b { - case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO: - return true - } - - case C_PSAUTO_8: - if b == C_ZAUTO { - return true - } - - case C_PSAUTO_4: - switch b { - case C_ZAUTO, C_PSAUTO_8: - return true - } - - case C_PSAUTO: - switch b { - case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4: - return true - } - - case C_PPAUTO: - switch b { - case C_ZAUTO, C_PSAUTO_8: - return true - } - - case C_UAUTO4K: - switch b { - case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, - C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8: - return true - } - - case C_UAUTO8K: - switch b { - case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, - C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8: - return true - } - - case C_UAUTO16K: - switch b { - case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, - C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8: - return true - } - - case C_UAUTO32K: - switch b { - case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, - C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8: - return true - } - - case C_LAUTO: - switch b { - case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO, - C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, - C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, - C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, - C_UAUTO16K, C_UAUTO16K_8, - C_UAUTO32K: - return true - } - - case C_NSOREG_4: - if b == C_NSOREG_8 { - return true - } - - case C_NSOREG: - switch b { - case C_NSOREG_4, C_NSOREG_8: - return true - } - - case C_NPOREG: - switch b { - case C_NSOREG_8: - return true - } - - case C_NOREG4K: - switch b { - case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG: - return true - } - - case C_PSOREG_4: - switch b { - case C_ZOREG, C_PSOREG_8: - return true - } - - case C_PSOREG: - switch b { - case C_ZOREG, C_PSOREG_8, C_PSOREG_4: - return true - } - - case C_PPOREG: - switch b { - case C_ZOREG, C_PSOREG_8: - return true - } - - case C_UOREG4K: - switch b { - case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, - C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8: - return true - } - - case C_UOREG8K: - switch b { - case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, - C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, - C_UOREG8K_4, C_UOREG8K_8: - return true - } - - case C_UOREG16K: - switch b { - case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, - C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, - C_UOREG8K_8, C_UOREG16K_8: - return true - } - - case C_UOREG32K: - switch b { - case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, - C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8: - return true - } - - case C_LOREG: - switch b { - case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG, - C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG, - C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, - C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, - C_UOREG16K, C_UOREG16K_8, - C_UOREG32K: - return true - } - - case C_LBRA: - if b == C_SBRA { - return true - } - } - - return false -} - -type ocmp []Optab - -func (x ocmp) Len() int { - return len(x) -} - -func (x ocmp) Swap(i, j int) { - x[i], x[j] = x[j], x[i] -} - -func (x ocmp) Less(i, j int) bool { - p1 := &x[i] - p2 := &x[j] - if p1.as != p2.as { - return p1.as < p2.as - } - if p1.a1 != p2.a1 { - return p1.a1 < p2.a1 - } - if p1.a2 != p2.a2 { - return p1.a2 < p2.a2 - } - if p1.a3 != p2.a3 { - return p1.a3 < p2.a3 - } - if p1.a4 != p2.a4 { - return p1.a4 < p2.a4 - } - if p1.scond != p2.scond { - return p1.scond < p2.scond - } - return false -} - -func oprangeset(a obj.As, t []Optab) { - oprange[a&obj.AMask] = t -} - -func buildop(ctxt *obj.Link) { - if oprange[AAND&obj.AMask] != nil { - // Already initialized; stop now. - // This happens in the cmd/asm tests, - // each of which re-initializes the arch. - return - } - - var n int - for i := 0; i < C_GOK; i++ { - for n = 0; n < C_GOK; n++ { - if cmp(n, i) { - xcmp[i][n] = true - } - } - } - for n = 0; optab[n].as != obj.AXXX; n++ { - } - sort.Sort(ocmp(optab[:n])) - for i := 0; i < n; i++ { - r := optab[i].as - start := i - for optab[i].as == r { - i++ - } - t := optab[start:i] - i-- - oprangeset(r, t) - switch r { - default: - ctxt.Diag("unknown op in build: %v", r) - ctxt.DiagFlush() - log.Fatalf("bad code") - - case AADD: - oprangeset(AADDS, t) - oprangeset(ASUB, t) - oprangeset(ASUBS, t) - oprangeset(AADDW, t) - oprangeset(AADDSW, t) - oprangeset(ASUBW, t) - oprangeset(ASUBSW, t) - - case AAND: /* logical immediate, logical shifted register */ - oprangeset(AANDW, t) - oprangeset(AEOR, t) - oprangeset(AEORW, t) - oprangeset(AORR, t) - oprangeset(AORRW, t) - oprangeset(ABIC, t) - oprangeset(ABICW, t) - oprangeset(AEON, t) - oprangeset(AEONW, t) - oprangeset(AORN, t) - oprangeset(AORNW, t) - - case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */ - oprangeset(AANDSW, t) - oprangeset(ABICS, t) - oprangeset(ABICSW, t) - - case ANEG: - oprangeset(ANEGS, t) - oprangeset(ANEGSW, t) - oprangeset(ANEGW, t) - - case AADC: /* rn=Rd */ - oprangeset(AADCW, t) - - oprangeset(AADCS, t) - oprangeset(AADCSW, t) - oprangeset(ASBC, t) - oprangeset(ASBCW, t) - oprangeset(ASBCS, t) - oprangeset(ASBCSW, t) - - case ANGC: /* rn=REGZERO */ - oprangeset(ANGCW, t) - - oprangeset(ANGCS, t) - oprangeset(ANGCSW, t) - - case ACMP: - oprangeset(ACMPW, t) - oprangeset(ACMN, t) - oprangeset(ACMNW, t) - - case ATST: - oprangeset(ATSTW, t) - - /* register/register, and shifted */ - case AMVN: - oprangeset(AMVNW, t) - - case AMOVK: - oprangeset(AMOVKW, t) - oprangeset(AMOVN, t) - oprangeset(AMOVNW, t) - oprangeset(AMOVZ, t) - oprangeset(AMOVZW, t) - - case ASWPD: - for i := range atomicInstructions { - oprangeset(i, t) - } - - case ABEQ: - oprangeset(ABNE, t) - oprangeset(ABCS, t) - oprangeset(ABHS, t) - oprangeset(ABCC, t) - oprangeset(ABLO, t) - oprangeset(ABMI, t) - oprangeset(ABPL, t) - oprangeset(ABVS, t) - oprangeset(ABVC, t) - oprangeset(ABHI, t) - oprangeset(ABLS, t) - oprangeset(ABGE, t) - oprangeset(ABLT, t) - oprangeset(ABGT, t) - oprangeset(ABLE, t) - - case ALSL: - oprangeset(ALSLW, t) - oprangeset(ALSR, t) - oprangeset(ALSRW, t) - oprangeset(AASR, t) - oprangeset(AASRW, t) - oprangeset(AROR, t) - oprangeset(ARORW, t) - - case ACLS: - oprangeset(ACLSW, t) - oprangeset(ACLZ, t) - oprangeset(ACLZW, t) - oprangeset(ARBIT, t) - oprangeset(ARBITW, t) - oprangeset(AREV, t) - oprangeset(AREVW, t) - oprangeset(AREV16, t) - oprangeset(AREV16W, t) - oprangeset(AREV32, t) - - case ASDIV: - oprangeset(ASDIVW, t) - oprangeset(AUDIV, t) - oprangeset(AUDIVW, t) - oprangeset(ACRC32B, t) - oprangeset(ACRC32CB, t) - oprangeset(ACRC32CH, t) - oprangeset(ACRC32CW, t) - oprangeset(ACRC32CX, t) - oprangeset(ACRC32H, t) - oprangeset(ACRC32W, t) - oprangeset(ACRC32X, t) - - case AMADD: - oprangeset(AMADDW, t) - oprangeset(AMSUB, t) - oprangeset(AMSUBW, t) - oprangeset(ASMADDL, t) - oprangeset(ASMSUBL, t) - oprangeset(AUMADDL, t) - oprangeset(AUMSUBL, t) - - case AREM: - oprangeset(AREMW, t) - oprangeset(AUREM, t) - oprangeset(AUREMW, t) - - case AMUL: - oprangeset(AMULW, t) - oprangeset(AMNEG, t) - oprangeset(AMNEGW, t) - oprangeset(ASMNEGL, t) - oprangeset(ASMULL, t) - oprangeset(ASMULH, t) - oprangeset(AUMNEGL, t) - oprangeset(AUMULH, t) - oprangeset(AUMULL, t) - - case AMOVB: - oprangeset(AMOVBU, t) - - case AMOVH: - oprangeset(AMOVHU, t) - - case AMOVW: - oprangeset(AMOVWU, t) - - case ABFM: - oprangeset(ABFMW, t) - oprangeset(ASBFM, t) - oprangeset(ASBFMW, t) - oprangeset(AUBFM, t) - oprangeset(AUBFMW, t) - - case ABFI: - oprangeset(ABFIW, t) - oprangeset(ABFXIL, t) - oprangeset(ABFXILW, t) - oprangeset(ASBFIZ, t) - oprangeset(ASBFIZW, t) - oprangeset(ASBFX, t) - oprangeset(ASBFXW, t) - oprangeset(AUBFIZ, t) - oprangeset(AUBFIZW, t) - oprangeset(AUBFX, t) - oprangeset(AUBFXW, t) - - case AEXTR: - oprangeset(AEXTRW, t) - - case ASXTB: - oprangeset(ASXTBW, t) - oprangeset(ASXTH, t) - oprangeset(ASXTHW, t) - oprangeset(ASXTW, t) - oprangeset(AUXTB, t) - oprangeset(AUXTH, t) - oprangeset(AUXTW, t) - oprangeset(AUXTBW, t) - oprangeset(AUXTHW, t) - - case ACCMN: - oprangeset(ACCMNW, t) - oprangeset(ACCMP, t) - oprangeset(ACCMPW, t) - - case ACSEL: - oprangeset(ACSELW, t) - oprangeset(ACSINC, t) - oprangeset(ACSINCW, t) - oprangeset(ACSINV, t) - oprangeset(ACSINVW, t) - oprangeset(ACSNEG, t) - oprangeset(ACSNEGW, t) - - case ACINC: - // aliases Rm=Rn, !cond - oprangeset(ACINCW, t) - oprangeset(ACINV, t) - oprangeset(ACINVW, t) - oprangeset(ACNEG, t) - oprangeset(ACNEGW, t) - - // aliases, Rm=Rn=REGZERO, !cond - case ACSET: - oprangeset(ACSETW, t) - - oprangeset(ACSETM, t) - oprangeset(ACSETMW, t) - - case AMOVD, - AMOVBU, - AB, - ABL, - AWORD, - ADWORD, - obj.ARET, - obj.ATEXT: - break - - case ALDP: - oprangeset(AFLDPD, t) - - case ASTP: - oprangeset(AFSTPD, t) - - case ASTPW: - oprangeset(AFSTPS, t) - - case ALDPW: - oprangeset(ALDPSW, t) - oprangeset(AFLDPS, t) - - case AERET: - oprangeset(AWFE, t) - oprangeset(AWFI, t) - oprangeset(AYIELD, t) - oprangeset(ASEV, t) - oprangeset(ASEVL, t) - oprangeset(ANOOP, t) - oprangeset(ADRPS, t) - - case ACBZ: - oprangeset(ACBZW, t) - oprangeset(ACBNZ, t) - oprangeset(ACBNZW, t) - - case ATBZ: - oprangeset(ATBNZ, t) - - case AADR, AADRP: - break - - case ACLREX: - break - - case ASVC: - oprangeset(AHVC, t) - oprangeset(AHLT, t) - oprangeset(ASMC, t) - oprangeset(ABRK, t) - oprangeset(ADCPS1, t) - oprangeset(ADCPS2, t) - oprangeset(ADCPS3, t) - - case AFADDS: - oprangeset(AFADDD, t) - oprangeset(AFSUBS, t) - oprangeset(AFSUBD, t) - oprangeset(AFMULS, t) - oprangeset(AFMULD, t) - oprangeset(AFNMULS, t) - oprangeset(AFNMULD, t) - oprangeset(AFDIVS, t) - oprangeset(AFMAXD, t) - oprangeset(AFMAXS, t) - oprangeset(AFMIND, t) - oprangeset(AFMINS, t) - oprangeset(AFMAXNMD, t) - oprangeset(AFMAXNMS, t) - oprangeset(AFMINNMD, t) - oprangeset(AFMINNMS, t) - oprangeset(AFDIVD, t) - - case AFMSUBD: - oprangeset(AFMSUBS, t) - oprangeset(AFMADDS, t) - oprangeset(AFMADDD, t) - oprangeset(AFNMSUBS, t) - oprangeset(AFNMSUBD, t) - oprangeset(AFNMADDS, t) - oprangeset(AFNMADDD, t) - - case AFCVTSD: - oprangeset(AFCVTDS, t) - oprangeset(AFABSD, t) - oprangeset(AFABSS, t) - oprangeset(AFNEGD, t) - oprangeset(AFNEGS, t) - oprangeset(AFSQRTD, t) - oprangeset(AFSQRTS, t) - oprangeset(AFRINTNS, t) - oprangeset(AFRINTND, t) - oprangeset(AFRINTPS, t) - oprangeset(AFRINTPD, t) - oprangeset(AFRINTMS, t) - oprangeset(AFRINTMD, t) - oprangeset(AFRINTZS, t) - oprangeset(AFRINTZD, t) - oprangeset(AFRINTAS, t) - oprangeset(AFRINTAD, t) - oprangeset(AFRINTXS, t) - oprangeset(AFRINTXD, t) - oprangeset(AFRINTIS, t) - oprangeset(AFRINTID, t) - oprangeset(AFCVTDH, t) - oprangeset(AFCVTHS, t) - oprangeset(AFCVTHD, t) - oprangeset(AFCVTSH, t) - - case AFCMPS: - oprangeset(AFCMPD, t) - oprangeset(AFCMPES, t) - oprangeset(AFCMPED, t) - - case AFCCMPS: - oprangeset(AFCCMPD, t) - oprangeset(AFCCMPES, t) - oprangeset(AFCCMPED, t) - - case AFCSELD: - oprangeset(AFCSELS, t) - - case AFMOVS, AFMOVD, AFMOVQ: - break - - case AFCVTZSD: - oprangeset(AFCVTZSDW, t) - oprangeset(AFCVTZSS, t) - oprangeset(AFCVTZSSW, t) - oprangeset(AFCVTZUD, t) - oprangeset(AFCVTZUDW, t) - oprangeset(AFCVTZUS, t) - oprangeset(AFCVTZUSW, t) - - case ASCVTFD: - oprangeset(ASCVTFS, t) - oprangeset(ASCVTFWD, t) - oprangeset(ASCVTFWS, t) - oprangeset(AUCVTFD, t) - oprangeset(AUCVTFS, t) - oprangeset(AUCVTFWD, t) - oprangeset(AUCVTFWS, t) - - case ASYS: - oprangeset(AAT, t) - oprangeset(ADC, t) - oprangeset(AIC, t) - oprangeset(ATLBI, t) - - case ASYSL, AHINT: - break - - case ADMB: - oprangeset(ADSB, t) - oprangeset(AISB, t) - - case AMRS, AMSR: - break - - case ALDAR: - oprangeset(ALDARW, t) - oprangeset(ALDARB, t) - oprangeset(ALDARH, t) - fallthrough - - case ALDXR: - oprangeset(ALDXRB, t) - oprangeset(ALDXRH, t) - oprangeset(ALDXRW, t) - - case ALDAXR: - oprangeset(ALDAXRB, t) - oprangeset(ALDAXRH, t) - oprangeset(ALDAXRW, t) - - case ALDXP: - oprangeset(ALDXPW, t) - oprangeset(ALDAXP, t) - oprangeset(ALDAXPW, t) - - case ASTLR: - oprangeset(ASTLRB, t) - oprangeset(ASTLRH, t) - oprangeset(ASTLRW, t) - - case ASTXR: - oprangeset(ASTXRB, t) - oprangeset(ASTXRH, t) - oprangeset(ASTXRW, t) - - case ASTLXR: - oprangeset(ASTLXRB, t) - oprangeset(ASTLXRH, t) - oprangeset(ASTLXRW, t) - - case ASTXP: - oprangeset(ASTLXP, t) - oprangeset(ASTLXPW, t) - oprangeset(ASTXPW, t) - - case AVADDP: - oprangeset(AVAND, t) - oprangeset(AVCMEQ, t) - oprangeset(AVORR, t) - oprangeset(AVEOR, t) - oprangeset(AVBSL, t) - oprangeset(AVBIT, t) - oprangeset(AVCMTST, t) - oprangeset(AVUZP1, t) - oprangeset(AVUZP2, t) - oprangeset(AVBIF, t) - - case AVADD: - oprangeset(AVSUB, t) - - case AAESD: - oprangeset(AAESE, t) - oprangeset(AAESMC, t) - oprangeset(AAESIMC, t) - oprangeset(ASHA1SU1, t) - oprangeset(ASHA256SU0, t) - oprangeset(ASHA512SU0, t) - - case ASHA1C: - oprangeset(ASHA1P, t) - oprangeset(ASHA1M, t) - - case ASHA256H: - oprangeset(ASHA256H2, t) - oprangeset(ASHA512H, t) - oprangeset(ASHA512H2, t) - - case ASHA1SU0: - oprangeset(ASHA256SU1, t) - oprangeset(ASHA512SU1, t) - - case AVADDV: - oprangeset(AVUADDLV, t) - - case AVFMLA: - oprangeset(AVFMLS, t) - - case AVPMULL: - oprangeset(AVPMULL2, t) - - case AVUSHR: - oprangeset(AVSHL, t) - oprangeset(AVSRI, t) - - case AVREV32: - oprangeset(AVCNT, t) - oprangeset(AVRBIT, t) - oprangeset(AVREV64, t) - oprangeset(AVREV16, t) - - case AVZIP1: - oprangeset(AVZIP2, t) - - case AVUXTL: - oprangeset(AVUXTL2, t) - - case AVUSHLL: - oprangeset(AVUSHLL2, t) - - case AVLD1R: - oprangeset(AVLD2, t) - oprangeset(AVLD2R, t) - oprangeset(AVLD3, t) - oprangeset(AVLD3R, t) - oprangeset(AVLD4, t) - oprangeset(AVLD4R, t) - - case ASHA1H, - AVCNT, - AVMOV, - AVLD1, - AVST1, - AVST2, - AVST3, - AVST4, - AVTBL, - AVDUP, - AVMOVI, - APRFM, - AVEXT: - break - - case obj.ANOP, - obj.AUNDEF, - obj.AFUNCDATA, - obj.APCALIGN, - obj.APCDATA, - obj.ADUFFZERO, - obj.ADUFFCOPY: - break - } - } -} - -// chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions. -// For details of the range of constants available, see -// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html. -func (c *ctxt7) chipfloat7(e float64) int { - ei := math.Float64bits(e) - l := uint32(int32(ei)) - h := uint32(int32(ei >> 32)) - - if l != 0 || h&0xffff != 0 { - return -1 - } - h1 := h & 0x7fc00000 - if h1 != 0x40000000 && h1 != 0x3fc00000 { - return -1 - } - n := 0 - - // sign bit (a) - if h&0x80000000 != 0 { - n |= 1 << 7 - } - - // exp sign bit (b) - if h1 == 0x3fc00000 { - n |= 1 << 6 - } - - // rest of exp and mantissa (cd-efgh) - n |= int((h >> 16) & 0x3f) - - //print("match %.8lux %.8lux %d\n", l, h, n); - return n -} - -/* form offset parameter to SYS; special register number */ -func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { - return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 -} - -func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { - return SYSARG5(0, op1, Cn, Cm, op2) -} - -// checkUnpredictable checks if the sourse and transfer registers are the same register. -// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same. -func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) { - if wback && rn != REGSP && (rn == rt1 || rn == rt2) { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - if isload && rt1 == rt2 { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } -} - -/* checkindex checks if index >= 0 && index <= maxindex */ -func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) { - if index < 0 || index > maxindex { - c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p) - } -} - -/* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */ -func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) { - var offset, list, n, expect int64 - switch as { - case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R: - offset = p.From.Offset - list = p.To.Offset - case AVST1, AVST2, AVST3, AVST4: - offset = p.To.Offset - list = p.From.Offset - default: - c.ctxt.Diag("invalid operation on op %v", p.As) - } - opcode := (list >> 12) & 15 - q := (list >> 30) & 1 - size := (list >> 10) & 3 - if offset == 0 { - return - } - switch opcode { - case 0x7: - n = 1 // one register - case 0xa: - n = 2 // two registers - case 0x6: - n = 3 // three registers - case 0x2: - n = 4 // four registers - default: - c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) - } - - switch as { - case AVLD1R, AVLD2R, AVLD3R, AVLD4R: - if offset != n*(1<> 5) & 7 - switch p.As { - case AMOVB, AMOVBU: - if amount != 0 { - c.ctxt.Diag("invalid index shift amount: %v", p) - } - case AMOVH, AMOVHU: - if amount != 1 && amount != 0 { - c.ctxt.Diag("invalid index shift amount: %v", p) - } - case AMOVW, AMOVWU, AFMOVS: - if amount != 2 && amount != 0 { - c.ctxt.Diag("invalid index shift amount: %v", p) - } - case AMOVD, AFMOVD: - if amount != 3 && amount != 0 { - c.ctxt.Diag("invalid index shift amount: %v", p) - } - default: - panic("invalid operation") - } -} - -func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { - var os [5]uint32 - o1 := uint32(0) - o2 := uint32(0) - o3 := uint32(0) - o4 := uint32(0) - o5 := uint32(0) - if false { /*debug['P']*/ - fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) - } - switch o.type_ { - default: - c.ctxt.Diag("%v: unknown asm %d", p, o.type_) - - case 0: /* pseudo ops */ - break - - case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ - o1 = c.oprrr(p, p.As) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - if r == 0 { - r = rt - } - o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ - o1 = c.opirr(p, p.As) - - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - if (o1 & Sbit) == 0 { - c.ctxt.Diag("ineffective ZR destination\n%v", p) - } - rt = REGZERO - } - - r := int(p.Reg) - if r == 0 { - r = rt - } - v := int32(c.regoff(&p.From)) - o1 = c.oaddi(p, int32(o1), v, r, rt) - - case 3: /* op R<> 10) & 63 - is64bit := o1 & (1 << 31) - if is64bit == 0 && amount >= 32 { - c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) - } - o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if p.As == AMVN || p.As == AMVNW { - r = REGZERO - } else if r == 0 { - r = rt - } - o1 |= (uint32(r&31) << 5) | uint32(rt&31) - - case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */ - rt := int(p.To.Reg) - r := int(o.param) - - if r == 0 { - r = REGZERO - } else if r == REGFROM { - r = int(p.From.Reg) - } - if r == 0 { - r = REGSP - } - - v := int32(c.regoff(&p.From)) - var op int32 - if v < 0 { - v = -v - op = int32(c.opirr(p, ASUB)) - } else { - op = int32(c.opirr(p, AADD)) - } - - if int(o.size) == 8 { - o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP) - o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt) - break - } - - o1 = c.oaddi(p, op, v, r, rt) - - case 5: /* b s; bl s */ - o1 = c.opbra(p, p.As) - - if p.To.Sym == nil { - o1 |= uint32(c.brdist(p, 0, 26, 2)) - break - } - - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - rel.Add = p.To.Offset - rel.Type = objabi.R_CALLARM64 - - case 6: /* b ,O(R); bl ,O(R) */ - o1 = c.opbrr(p, p.As) - - o1 |= uint32(p.To.Reg&31) << 5 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 0 - rel.Type = objabi.R_CALLIND - - case 7: /* beq s */ - o1 = c.opbra(p, p.As) - - o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) - - case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ - rt := int(p.To.Reg) - - rf := int(p.Reg) - if rf == 0 { - rf = rt - } - v := int32(p.From.Offset) - switch p.As { - case AASR: - o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt) - - case AASRW: - o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt) - - case ALSL: - o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt) - - case ALSLW: - o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) - - case ALSR: - o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt) - - case ALSRW: - o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt) - - case AROR: - o1 = c.opextr(p, AEXTR, v, rf, rf, rt) - - case ARORW: - o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) - - default: - c.ctxt.Diag("bad shift $con\n%v", p) - break - } - - case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ - o1 = c.oprrr(p, p.As) - - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) - - case 10: /* brk/hvc/.../svc [$con] */ - o1 = c.opimm(p, p.As) - - if p.From.Type != obj.TYPE_NONE { - o1 |= uint32((p.From.Offset & 0xffff) << 5) - } - - case 11: /* dword */ - c.aclass(&p.To) - - o1 = uint32(c.instoffset) - o2 = uint32(c.instoffset >> 32) - if p.To.Sym != nil { - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.To.Sym - rel.Add = p.To.Offset - rel.Type = objabi.R_ADDR - o2 = 0 - o1 = o2 - } - - case 12: /* movT $vcon, reg */ - // NOTE: this case does not use REGTMP. If it ever does, - // remove the NOTUSETMP flag in optab. - num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:]) - if num == 0 { - c.ctxt.Diag("invalid constant: %v", p) - } - o1 = os[0] - o2 = os[1] - o3 = os[2] - o4 = os[3] - - case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ - o := uint32(0) - num := uint8(0) - cls := oclass(&p.From) - if isADDWop(p.As) { - if !cmp(C_LCON, cls) { - c.ctxt.Diag("illegal combination: %v", p) - } - num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) - } else { - num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) - } - if num == 0 { - c.ctxt.Diag("invalid constant: %v", p) - } - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if r == 0 { - r = rt - } - if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { - o = c.opxrrr(p, p.As, false) - o |= REGTMP & 31 << 16 - o |= LSL0_64 - } else { - o = c.oprrr(p, p.As) - o |= REGTMP & 31 << 16 /* shift is 0 */ - } - - o |= uint32(r&31) << 5 - o |= uint32(rt & 31) - - os[num] = o - o1 = os[0] - o2 = os[1] - o3 = os[2] - o4 = os[3] - o5 = os[4] - - case 14: /* word */ - if c.aclass(&p.To) == C_ADDR { - c.ctxt.Diag("address constant needs DWORD\n%v", p) - } - o1 = uint32(c.instoffset) - if p.To.Sym != nil { - // This case happens with words generated - // in the PC stream as part of the literal pool. - rel := obj.Addrel(c.cursym) - - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - rel.Add = p.To.Offset - rel.Type = objabi.R_ADDR - o1 = 0 - } - - case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */ - o1 = c.oprrr(p, p.As) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - var r int - var ra int - if p.From3Type() == obj.TYPE_REG { - r = int(p.GetFrom3().Reg) - ra = int(p.Reg) - if ra == 0 { - ra = REGZERO - } - } else { - r = int(p.Reg) - if r == 0 { - r = rt - } - ra = REGZERO - } - - o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) - - case 16: /* XremY R[,R],R -> XdivY; XmsubY */ - o1 = c.oprrr(p, p.As) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if r == 0 { - r = rt - } - o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 - o2 = c.oprrr(p, AMSUBW) - o2 |= o1 & (1 << 31) /* same size */ - o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) - - case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ - o1 = c.oprrr(p, p.As) - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - if r == 0 { - r = REGZERO - } - o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ - o1 = c.oprrr(p, p.As) - - cond := int(p.From.Reg) - if cond < COND_EQ || cond > COND_NV { - c.ctxt.Diag("invalid condition: %v", p) - } else { - cond -= COND_EQ - } - - r := int(p.Reg) - var rf int - if r != 0 { - if p.From3Type() == obj.TYPE_NONE { - /* CINC/CINV/CNEG */ - rf = r - cond ^= 1 - } else { - rf = int(p.GetFrom3().Reg) /* CSEL */ - } - } else { - /* CSET */ - rf = REGZERO - r = rf - cond ^= 1 - } - - rt := int(p.To.Reg) - o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) - - case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ - nzcv := int(p.To.Offset) - - cond := int(p.From.Reg) - if cond < COND_EQ || cond > COND_NV { - c.ctxt.Diag("invalid condition\n%v", p) - } else { - cond -= COND_EQ - } - var rf int - if p.GetFrom3().Type == obj.TYPE_REG { - o1 = c.oprrr(p, p.As) - rf = int(p.GetFrom3().Reg) /* Rm */ - } else { - o1 = c.opirr(p, p.As) - rf = int(p.GetFrom3().Offset & 0x1F) - } - - o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) - - case 20: /* movT R,O(R) -> strT */ - v := int32(c.regoff(&p.To)) - sz := int32(1 << uint(movesize(p.As))) - - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ - o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) - } else { - v = int32(c.offsetshift(p, int64(v), int(o.a4))) - o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) - } - - case 21: /* movT O(R),R -> ldrT */ - v := int32(c.regoff(&p.From)) - sz := int32(1 << uint(movesize(p.As))) - - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ - o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) - } else { - v = int32(c.offsetshift(p, int64(v), int(o.a1))) - //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); - o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) - } - - case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ - if p.From.Reg != REGSP && p.From.Reg == p.To.Reg { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - - v := int32(p.From.Offset) - - if v < -256 || v > 255 { - c.ctxt.Diag("offset out of range [-255,254]: %v", p) - } - o1 = c.opldrpp(p, p.As) - if o.scond == C_XPOST { - o1 |= 1 << 10 - } else { - o1 |= 3 << 10 - } - o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) - - case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ - if p.To.Reg != REGSP && p.From.Reg == p.To.Reg { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - - v := int32(p.To.Offset) - - if v < -256 || v > 255 { - c.ctxt.Diag("offset out of range [-255,254]: %v", p) - } - o1 = LD2STR(c.opldrpp(p, p.As)) - if o.scond == C_XPOST { - o1 |= 1 << 10 - } else { - o1 |= 3 << 10 - } - o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) - - case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - s := rf == REGSP || rt == REGSP - if p.As == AMVN || p.As == AMVNW { - if s { - c.ctxt.Diag("illegal SP reference\n%v", p) - } - o1 = c.oprrr(p, p.As) - o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - } else if s { - o1 = c.opirr(p, p.As) - o1 |= (uint32(rf&31) << 5) | uint32(rt&31) - } else { - o1 = c.oprrr(p, p.As) - o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - } - - case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ - o1 = c.oprrr(p, p.As) - - rf := int(p.From.Reg) - if rf == C_NONE { - rf = int(p.To.Reg) - } - rt := int(p.To.Reg) - o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - - case 26: /* negX Rm< subX Rm<> 5) & 7 - if amount > 4 { - c.ctxt.Diag("shift amount out of range 0 to 4: %v", p) - } - o1 = c.opxrrr(p, p.As, true) - o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */ - } else { - o1 = c.opxrrr(p, p.As, false) - o1 |= uint32(p.From.Reg&31) << 16 - } - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if r == 0 { - r = rt - } - o1 |= (uint32(r&31) << 5) | uint32(rt&31) - - case 28: /* logop $vcon, [R], R (64 bit literal) */ - o := uint32(0) - num := uint8(0) - cls := oclass(&p.From) - if isANDWop(p.As) { - if !cmp(C_LCON, cls) { - c.ctxt.Diag("illegal combination: %v", p) - } - num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) - } else { - num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) - } - - if num == 0 { - c.ctxt.Diag("invalid constant: %v", p) - } - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if r == 0 { - r = rt - } - o = c.oprrr(p, p.As) - o |= REGTMP & 31 << 16 /* shift is 0 */ - o |= uint32(r&31) << 5 - o |= uint32(rt & 31) - - os[num] = o - o1 = os[0] - o2 = os[1] - o3 = os[2] - o4 = os[3] - o5 = os[4] - - case 29: /* op Rn, Rd */ - fc := c.aclass(&p.From) - tc := c.aclass(&p.To) - if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { - // FMOV Rx, Fy or FMOV Fy, Rx - o1 = FPCVTI(0, 0, 0, 0, 6) - if p.As == AFMOVD { - o1 |= 1<<31 | 1<<22 // 64-bit - } - if fc == C_REG || fc == C_ZCON { - o1 |= 1 << 16 // FMOV Rx, Fy - } - } else { - o1 = c.oprrr(p, p.As) - } - o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) - - case 30: /* movT R,L(R) -> strT */ - // if offset L can be split into hi+lo, and both fit into instructions, do - // add $hi, R, Rtmp - // str R, lo(Rtmp) - // otherwise, use constant pool - // mov $L, Rtmp (from constant pool) - // str R, (R+Rtmp) - s := movesize(o.as) - if s < 0 { - c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) - } - - r := int(p.To.Reg) - if r == 0 { - r = int(o.param) - } - - v := int32(c.regoff(&p.To)) - var hi int32 - if v < 0 || (v&((1<>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) - break - - storeusepool: - if r == REGTMP || p.From.Reg == REGTMP { - c.ctxt.Diag("REGTMP used in large offset store: %v", p) - } - o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) - o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP) - - case 31: /* movT L(R), R -> ldrT */ - // if offset L can be split into hi+lo, and both fit into instructions, do - // add $hi, R, Rtmp - // ldr lo(Rtmp), R - // otherwise, use constant pool - // mov $L, Rtmp (from constant pool) - // ldr (R+Rtmp), R - s := movesize(o.as) - if s < 0 { - c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) - } - - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - - v := int32(c.regoff(&p.From)) - var hi int32 - if v < 0 || (v&((1<>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) - break - - loadusepool: - if r == REGTMP || p.From.Reg == REGTMP { - c.ctxt.Diag("REGTMP used in large offset load: %v", p) - } - o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) - o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP) - - case 32: /* mov $con, R -> movz/movn */ - o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) - - case 33: /* movk $uimm16 << pos */ - o1 = c.opirr(p, p.As) - - d := p.From.Offset - s := movcon(d) - if s < 0 || s >= 4 { - c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) - } - if (o1&S64) == 0 && s >= 2 { - c.ctxt.Diag("illegal bit position\n%v", p) - } - if ((d >> uint(s*16)) >> 16) != 0 { - c.ctxt.Diag("requires uimm16\n%v", p) - } - rt := int(p.To.Reg) - - o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) - - case 34: /* mov $lacon,R */ - o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) - - if o1 == 0 { - break - } - o2 = c.opxrrr(p, AADD, false) - o2 |= REGTMP & 31 << 16 - o2 |= LSL0_64 - r := int(p.From.Reg) - if r == 0 { - r = int(o.param) - } - o2 |= uint32(r&31) << 5 - o2 |= uint32(p.To.Reg & 31) - - case 35: /* mov SPR,R -> mrs */ - o1 = c.oprrr(p, AMRS) - - // SysRegEnc function returns the system register encoding and accessFlags. - _, v, accessFlags := SysRegEnc(p.From.Reg) - if v == 0 { - c.ctxt.Diag("illegal system register:\n%v", p) - } - if (o1 & (v &^ (3 << 19))) != 0 { - c.ctxt.Diag("MRS register value overlap\n%v", p) - } - if accessFlags&SR_READ == 0 { - c.ctxt.Diag("system register is not readable: %v", p) - } - - o1 |= v - o1 |= uint32(p.To.Reg & 31) - - case 36: /* mov R,SPR */ - o1 = c.oprrr(p, AMSR) - - // SysRegEnc function returns the system register encoding and accessFlags. - _, v, accessFlags := SysRegEnc(p.To.Reg) - if v == 0 { - c.ctxt.Diag("illegal system register:\n%v", p) - } - if (o1 & (v &^ (3 << 19))) != 0 { - c.ctxt.Diag("MSR register value overlap\n%v", p) - } - if accessFlags&SR_WRITE == 0 { - c.ctxt.Diag("system register is not writable: %v", p) - } - - o1 |= v - o1 |= uint32(p.From.Reg & 31) - - case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ - if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { - c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) - } - o1 = c.opirr(p, AMSR) - o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ - v := uint32(0) - for i := 0; i < len(pstatefield); i++ { - if pstatefield[i].reg == p.To.Reg { - v = pstatefield[i].enc - break - } - } - - if v == 0 { - c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) - } - o1 |= v - - case 38: /* clrex [$imm] */ - o1 = c.opimm(p, p.As) - - if p.To.Type == obj.TYPE_NONE { - o1 |= 0xF << 8 - } else { - o1 |= uint32((p.To.Offset & 0xF) << 8) - } - - case 39: /* cbz R, rel */ - o1 = c.opirr(p, p.As) - - o1 |= uint32(p.From.Reg & 31) - o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) - - case 40: /* tbz */ - o1 = c.opirr(p, p.As) - - v := int32(p.From.Offset) - if v < 0 || v > 63 { - c.ctxt.Diag("illegal bit number\n%v", p) - } - o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) - o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) - o1 |= uint32(p.Reg & 31) - - case 41: /* eret, nop, others with no operands */ - o1 = c.op0(p, p.As) - - case 42: /* bfm R,r,s,R */ - o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg)) - - case 43: /* bfm aliases */ - r := int(p.From.Offset) - s := int(p.GetFrom3().Offset) - rf := int(p.Reg) - rt := int(p.To.Reg) - if rf == 0 { - rf = rt - } - switch p.As { - case ABFI: - if r != 0 { - r = 64 - r - } - o1 = c.opbfm(p, ABFM, r, s-1, rf, rt) - - case ABFIW: - if r != 0 { - r = 32 - r - } - o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt) - - case ABFXIL: - o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) - - case ABFXILW: - o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) - - case ASBFIZ: - if r != 0 { - r = 64 - r - } - o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt) - - case ASBFIZW: - if r != 0 { - r = 32 - r - } - o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt) - - case ASBFX: - o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) - - case ASBFXW: - o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) - - case AUBFIZ: - if r != 0 { - r = 64 - r - } - o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt) - - case AUBFIZW: - if r != 0 { - r = 32 - r - } - o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt) - - case AUBFX: - o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) - - case AUBFXW: - o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) - - default: - c.ctxt.Diag("bad bfm alias\n%v", p) - break - } - - case 44: /* extr $b, Rn, Rm, Rd */ - o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg)) - - case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ - rf := int(p.From.Reg) - - rt := int(p.To.Reg) - as := p.As - if rf == REGZERO { - as = AMOVWU /* clearer in disassembly */ - } - switch as { - case AMOVB, ASXTB: - o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) - - case AMOVH, ASXTH: - o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) - - case AMOVW, ASXTW: - o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) - - case AMOVBU, AUXTB: - o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) - - case AMOVHU, AUXTH: - o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) - - case AMOVWU: - o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - - case AUXTW: - o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) - - case ASXTBW: - o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) - - case ASXTHW: - o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) - - case AUXTBW: - o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) - - case AUXTHW: - o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) - - default: - c.ctxt.Diag("bad sxt %v", as) - break - } - - case 46: /* cls */ - o1 = c.opbit(p, p.As) - - o1 |= uint32(p.From.Reg&31) << 5 - o1 |= uint32(p.To.Reg & 31) - - case 47: /* SWPx/LDADDx/LDANDx/LDEORx/LDORx Rs, (Rb), Rt */ - rs := p.From.Reg - rt := p.RegTo2 - rb := p.To.Reg - - fields := atomicInstructions[p.As] - // rt can't be sp. rt can't be r31 when field A is 0, A bit is the 23rd bit. - if rt == REG_RSP || (rt == REGZERO && (fields&(1<<23) == 0)) { - c.ctxt.Diag("illegal destination register: %v\n", p) - } - o1 |= fields | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31) - - case 48: /* ADD $C_ADDCON2, Rm, Rd */ - // NOTE: this case does not use REGTMP. If it ever does, - // remove the NOTUSETMP flag in optab. - op := c.opirr(p, p.As) - if op&Sbit != 0 { - c.ctxt.Diag("can not break addition/subtraction when S bit is set", p) - } - rt := int(p.To.Reg) - r := int(p.Reg) - if r == 0 { - r = rt - } - o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt) - o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt) - - case 50: /* sys/sysl */ - o1 = c.opirr(p, p.As) - - if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { - c.ctxt.Diag("illegal SYS argument\n%v", p) - } - o1 |= uint32(p.From.Offset) - if p.To.Type == obj.TYPE_REG { - o1 |= uint32(p.To.Reg & 31) - } else if p.Reg != 0 { - o1 |= uint32(p.Reg & 31) - } else { - o1 |= 0x1F - } - - case 51: /* dmb */ - o1 = c.opirr(p, p.As) - - if p.From.Type == obj.TYPE_CONST { - o1 |= uint32((p.From.Offset & 0xF) << 8) - } - - case 52: /* hint */ - o1 = c.opirr(p, p.As) - - o1 |= uint32((p.From.Offset & 0x7F) << 5) - - case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */ - a := p.As - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if r == 0 { - r = rt - } - mode := 64 - v := uint64(p.From.Offset) - switch p.As { - case AANDW, AORRW, AEORW, AANDSW, ATSTW: - mode = 32 - case ABIC, AORN, AEON, ABICS: - v = ^v - case ABICW, AORNW, AEONW, ABICSW: - v = ^v - mode = 32 - } - o1 = c.opirr(p, a) - o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) - - case 54: /* floating point arith */ - o1 = c.oprrr(p, p.As) - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ - r = rf - rf = 0 - } else if r == 0 { - r = rt - } - o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - case 55: /* floating-point constant */ - var rf int - o1 = 0xf<<25 | 1<<21 | 1<<12 - rf = c.chipfloat7(p.From.Val.(float64)) - if rf < 0 { - c.ctxt.Diag("invalid floating-point immediate\n%v", p) - } - if p.As == AFMOVD { - o1 |= 1 << 22 - } - o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31) - - case 56: /* floating point compare */ - o1 = c.oprrr(p, p.As) - - var rf int - if p.From.Type == obj.TYPE_FCONST { - o1 |= 8 /* zero */ - rf = 0 - } else { - rf = int(p.From.Reg) - } - rt := int(p.Reg) - o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 - - case 57: /* floating point conditional compare */ - o1 = c.oprrr(p, p.As) - - cond := int(p.From.Reg) - if cond < COND_EQ || cond > COND_NV { - c.ctxt.Diag("invalid condition\n%v", p) - } else { - cond -= COND_EQ - } - - nzcv := int(p.To.Offset) - if nzcv&^0xF != 0 { - c.ctxt.Diag("implausible condition\n%v", p) - } - rf := int(p.Reg) - if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 { - c.ctxt.Diag("illegal FCCMP\n%v", p) - break - } - rt := int(p.GetFrom3().Reg) - o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) - - case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */ - o1 = c.opload(p, p.As) - - o1 |= 0x1F << 16 - o1 |= uint32(p.From.Reg&31) << 5 - if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW { - if int(p.To.Reg) == int(p.To.Offset) { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - o1 |= uint32(p.To.Offset&31) << 10 - } else { - o1 |= 0x1F << 10 - } - o1 |= uint32(p.To.Reg & 31) - - case 59: /* stxr/stlxr/stxp/stlxp */ - s := p.RegTo2 - n := p.To.Reg - t := p.From.Reg - if isSTLXRop(p.As) { - if s == t || (s == n && n != REGSP) { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - } else if isSTXPop(p.As) { - t2 := int16(p.From.Offset) - if (s == t || s == t2) || (s == n && n != REGSP) { - c.ctxt.Diag("constrained unpredictable behavior: %v", p) - } - } - if s == REG_RSP { - c.ctxt.Diag("illegal destination register: %v\n", p) - } - o1 = c.opstore(p, p.As) - - if p.RegTo2 != obj.REG_NONE { - o1 |= uint32(p.RegTo2&31) << 16 - } else { - o1 |= 0x1F << 16 - } - if isSTXPop(p.As) { - o1 |= uint32(p.From.Offset&31) << 10 - } - o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31) - - case 60: /* adrp label,r */ - d := c.brdist(p, 12, 21, 0) - - o1 = ADR(1, uint32(d), uint32(p.To.Reg)) - - case 61: /* adr label, r */ - d := c.brdist(p, 0, 21, 0) - - o1 = ADR(0, uint32(d), uint32(p.To.Reg)) - - case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ - if p.Reg == REGTMP { - c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) - } - if isADDWop(p.As) || isANDWop(p.As) { - o1 = c.omovconst(AMOVW, p, &p.From, REGTMP) - } else { - o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) - } - - rt := int(p.To.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - r := int(p.Reg) - if r == 0 { - r = rt - } - if p.To.Reg == REGSP || r == REGSP { - o2 = c.opxrrr(p, p.As, false) - o2 |= REGTMP & 31 << 16 - o2 |= LSL0_64 - } else { - o2 = c.oprrr(p, p.As) - o2 |= REGTMP & 31 << 16 /* shift is 0 */ - } - o2 |= uint32(r&31) << 5 - o2 |= uint32(rt & 31) - - /* reloc ops */ - case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ - o1 = ADR(1, 0, REGTMP) - o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.To.Sym - rel.Add = p.To.Offset - rel.Type = objabi.R_ADDRARM64 - o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) - - case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ - o1 = ADR(1, 0, REGTMP) - o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.From.Sym - rel.Add = p.From.Offset - rel.Type = objabi.R_ADDRARM64 - o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) - - case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ - v := int32(c.regoff(&p.From)) - r := int(p.From.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid ldp source: %v\n", p) - } - o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1) - - case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ - r := int(p.To.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid stp destination: %v\n", p) - } - v := int32(c.regoff(&p.To)) - o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0) - - case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ - // NOTE: this case does not use REGTMP. If it ever does, - // remove the NOTUSETMP flag in optab. - if p.As == AMOVW { - c.ctxt.Diag("invalid load of 32-bit address: %v", p) - } - o1 = ADR(1, 0, uint32(p.To.Reg)) - o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.From.Sym - rel.Add = p.From.Offset - rel.Type = objabi.R_ADDRARM64 - - case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ - o1 = c.opirr(p, AMOVZ) - o1 |= uint32(p.To.Reg & 31) - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 4 - rel.Sym = p.From.Sym - rel.Type = objabi.R_ARM64_TLS_LE - if p.From.Offset != 0 { - c.ctxt.Diag("invalid offset on MOVW $tlsvar") - } - - case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ - o1 = ADR(1, 0, REGTMP) - o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.From.Sym - rel.Add = 0 - rel.Type = objabi.R_ARM64_TLS_IE - if p.From.Offset != 0 { - c.ctxt.Diag("invalid offset on MOVW $tlsvar") - } - - case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ - o1 = ADR(1, 0, REGTMP) - o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.From.Sym - rel.Add = 0 - rel.Type = objabi.R_ARM64_GOTPCREL - - case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2 Vm., Vn., Vd. */ - af := int((p.From.Reg >> 5) & 15) - af3 := int((p.Reg >> 5) & 15) - at := int((p.To.Reg >> 5) & 15) - if af != af3 || af != at { - c.ctxt.Diag("operand mismatch: %v", p) - break - } - o1 = c.oprrr(p, p.As) - rf := int((p.From.Reg) & 31) - rt := int((p.To.Reg) & 31) - r := int((p.Reg) & 31) - - Q := 0 - size := 0 - switch af { - case ARNG_16B: - Q = 1 - size = 0 - case ARNG_2D: - Q = 1 - size = 3 - case ARNG_2S: - Q = 0 - size = 2 - case ARNG_4H: - Q = 0 - size = 1 - case ARNG_4S: - Q = 1 - size = 2 - case ARNG_8B: - Q = 0 - size = 0 - case ARNG_8H: - Q = 1 - size = 1 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - - switch p.As { - case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF: - if af != ARNG_16B && af != ARNG_8B { - c.ctxt.Diag("invalid arrangement: %v", p) - } - case AVFMLA, AVFMLS: - if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S { - c.ctxt.Diag("invalid arrangement: %v", p) - } - } - switch p.As { - case AVAND, AVEOR: - size = 0 - case AVBSL: - size = 1 - case AVORR, AVBIT, AVBIF: - size = 2 - case AVFMLA, AVFMLS: - if af == ARNG_2D { - size = 1 - } else { - size = 0 - } - } - - o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - case 73: /* vmov V.[index], R */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - imm5 := 0 - o1 = 7<<25 | 0xf<<10 - index := int(p.From.Index) - switch (p.From.Reg >> 5) & 15 { - case ARNG_B: - c.checkindex(p, index, 15) - imm5 |= 1 - imm5 |= index << 1 - case ARNG_H: - c.checkindex(p, index, 7) - imm5 |= 2 - imm5 |= index << 2 - case ARNG_S: - c.checkindex(p, index, 3) - imm5 |= 4 - imm5 |= index << 3 - case ARNG_D: - c.checkindex(p, index, 1) - imm5 |= 8 - imm5 |= index << 4 - o1 |= 1 << 30 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 74: - // add $O, R, Rtmp or sub $O, R, Rtmp - // ldp (Rtmp), (R1, R2) - r := int(p.From.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid ldp source: %v", p) - } - v := int32(c.regoff(&p.From)) - - if v > 0 { - if v > 4095 { - c.ctxt.Diag("offset out of range: %v", p) - } - o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) - } - if v < 0 { - if v < -4095 { - c.ctxt.Diag("offset out of range: %v", p) - } - o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) - } - o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) - - case 75: - // mov $L, Rtmp (from constant pool) - // add Rtmp, R, Rtmp - // ldp (Rtmp), (R1, R2) - r := int(p.From.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid ldp source: %v", p) - } - o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) - o2 = c.opxrrr(p, AADD, false) - o2 |= (REGTMP & 31) << 16 - o2 |= uint32(r&31) << 5 - o2 |= uint32(REGTMP & 31) - o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) - - case 76: - // add $O, R, Rtmp or sub $O, R, Rtmp - // stp (R1, R2), (Rtmp) - r := int(p.To.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid stp destination: %v", p) - } - v := int32(c.regoff(&p.To)) - if v > 0 { - if v > 4095 { - c.ctxt.Diag("offset out of range: %v", p) - } - o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) - } - if v < 0 { - if v < -4095 { - c.ctxt.Diag("offset out of range: %v", p) - } - o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) - } - o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) - - case 77: - // mov $L, Rtmp (from constant pool) - // add Rtmp, R, Rtmp - // stp (R1, R2), (Rtmp) - r := int(p.To.Reg) - if r == obj.REG_NONE { - r = int(o.param) - } - if r == obj.REG_NONE { - c.ctxt.Diag("invalid stp destination: %v", p) - } - o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) - o2 = c.opxrrr(p, AADD, false) - o2 |= REGTMP & 31 << 16 - o2 |= uint32(r&31) << 5 - o2 |= uint32(REGTMP & 31) - o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) - - case 78: /* vmov R, V.[index] */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - imm5 := 0 - o1 = 1<<30 | 7<<25 | 7<<10 - index := int(p.To.Index) - switch (p.To.Reg >> 5) & 15 { - case ARNG_B: - c.checkindex(p, index, 15) - imm5 |= 1 - imm5 |= index << 1 - case ARNG_H: - c.checkindex(p, index, 7) - imm5 |= 2 - imm5 |= index << 2 - case ARNG_S: - c.checkindex(p, index, 3) - imm5 |= 4 - imm5 |= index << 3 - case ARNG_D: - c.checkindex(p, index, 1) - imm5 |= 8 - imm5 |= index << 4 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 79: /* vdup Vn.[index], Vd. */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - o1 = 7<<25 | 1<<10 - var imm5, Q int - index := int(p.From.Index) - switch (p.To.Reg >> 5) & 15 { - case ARNG_16B: - c.checkindex(p, index, 15) - Q = 1 - imm5 = 1 - imm5 |= index << 1 - case ARNG_2D: - c.checkindex(p, index, 1) - Q = 1 - imm5 = 8 - imm5 |= index << 4 - case ARNG_2S: - c.checkindex(p, index, 3) - Q = 0 - imm5 = 4 - imm5 |= index << 3 - case ARNG_4H: - c.checkindex(p, index, 7) - Q = 0 - imm5 = 2 - imm5 |= index << 2 - case ARNG_4S: - c.checkindex(p, index, 3) - Q = 1 - imm5 = 4 - imm5 |= index << 3 - case ARNG_8B: - c.checkindex(p, index, 15) - Q = 0 - imm5 = 1 - imm5 |= index << 1 - case ARNG_8H: - c.checkindex(p, index, 7) - Q = 1 - imm5 = 2 - imm5 |= index << 2 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) - o1 |= (uint32(rf&31) << 5) | uint32(rt&31) - - case 80: /* vmov V.[index], Vn */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - imm5 := 0 - index := int(p.From.Index) - switch p.As { - case AVMOV: - o1 = 1<<30 | 15<<25 | 1<<10 - switch (p.From.Reg >> 5) & 15 { - case ARNG_B: - c.checkindex(p, index, 15) - imm5 |= 1 - imm5 |= index << 1 - case ARNG_H: - c.checkindex(p, index, 7) - imm5 |= 2 - imm5 |= index << 2 - case ARNG_S: - c.checkindex(p, index, 3) - imm5 |= 4 - imm5 |= index << 3 - case ARNG_D: - c.checkindex(p, index, 1) - imm5 |= 8 - imm5 |= index << 4 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - default: - c.ctxt.Diag("unsupported op %v", p.As) - } - o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1., Vt2., ...] */ - c.checkoffset(p, p.As) - r := int(p.From.Reg) - o1 = c.oprrr(p, p.As) - if o.scond == C_XPOST { - o1 |= 1 << 23 - if p.From.Index == 0 { - // immediate offset variant - o1 |= 0x1f << 16 - } else { - // register offset variant - if isRegShiftOrExt(&p.From) { - c.ctxt.Diag("invalid extended register op: %v\n", p) - } - o1 |= uint32(p.From.Index&0x1f) << 16 - } - } - o1 |= uint32(p.To.Offset) - // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset - // add opcode(bit 12-15) for vld1, mask it off if it's not vld1 - o1 = c.maskOpvldvst(p, o1) - o1 |= uint32(r&31) << 5 - - case 82: /* vmov Rn, Vd. */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - o1 = 7<<25 | 3<<10 - var imm5, Q uint32 - switch (p.To.Reg >> 5) & 15 { - case ARNG_16B: - Q = 1 - imm5 = 1 - case ARNG_2D: - Q = 1 - imm5 = 8 - case ARNG_2S: - Q = 0 - imm5 = 4 - case ARNG_4H: - Q = 0 - imm5 = 2 - case ARNG_4S: - Q = 1 - imm5 = 4 - case ARNG_8B: - Q = 0 - imm5 = 1 - case ARNG_8H: - Q = 1 - imm5 = 2 - default: - c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.: %v\n", p) - } - o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16) - o1 |= (uint32(rf&31) << 5) | uint32(rt&31) - - case 83: /* vmov Vn., Vd. */ - af := int((p.From.Reg >> 5) & 15) - at := int((p.To.Reg >> 5) & 15) - if af != at { - c.ctxt.Diag("invalid arrangement: %v\n", p) - } - o1 = c.oprrr(p, p.As) - rf := int((p.From.Reg) & 31) - rt := int((p.To.Reg) & 31) - - var Q, size uint32 - switch af { - case ARNG_8B: - Q = 0 - size = 0 - case ARNG_16B: - Q = 1 - size = 0 - case ARNG_4H: - Q = 0 - size = 1 - case ARNG_8H: - Q = 1 - size = 1 - case ARNG_2S: - Q = 0 - size = 2 - case ARNG_4S: - Q = 1 - size = 2 - default: - c.ctxt.Diag("invalid arrangement: %v\n", p) - } - - if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) { - c.ctxt.Diag("invalid arrangement: %v", p) - } - - if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) { - c.ctxt.Diag("invalid arrangement: %v", p) - } - - if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B { - c.ctxt.Diag("invalid arrangement: %v", p) - } - - if p.As == AVMOV { - o1 |= uint32(rf&31) << 16 - } - - if p.As == AVRBIT { - size = 1 - } - - o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31) - - case 84: /* vst[1-4] [Vt1., Vt2., ...], (Rn) */ - c.checkoffset(p, p.As) - r := int(p.To.Reg) - o1 = 3 << 26 - if o.scond == C_XPOST { - o1 |= 1 << 23 - if p.To.Index == 0 { - // immediate offset variant - o1 |= 0x1f << 16 - } else { - // register offset variant - if isRegShiftOrExt(&p.To) { - c.ctxt.Diag("invalid extended register: %v\n", p) - } - o1 |= uint32(p.To.Index&31) << 16 - } - } - o1 |= uint32(p.From.Offset) - // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset - // add opcode(bit 12-15) for vst1, mask it off if it's not vst1 - o1 = c.maskOpvldvst(p, o1) - o1 |= uint32(r&31) << 5 - - case 85: /* vaddv/vuaddlv Vn., Vd*/ - af := int((p.From.Reg >> 5) & 15) - o1 = c.oprrr(p, p.As) - rf := int((p.From.Reg) & 31) - rt := int((p.To.Reg) & 31) - Q := 0 - size := 0 - switch af { - case ARNG_8B: - Q = 0 - size = 0 - case ARNG_16B: - Q = 1 - size = 0 - case ARNG_4H: - Q = 0 - size = 1 - case ARNG_8H: - Q = 1 - size = 1 - case ARNG_4S: - Q = 1 - size = 2 - default: - c.ctxt.Diag("invalid arrangement: %v\n", p) - } - o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 86: /* vmovi $imm8, Vd.*/ - at := int((p.To.Reg >> 5) & 15) - r := int(p.From.Offset) - if r > 255 || r < 0 { - c.ctxt.Diag("immediate constant out of range: %v\n", p) - } - rt := int((p.To.Reg) & 31) - Q := 0 - switch at { - case ARNG_8B: - Q = 0 - case ARNG_16B: - Q = 1 - default: - c.ctxt.Diag("invalid arrangement: %v\n", p) - } - o1 = 0xf<<24 | 0xe<<12 | 1<<10 - o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) - - case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ - o1 = ADR(1, 0, REGTMP) - o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.To.Sym - rel.Add = p.To.Offset - rel.Type = objabi.R_ADDRARM64 - o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) - - case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */ - o1 = ADR(1, 0, REGTMP) - o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 - rel := obj.Addrel(c.cursym) - rel.Off = int32(c.pc) - rel.Siz = 8 - rel.Sym = p.From.Sym - rel.Add = p.From.Offset - rel.Type = objabi.R_ADDRARM64 - o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) - - case 89: /* vadd/vsub Vm, Vn, Vd */ - switch p.As { - case AVADD: - o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 - - case AVSUB: - o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 - - default: - c.ctxt.Diag("bad opcode: %v\n", p) - break - } - - rf := int(p.From.Reg) - rt := int(p.To.Reg) - r := int(p.Reg) - if r == 0 { - r = rt - } - o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - // This is supposed to be something that stops execution. - // It's not supposed to be reached, ever, but if it is, we'd - // like to be able to tell how we got there. Assemble as - // 0xbea71700 which is guaranteed to raise undefined instruction - // exception. - case 90: - o1 = 0xbea71700 - - case 91: /* prfm imm(Rn), */ - imm := uint32(p.From.Offset) - r := p.From.Reg - v := uint32(0xff) - if p.To.Type == obj.TYPE_CONST { - v = uint32(p.To.Offset) - if v > 31 { - c.ctxt.Diag("illegal prefetch operation\n%v", p) - } - } else { - for i := 0; i < len(prfopfield); i++ { - if prfopfield[i].reg == p.To.Reg { - v = prfopfield[i].enc - break - } - } - if v == 0xff { - c.ctxt.Diag("illegal prefetch operation:\n%v", p) - } - } - - o1 = c.opldrpp(p, p.As) - o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31)) - - case 92: /* vmov Vn.[index], Vd.[index] */ - rf := int(p.From.Reg) - rt := int(p.To.Reg) - imm4 := 0 - imm5 := 0 - o1 = 3<<29 | 7<<25 | 1<<10 - index1 := int(p.To.Index) - index2 := int(p.From.Index) - if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) { - c.ctxt.Diag("operand mismatch: %v", p) - } - switch (p.To.Reg >> 5) & 15 { - case ARNG_B: - c.checkindex(p, index1, 15) - c.checkindex(p, index2, 15) - imm5 |= 1 - imm5 |= index1 << 1 - imm4 |= index2 - case ARNG_H: - c.checkindex(p, index1, 7) - c.checkindex(p, index2, 7) - imm5 |= 2 - imm5 |= index1 << 2 - imm4 |= index2 << 1 - case ARNG_S: - c.checkindex(p, index1, 3) - c.checkindex(p, index2, 3) - imm5 |= 4 - imm5 |= index1 << 3 - imm4 |= index2 << 2 - case ARNG_D: - c.checkindex(p, index1, 1) - c.checkindex(p, index2, 1) - imm5 |= 8 - imm5 |= index1 << 4 - imm4 |= index2 << 3 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 93: /* vpmull{2} Vm., Vn., Vd */ - af := int((p.From.Reg >> 5) & 15) - at := int((p.To.Reg >> 5) & 15) - a := int((p.Reg >> 5) & 15) - - var Q, size uint32 - if p.As == AVPMULL { - Q = 0 - } else { - Q = 1 - } - - var fArng int - switch at { - case ARNG_8H: - if Q == 0 { - fArng = ARNG_8B - } else { - fArng = ARNG_16B - } - size = 0 - case ARNG_1Q: - if Q == 0 { - fArng = ARNG_1D - } else { - fArng = ARNG_2D - } - size = 3 - default: - c.ctxt.Diag("invalid arrangement on Vd.: %v", p) - } - - if af != a || af != fArng { - c.ctxt.Diag("invalid arrangement: %v", p) - } - - o1 = c.oprrr(p, p.As) - rf := int((p.From.Reg) & 31) - rt := int((p.To.Reg) & 31) - r := int((p.Reg) & 31) - - o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) - - case 94: /* vext $imm4, Vm., Vn., Vd. */ - af := int(((p.GetFrom3().Reg) >> 5) & 15) - at := int((p.To.Reg >> 5) & 15) - a := int((p.Reg >> 5) & 15) - index := int(p.From.Offset) - - if af != a || af != at { - c.ctxt.Diag("invalid arrangement: %v", p) - break - } - - var Q uint32 - var b int - if af == ARNG_8B { - Q = 0 - b = 7 - } else if af == ARNG_16B { - Q = 1 - b = 15 - } else { - c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p) - break - } - - if index < 0 || index > b { - c.ctxt.Diag("illegal offset: %v", p) - } - - o1 = c.opirr(p, p.As) - rf := int((p.GetFrom3().Reg) & 31) - rt := int((p.To.Reg) & 31) - r := int((p.Reg) & 31) - - o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 95: /* vushr $shift, Vn., Vd. */ - at := int((p.To.Reg >> 5) & 15) - af := int((p.Reg >> 5) & 15) - shift := int(p.From.Offset) - - if af != at { - c.ctxt.Diag("invalid arrangement on op Vn., Vd.: %v", p) - } - - var Q uint32 - var imax, esize int - - switch af { - case ARNG_8B, ARNG_4H, ARNG_2S: - Q = 0 - case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D: - Q = 1 - default: - c.ctxt.Diag("invalid arrangement on op Vn., Vd.: %v", p) - } - - switch af { - case ARNG_8B, ARNG_16B: - imax = 15 - esize = 8 - case ARNG_4H, ARNG_8H: - imax = 31 - esize = 16 - case ARNG_2S, ARNG_4S: - imax = 63 - esize = 32 - case ARNG_2D: - imax = 127 - esize = 64 - } - - imm := 0 - - switch p.As { - case AVUSHR, AVSRI: - imm = esize*2 - shift - if imm < esize || imm > imax { - c.ctxt.Diag("shift out of range: %v", p) - } - case AVSHL: - imm = esize + shift - if imm > imax { - c.ctxt.Diag("shift out of range: %v", p) - } - default: - c.ctxt.Diag("invalid instruction %v\n", p) - } - - o1 = c.opirr(p, p.As) - rt := int((p.To.Reg) & 31) - rf := int((p.Reg) & 31) - - o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 96: /* vst1 Vt1.[index], offset(Rn) */ - af := int((p.From.Reg >> 5) & 15) - rt := int((p.From.Reg) & 31) - rf := int((p.To.Reg) & 31) - r := int(p.To.Index & 31) - index := int(p.From.Index) - offset := int32(c.regoff(&p.To)) - - if o.scond == C_XPOST { - if (p.To.Index != 0) && (offset != 0) { - c.ctxt.Diag("invalid offset: %v", p) - } - if p.To.Index == 0 && offset == 0 { - c.ctxt.Diag("invalid offset: %v", p) - } - } - - if offset != 0 { - r = 31 - } - - var Q, S, size int - var opcode uint32 - switch af { - case ARNG_B: - c.checkindex(p, index, 15) - if o.scond == C_XPOST && offset != 0 && offset != 1 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 3 - S = (index >> 2) & 1 - size = index & 3 - opcode = 0 - case ARNG_H: - c.checkindex(p, index, 7) - if o.scond == C_XPOST && offset != 0 && offset != 2 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 2 - S = (index >> 1) & 1 - size = (index & 1) << 1 - opcode = 2 - case ARNG_S: - c.checkindex(p, index, 3) - if o.scond == C_XPOST && offset != 0 && offset != 4 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 1 - S = index & 1 - size = 0 - opcode = 4 - case ARNG_D: - c.checkindex(p, index, 1) - if o.scond == C_XPOST && offset != 0 && offset != 8 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index - S = 0 - size = 1 - opcode = 4 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - - if o.scond == C_XPOST { - o1 |= 27 << 23 - } else { - o1 |= 26 << 23 - } - - o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 97: /* vld1 offset(Rn), vt.[index] */ - at := int((p.To.Reg >> 5) & 15) - rt := int((p.To.Reg) & 31) - rf := int((p.From.Reg) & 31) - r := int(p.From.Index & 31) - index := int(p.To.Index) - offset := int32(c.regoff(&p.From)) - - if o.scond == C_XPOST { - if (p.From.Index != 0) && (offset != 0) { - c.ctxt.Diag("invalid offset: %v", p) - } - if p.From.Index == 0 && offset == 0 { - c.ctxt.Diag("invalid offset: %v", p) - } - } - - if offset != 0 { - r = 31 - } - - Q := 0 - S := 0 - size := 0 - var opcode uint32 - switch at { - case ARNG_B: - c.checkindex(p, index, 15) - if o.scond == C_XPOST && offset != 0 && offset != 1 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 3 - S = (index >> 2) & 1 - size = index & 3 - opcode = 0 - case ARNG_H: - c.checkindex(p, index, 7) - if o.scond == C_XPOST && offset != 0 && offset != 2 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 2 - S = (index >> 1) & 1 - size = (index & 1) << 1 - opcode = 2 - case ARNG_S: - c.checkindex(p, index, 3) - if o.scond == C_XPOST && offset != 0 && offset != 4 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index >> 1 - S = index & 1 - size = 0 - opcode = 4 - case ARNG_D: - c.checkindex(p, index, 1) - if o.scond == C_XPOST && offset != 0 && offset != 8 { - c.ctxt.Diag("invalid offset: %v", p) - } - Q = index - S = 0 - size = 1 - opcode = 4 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - - if o.scond == C_XPOST { - o1 |= 110 << 21 - } else { - o1 |= 106 << 21 - } - - o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) - - case 98: /* MOVD (Rn)(Rm.SXTW[<, [Vt1., Vt2., ...], Vd. */ - af := int((p.From.Reg >> 5) & 15) - at := int((p.To.Reg >> 5) & 15) - if af != at { - c.ctxt.Diag("invalid arrangement: %v\n", p) - } - var q, len uint32 - switch af { - case ARNG_8B: - q = 0 - case ARNG_16B: - q = 1 - default: - c.ctxt.Diag("invalid arrangement: %v", p) - } - rf := int(p.From.Reg) - rt := int(p.To.Reg) - offset := int(p.GetFrom3().Offset) - opcode := (offset >> 12) & 15 - switch opcode { - case 0x7: - len = 0 // one register - case 0xa: - len = 1 // two register - case 0x6: - len = 2 // three registers - case 0x2: - len = 3 // four registers - default: - c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) - } - o1 = q<<30 | 0xe<<24 | len<<13 - o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31) - - case 101: // FOMVQ/FMOVD $vcon, Vd -> load from constant pool. - o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg)) - - case 102: /* vushll, vushll2, vuxtl, vuxtl2 */ - o1 = c.opirr(p, p.As) - rf := p.Reg - af := uint8((p.Reg >> 5) & 15) - at := uint8((p.To.Reg >> 5) & 15) - shift := int(p.From.Offset) - if p.As == AVUXTL || p.As == AVUXTL2 { - rf = p.From.Reg - af = uint8((p.From.Reg >> 5) & 15) - shift = 0 - } - - pack := func(q, x, y uint8) uint32 { - return uint32(q)<<16 | uint32(x)<<8 | uint32(y) - } - - var Q uint8 = uint8(o1>>30) & 1 - var immh, width uint8 - switch pack(Q, af, at) { - case pack(0, ARNG_8B, ARNG_8H): - immh, width = 1, 8 - case pack(1, ARNG_16B, ARNG_8H): - immh, width = 1, 8 - case pack(0, ARNG_4H, ARNG_4S): - immh, width = 2, 16 - case pack(1, ARNG_8H, ARNG_4S): - immh, width = 2, 16 - case pack(0, ARNG_2S, ARNG_2D): - immh, width = 4, 32 - case pack(1, ARNG_4S, ARNG_2D): - immh, width = 4, 32 - default: - c.ctxt.Diag("operand mismatch: %v\n", p) - } - if !(0 <= shift && shift <= int(width-1)) { - c.ctxt.Diag("shift amount out of range: %v\n", p) - } - o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31) - } - out[0] = o1 - out[1] = o2 - out[2] = o3 - out[3] = o4 - out[4] = o5 -} - -/* - * basic Rm op Rn -> Rd (using shifted register with 0) - * also op Rn -> Rt - * also Rm*Rn op Ra -> Rd - * also Vm op Vn -> Vd - */ -func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { - switch a { - case AADC: - return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 - - case AADCW: - return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 - - case AADCS: - return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 - - case AADCSW: - return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 - - case ANGC, ASBC: - return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 - - case ANGCS, ASBCS: - return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 - - case ANGCW, ASBCW: - return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 - - case ANGCSW, ASBCSW: - return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 - - case AADD: - return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case AADDW: - return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ACMN, AADDS: - return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ACMNW, AADDSW: - return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ASUB: - return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ASUBW: - return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ACMP, ASUBS: - return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case ACMPW, ASUBSW: - return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 - - case AAND: - return S64 | 0<<29 | 0xA<<24 - - case AANDW: - return S32 | 0<<29 | 0xA<<24 - - case AMOVD, AORR: - return S64 | 1<<29 | 0xA<<24 - - // case AMOVW: - case AMOVWU, AORRW: - return S32 | 1<<29 | 0xA<<24 - - case AEOR: - return S64 | 2<<29 | 0xA<<24 - - case AEORW: - return S32 | 2<<29 | 0xA<<24 - - case AANDS, ATST: - return S64 | 3<<29 | 0xA<<24 - - case AANDSW, ATSTW: - return S32 | 3<<29 | 0xA<<24 - - case ABIC: - return S64 | 0<<29 | 0xA<<24 | 1<<21 - - case ABICW: - return S32 | 0<<29 | 0xA<<24 | 1<<21 - - case ABICS: - return S64 | 3<<29 | 0xA<<24 | 1<<21 - - case ABICSW: - return S32 | 3<<29 | 0xA<<24 | 1<<21 - - case AEON: - return S64 | 2<<29 | 0xA<<24 | 1<<21 - - case AEONW: - return S32 | 2<<29 | 0xA<<24 | 1<<21 - - case AMVN, AORN: - return S64 | 1<<29 | 0xA<<24 | 1<<21 - - case AMVNW, AORNW: - return S32 | 1<<29 | 0xA<<24 | 1<<21 - - case AASR: - return S64 | OPDP2(10) /* also ASRV */ - - case AASRW: - return S32 | OPDP2(10) - - case ALSL: - return S64 | OPDP2(8) - - case ALSLW: - return S32 | OPDP2(8) - - case ALSR: - return S64 | OPDP2(9) - - case ALSRW: - return S32 | OPDP2(9) - - case AROR: - return S64 | OPDP2(11) - - case ARORW: - return S32 | OPDP2(11) - - case ACCMN: - return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ - - case ACCMNW: - return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 - - case ACCMP: - return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ - - case ACCMPW: - return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 - - case ACRC32B: - return S32 | OPDP2(16) - - case ACRC32H: - return S32 | OPDP2(17) - - case ACRC32W: - return S32 | OPDP2(18) - - case ACRC32X: - return S64 | OPDP2(19) - - case ACRC32CB: - return S32 | OPDP2(20) - - case ACRC32CH: - return S32 | OPDP2(21) - - case ACRC32CW: - return S32 | OPDP2(22) - - case ACRC32CX: - return S64 | OPDP2(23) - - case ACSEL: - return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACSELW: - return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACSET: - return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case ACSETW: - return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case ACSETM: - return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACSETMW: - return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACINC, ACSINC: - return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case ACINCW, ACSINCW: - return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case ACINV, ACSINV: - return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACINVW, ACSINVW: - return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 - - case ACNEG, ACSNEG: - return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case ACNEGW, ACSNEGW: - return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 - - case AMUL, AMADD: - return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 - - case AMULW, AMADDW: - return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 - - case AMNEG, AMSUB: - return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 - - case AMNEGW, AMSUBW: - return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 - - case AMRS: - return SYSOP(1, 2, 0, 0, 0, 0, 0) - - case AMSR: - return SYSOP(0, 2, 0, 0, 0, 0, 0) - - case ANEG: - return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 - - case ANEGW: - return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 - - case ANEGS: - return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 - - case ANEGSW: - return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 - - case AREM, ASDIV: - return S64 | OPDP2(3) - - case AREMW, ASDIVW: - return S32 | OPDP2(3) - - case ASMULL, ASMADDL: - return OPDP3(1, 0, 1, 0) - - case ASMNEGL, ASMSUBL: - return OPDP3(1, 0, 1, 1) - - case ASMULH: - return OPDP3(1, 0, 2, 0) - - case AUMULL, AUMADDL: - return OPDP3(1, 0, 5, 0) - - case AUMNEGL, AUMSUBL: - return OPDP3(1, 0, 5, 1) - - case AUMULH: - return OPDP3(1, 0, 6, 0) - - case AUREM, AUDIV: - return S64 | OPDP2(2) - - case AUREMW, AUDIVW: - return S32 | OPDP2(2) - - case AAESE: - return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 - - case AAESD: - return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 - - case AAESMC: - return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 - - case AAESIMC: - return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 - - case ASHA1C: - return 0x5E<<24 | 0<<12 - - case ASHA1P: - return 0x5E<<24 | 1<<12 - - case ASHA1M: - return 0x5E<<24 | 2<<12 - - case ASHA1SU0: - return 0x5E<<24 | 3<<12 - - case ASHA256H: - return 0x5E<<24 | 4<<12 - - case ASHA256H2: - return 0x5E<<24 | 5<<12 - - case ASHA256SU1: - return 0x5E<<24 | 6<<12 - - case ASHA1H: - return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 - - case ASHA1SU1: - return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 - - case ASHA256SU0: - return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 - - case ASHA512H: - return 0xCE<<24 | 3<<21 | 8<<12 - - case ASHA512H2: - return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8 - - case ASHA512SU1: - return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8 - - case ASHA512SU0: - return 0xCE<<24 | 3<<22 | 8<<12 - - case AFCVTZSD: - return FPCVTI(1, 0, 1, 3, 0) - - case AFCVTZSDW: - return FPCVTI(0, 0, 1, 3, 0) - - case AFCVTZSS: - return FPCVTI(1, 0, 0, 3, 0) - - case AFCVTZSSW: - return FPCVTI(0, 0, 0, 3, 0) - - case AFCVTZUD: - return FPCVTI(1, 0, 1, 3, 1) - - case AFCVTZUDW: - return FPCVTI(0, 0, 1, 3, 1) - - case AFCVTZUS: - return FPCVTI(1, 0, 0, 3, 1) - - case AFCVTZUSW: - return FPCVTI(0, 0, 0, 3, 1) - - case ASCVTFD: - return FPCVTI(1, 0, 1, 0, 2) - - case ASCVTFS: - return FPCVTI(1, 0, 0, 0, 2) - - case ASCVTFWD: - return FPCVTI(0, 0, 1, 0, 2) - - case ASCVTFWS: - return FPCVTI(0, 0, 0, 0, 2) - - case AUCVTFD: - return FPCVTI(1, 0, 1, 0, 3) - - case AUCVTFS: - return FPCVTI(1, 0, 0, 0, 3) - - case AUCVTFWD: - return FPCVTI(0, 0, 1, 0, 3) - - case AUCVTFWS: - return FPCVTI(0, 0, 0, 0, 3) - - case AFADDS: - return FPOP2S(0, 0, 0, 2) - - case AFADDD: - return FPOP2S(0, 0, 1, 2) - - case AFSUBS: - return FPOP2S(0, 0, 0, 3) - - case AFSUBD: - return FPOP2S(0, 0, 1, 3) - - case AFMADDD: - return FPOP3S(0, 0, 1, 0, 0) - - case AFMADDS: - return FPOP3S(0, 0, 0, 0, 0) - - case AFMSUBD: - return FPOP3S(0, 0, 1, 0, 1) - - case AFMSUBS: - return FPOP3S(0, 0, 0, 0, 1) - - case AFNMADDD: - return FPOP3S(0, 0, 1, 1, 0) - - case AFNMADDS: - return FPOP3S(0, 0, 0, 1, 0) - - case AFNMSUBD: - return FPOP3S(0, 0, 1, 1, 1) - - case AFNMSUBS: - return FPOP3S(0, 0, 0, 1, 1) - - case AFMULS: - return FPOP2S(0, 0, 0, 0) - - case AFMULD: - return FPOP2S(0, 0, 1, 0) - - case AFDIVS: - return FPOP2S(0, 0, 0, 1) - - case AFDIVD: - return FPOP2S(0, 0, 1, 1) - - case AFMAXS: - return FPOP2S(0, 0, 0, 4) - - case AFMINS: - return FPOP2S(0, 0, 0, 5) - - case AFMAXD: - return FPOP2S(0, 0, 1, 4) - - case AFMIND: - return FPOP2S(0, 0, 1, 5) - - case AFMAXNMS: - return FPOP2S(0, 0, 0, 6) - - case AFMAXNMD: - return FPOP2S(0, 0, 1, 6) - - case AFMINNMS: - return FPOP2S(0, 0, 0, 7) - - case AFMINNMD: - return FPOP2S(0, 0, 1, 7) - - case AFNMULS: - return FPOP2S(0, 0, 0, 8) - - case AFNMULD: - return FPOP2S(0, 0, 1, 8) - - case AFCMPS: - return FPCMP(0, 0, 0, 0, 0) - - case AFCMPD: - return FPCMP(0, 0, 1, 0, 0) - - case AFCMPES: - return FPCMP(0, 0, 0, 0, 16) - - case AFCMPED: - return FPCMP(0, 0, 1, 0, 16) - - case AFCCMPS: - return FPCCMP(0, 0, 0, 0) - - case AFCCMPD: - return FPCCMP(0, 0, 1, 0) - - case AFCCMPES: - return FPCCMP(0, 0, 0, 1) - - case AFCCMPED: - return FPCCMP(0, 0, 1, 1) - - case AFCSELS: - return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 - - case AFCSELD: - return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 - - case AFMOVS: - return FPOP1S(0, 0, 0, 0) - - case AFABSS: - return FPOP1S(0, 0, 0, 1) - - case AFNEGS: - return FPOP1S(0, 0, 0, 2) - - case AFSQRTS: - return FPOP1S(0, 0, 0, 3) - - case AFCVTSD: - return FPOP1S(0, 0, 0, 5) - - case AFCVTSH: - return FPOP1S(0, 0, 0, 7) - - case AFRINTNS: - return FPOP1S(0, 0, 0, 8) - - case AFRINTPS: - return FPOP1S(0, 0, 0, 9) - - case AFRINTMS: - return FPOP1S(0, 0, 0, 10) - - case AFRINTZS: - return FPOP1S(0, 0, 0, 11) - - case AFRINTAS: - return FPOP1S(0, 0, 0, 12) - - case AFRINTXS: - return FPOP1S(0, 0, 0, 14) - - case AFRINTIS: - return FPOP1S(0, 0, 0, 15) - - case AFMOVD: - return FPOP1S(0, 0, 1, 0) - - case AFABSD: - return FPOP1S(0, 0, 1, 1) - - case AFNEGD: - return FPOP1S(0, 0, 1, 2) - - case AFSQRTD: - return FPOP1S(0, 0, 1, 3) - - case AFCVTDS: - return FPOP1S(0, 0, 1, 4) - - case AFCVTDH: - return FPOP1S(0, 0, 1, 7) - - case AFRINTND: - return FPOP1S(0, 0, 1, 8) - - case AFRINTPD: - return FPOP1S(0, 0, 1, 9) - - case AFRINTMD: - return FPOP1S(0, 0, 1, 10) - - case AFRINTZD: - return FPOP1S(0, 0, 1, 11) - - case AFRINTAD: - return FPOP1S(0, 0, 1, 12) - - case AFRINTXD: - return FPOP1S(0, 0, 1, 14) - - case AFRINTID: - return FPOP1S(0, 0, 1, 15) - - case AFCVTHS: - return FPOP1S(0, 0, 3, 4) - - case AFCVTHD: - return FPOP1S(0, 0, 3, 5) - - case AVADD: - return 7<<25 | 1<<21 | 1<<15 | 1<<10 - - case AVSUB: - return 0x17<<25 | 1<<21 | 1<<15 | 1<<10 - - case AVADDP: - return 7<<25 | 1<<21 | 1<<15 | 15<<10 - - case AVAND: - return 7<<25 | 1<<21 | 7<<10 - - case AVCMEQ: - return 1<<29 | 0x71<<21 | 0x23<<10 - - case AVCNT: - return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10 - - case AVZIP1: - return 0xE<<24 | 3<<12 | 2<<10 - - case AVZIP2: - return 0xE<<24 | 1<<14 | 3<<12 | 2<<10 - - case AVEOR: - return 1<<29 | 0x71<<21 | 7<<10 - - case AVORR: - return 7<<25 | 5<<21 | 7<<10 - - case AVREV16: - return 3<<26 | 2<<24 | 1<<21 | 3<<11 - - case AVREV32: - return 11<<26 | 2<<24 | 1<<21 | 1<<11 - - case AVREV64: - return 3<<26 | 2<<24 | 1<<21 | 1<<11 - - case AVMOV: - return 7<<25 | 5<<21 | 7<<10 - - case AVADDV: - return 7<<25 | 3<<20 | 3<<15 | 7<<11 - - case AVUADDLV: - return 1<<29 | 7<<25 | 3<<20 | 7<<11 - - case AVFMLA: - return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10 - - case AVFMLS: - return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10 - - case AVPMULL, AVPMULL2: - return 0xE<<24 | 1<<21 | 0x38<<10 - - case AVRBIT: - return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10 - - case AVLD1, AVLD2, AVLD3, AVLD4: - return 3<<26 | 1<<22 - - case AVLD1R, AVLD3R: - return 0xD<<24 | 1<<22 - - case AVLD2R, AVLD4R: - return 0xD<<24 | 3<<21 - - case AVBIF: - return 1<<29 | 7<<25 | 7<<21 | 7<<10 - - case AVBIT: - return 1<<29 | 0x75<<21 | 7<<10 - - case AVBSL: - return 1<<29 | 0x73<<21 | 7<<10 - - case AVCMTST: - return 0xE<<24 | 1<<21 | 0x23<<10 - - case AVUZP1: - return 7<<25 | 3<<11 - - case AVUZP2: - return 7<<25 | 1<<14 | 3<<11 - } - - c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) - return 0 -} - -/* - * imm -> Rd - * imm op Rn -> Rd - */ -func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { - switch a { - /* op $addcon, Rn, Rd */ - case AMOVD, AADD: - return S64 | 0<<30 | 0<<29 | 0x11<<24 - - case ACMN, AADDS: - return S64 | 0<<30 | 1<<29 | 0x11<<24 - - case AMOVW, AADDW: - return S32 | 0<<30 | 0<<29 | 0x11<<24 - - case ACMNW, AADDSW: - return S32 | 0<<30 | 1<<29 | 0x11<<24 - - case ASUB: - return S64 | 1<<30 | 0<<29 | 0x11<<24 - - case ACMP, ASUBS: - return S64 | 1<<30 | 1<<29 | 0x11<<24 - - case ASUBW: - return S32 | 1<<30 | 0<<29 | 0x11<<24 - - case ACMPW, ASUBSW: - return S32 | 1<<30 | 1<<29 | 0x11<<24 - - /* op $imm(SB), Rd; op label, Rd */ - case AADR: - return 0<<31 | 0x10<<24 - - case AADRP: - return 1<<31 | 0x10<<24 - - /* op $bimm, Rn, Rd */ - case AAND, ABIC: - return S64 | 0<<29 | 0x24<<23 - - case AANDW, ABICW: - return S32 | 0<<29 | 0x24<<23 | 0<<22 - - case AORR, AORN: - return S64 | 1<<29 | 0x24<<23 - - case AORRW, AORNW: - return S32 | 1<<29 | 0x24<<23 | 0<<22 - - case AEOR, AEON: - return S64 | 2<<29 | 0x24<<23 - - case AEORW, AEONW: - return S32 | 2<<29 | 0x24<<23 | 0<<22 - - case AANDS, ABICS, ATST: - return S64 | 3<<29 | 0x24<<23 - - case AANDSW, ABICSW, ATSTW: - return S32 | 3<<29 | 0x24<<23 | 0<<22 - - case AASR: - return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ - - case AASRW: - return S32 | 0<<29 | 0x26<<23 | 0<<22 - - /* op $width, $lsb, Rn, Rd */ - case ABFI: - return S64 | 2<<29 | 0x26<<23 | 1<<22 - /* alias of BFM */ - - case ABFIW: - return S32 | 2<<29 | 0x26<<23 | 0<<22 - - /* op $imms, $immr, Rn, Rd */ - case ABFM: - return S64 | 1<<29 | 0x26<<23 | 1<<22 - - case ABFMW: - return S32 | 1<<29 | 0x26<<23 | 0<<22 - - case ASBFM: - return S64 | 0<<29 | 0x26<<23 | 1<<22 - - case ASBFMW: - return S32 | 0<<29 | 0x26<<23 | 0<<22 - - case AUBFM: - return S64 | 2<<29 | 0x26<<23 | 1<<22 - - case AUBFMW: - return S32 | 2<<29 | 0x26<<23 | 0<<22 - - case ABFXIL: - return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ - - case ABFXILW: - return S32 | 1<<29 | 0x26<<23 | 0<<22 - - case AEXTR: - return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 - - case AEXTRW: - return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 - - case ACBNZ: - return S64 | 0x1A<<25 | 1<<24 - - case ACBNZW: - return S32 | 0x1A<<25 | 1<<24 - - case ACBZ: - return S64 | 0x1A<<25 | 0<<24 - - case ACBZW: - return S32 | 0x1A<<25 | 0<<24 - - case ACCMN: - return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ - - case ACCMNW: - return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 - - case ACCMP: - return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ - - case ACCMPW: - return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 - - case AMOVK: - return S64 | 3<<29 | 0x25<<23 - - case AMOVKW: - return S32 | 3<<29 | 0x25<<23 - - case AMOVN: - return S64 | 0<<29 | 0x25<<23 - - case AMOVNW: - return S32 | 0<<29 | 0x25<<23 - - case AMOVZ: - return S64 | 2<<29 | 0x25<<23 - - case AMOVZW: - return S32 | 2<<29 | 0x25<<23 - - case AMSR: - return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ - - case AAT, - ADC, - AIC, - ATLBI, - ASYS: - return SYSOP(0, 1, 0, 0, 0, 0, 0) - - case ASYSL: - return SYSOP(1, 1, 0, 0, 0, 0, 0) - - case ATBZ: - return 0x36 << 24 - - case ATBNZ: - return 0x37 << 24 - - case ADSB: - return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) - - case ADMB: - return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) - - case AISB: - return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) - - case AHINT: - return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) - - case AVEXT: - return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15 - - case AVUSHR: - return 0x5E<<23 | 1<<10 - - case AVSHL: - return 0x1E<<23 | 21<<10 - - case AVSRI: - return 0x5E<<23 | 17<<10 - - case AVUSHLL, AVUXTL: - return 1<<29 | 15<<24 | 0x29<<10 - - case AVUSHLL2, AVUXTL2: - return 3<<29 | 15<<24 | 0x29<<10 - } - - c.ctxt.Diag("%v: bad irr %v", p, a) - return 0 -} - -func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { - switch a { - case ACLS: - return S64 | OPBIT(5) - - case ACLSW: - return S32 | OPBIT(5) - - case ACLZ: - return S64 | OPBIT(4) - - case ACLZW: - return S32 | OPBIT(4) - - case ARBIT: - return S64 | OPBIT(0) - - case ARBITW: - return S32 | OPBIT(0) - - case AREV: - return S64 | OPBIT(3) - - case AREVW: - return S32 | OPBIT(2) - - case AREV16: - return S64 | OPBIT(1) - - case AREV16W: - return S32 | OPBIT(1) - - case AREV32: - return S64 | OPBIT(2) - - default: - c.ctxt.Diag("bad bit op\n%v", p) - return 0 - } -} - -/* - * add/subtract sign or zero-extended register - */ -func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 { - extension := uint32(0) - if !extend { - switch a { - case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS: - extension = LSL0_64 - - case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW: - extension = LSL0_32 - } - } - - switch a { - case AADD: - return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case AADDW: - return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ACMN, AADDS: - return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ACMNW, AADDSW: - return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ASUB: - return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ASUBW: - return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ACMP, ASUBS: - return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - - case ACMPW, ASUBSW: - return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension - } - - c.ctxt.Diag("bad opxrrr %v\n%v", a, p) - return 0 -} - -func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { - switch a { - case ASVC: - return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ - - case AHVC: - return 0xD4<<24 | 0<<21 | 2 - - case ASMC: - return 0xD4<<24 | 0<<21 | 3 - - case ABRK: - return 0xD4<<24 | 1<<21 | 0 - - case AHLT: - return 0xD4<<24 | 2<<21 | 0 - - case ADCPS1: - return 0xD4<<24 | 5<<21 | 1 - - case ADCPS2: - return 0xD4<<24 | 5<<21 | 2 - - case ADCPS3: - return 0xD4<<24 | 5<<21 | 3 - - case ACLREX: - return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) - } - - c.ctxt.Diag("%v: bad imm %v", p, a) - return 0 -} - -func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { - v := int64(0) - t := int64(0) - q := p.To.Target() - if q == nil { - // TODO: don't use brdist for this case, as it isn't a branch. - // (Calls from omovlit, and maybe adr/adrp opcodes as well.) - q = p.Pool - } - if q != nil { - v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) - if (v & ((1 << uint(shift)) - 1)) != 0 { - c.ctxt.Diag("misaligned label\n%v", p) - } - v >>= uint(shift) - t = int64(1) << uint(flen-1) - if v < -t || v >= t { - c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q) - panic("branch too far") - } - } - - return v & ((t << 1) - 1) -} - -/* - * pc-relative branches - */ -func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { - switch a { - case ABEQ: - return OPBcc(0x0) - - case ABNE: - return OPBcc(0x1) - - case ABCS: - return OPBcc(0x2) - - case ABHS: - return OPBcc(0x2) - - case ABCC: - return OPBcc(0x3) - - case ABLO: - return OPBcc(0x3) - - case ABMI: - return OPBcc(0x4) - - case ABPL: - return OPBcc(0x5) - - case ABVS: - return OPBcc(0x6) - - case ABVC: - return OPBcc(0x7) - - case ABHI: - return OPBcc(0x8) - - case ABLS: - return OPBcc(0x9) - - case ABGE: - return OPBcc(0xa) - - case ABLT: - return OPBcc(0xb) - - case ABGT: - return OPBcc(0xc) - - case ABLE: - return OPBcc(0xd) /* imm19<<5 | cond */ - - case AB: - return 0<<31 | 5<<26 /* imm26 */ - - case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: - return 1<<31 | 5<<26 - } - - c.ctxt.Diag("%v: bad bra %v", p, a) - return 0 -} - -func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { - switch a { - case ABL: - return OPBLR(1) /* BLR */ - - case AB: - return OPBLR(0) /* BR */ - - case obj.ARET: - return OPBLR(2) /* RET */ - } - - c.ctxt.Diag("%v: bad brr %v", p, a) - return 0 -} - -func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { - switch a { - case ADRPS: - return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 - - case AERET: - return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 - - case ANOOP: - return SYSHINT(0) - - case AYIELD: - return SYSHINT(1) - - case AWFE: - return SYSHINT(2) - - case AWFI: - return SYSHINT(3) - - case ASEV: - return SYSHINT(4) - - case ASEVL: - return SYSHINT(5) - } - - c.ctxt.Diag("%v: bad op0 %v", p, a) - return 0 -} - -/* - * register offset - */ -func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { - switch a { - case ALDAR: - return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 - - case ALDARW: - return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 - - case ALDARB: - return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 - - case ALDARH: - return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 - - case ALDAXP: - return LDSTX(3, 0, 1, 1, 1) - - case ALDAXPW: - return LDSTX(2, 0, 1, 1, 1) - - case ALDAXR: - return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 - - case ALDAXRW: - return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 - - case ALDAXRB: - return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 - - case ALDAXRH: - return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 - - case ALDXR: - return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 - - case ALDXRB: - return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 - - case ALDXRH: - return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 - - case ALDXRW: - return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 - - case ALDXP: - return LDSTX(3, 0, 1, 1, 0) - - case ALDXPW: - return LDSTX(2, 0, 1, 1, 0) - - case AMOVNP: - return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 - - case AMOVNPW: - return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 - } - - c.ctxt.Diag("bad opload %v\n%v", a, p) - return 0 -} - -func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { - switch a { - case ASTLR: - return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 - - case ASTLRB: - return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 - - case ASTLRH: - return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 - - case ASTLP: - return LDSTX(3, 0, 0, 1, 1) - - case ASTLPW: - return LDSTX(2, 0, 0, 1, 1) - - case ASTLRW: - return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 - - case ASTLXP: - return LDSTX(3, 0, 0, 1, 1) - - case ASTLXPW: - return LDSTX(2, 0, 0, 1, 1) - - case ASTLXR: - return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 - - case ASTLXRB: - return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 - - case ASTLXRH: - return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 - - case ASTLXRW: - return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 - - case ASTXR: - return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 - - case ASTXRB: - return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 - - case ASTXRH: - return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 - - case ASTXP: - return LDSTX(3, 0, 0, 1, 0) - - case ASTXPW: - return LDSTX(2, 0, 0, 1, 0) - - case ASTXRW: - return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 - - case AMOVNP: - return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 - - case AMOVNPW: - return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 - } - - c.ctxt.Diag("bad opstore %v\n%v", a, p) - return 0 -} - -/* - * load/store register (unsigned immediate) C3.3.13 - * these produce 64-bit values (when there's an option) - */ -func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { - if v < 0 || v >= (1<<12) { - c.ctxt.Diag("offset out of range: %d\n%v", v, p) - } - o |= (v & 0xFFF) << 10 - o |= int32(b&31) << 5 - o |= int32(r & 31) - return uint32(o) -} - -func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 { - switch a { - case AMOVD: - return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ - - case AMOVW: - return LDSTR12U(2, 0, 2) - - case AMOVWU: - return LDSTR12U(2, 0, 1) - - case AMOVH: - return LDSTR12U(1, 0, 2) - - case AMOVHU: - return LDSTR12U(1, 0, 1) - - case AMOVB: - return LDSTR12U(0, 0, 2) - - case AMOVBU: - return LDSTR12U(0, 0, 1) - - case AFMOVS: - return LDSTR12U(2, 1, 1) - - case AFMOVD: - return LDSTR12U(3, 1, 1) - } - - c.ctxt.Diag("bad opldr12 %v\n%v", a, p) - return 0 -} - -func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 { - return LD2STR(c.opldr12(p, a)) -} - -/* - * load/store register (unscaled immediate) C3.3.12 - */ -func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { - if v < -256 || v > 255 { - c.ctxt.Diag("offset out of range: %d\n%v", v, p) - } - o |= (v & 0x1FF) << 12 - o |= int32(b&31) << 5 - o |= int32(r & 31) - return uint32(o) -} - -func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { - switch a { - case AMOVD: - return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ - - case AMOVW: - return LDSTR9S(2, 0, 2) - - case AMOVWU: - return LDSTR9S(2, 0, 1) - - case AMOVH: - return LDSTR9S(1, 0, 2) - - case AMOVHU: - return LDSTR9S(1, 0, 1) - - case AMOVB: - return LDSTR9S(0, 0, 2) - - case AMOVBU: - return LDSTR9S(0, 0, 1) - - case AFMOVS: - return LDSTR9S(2, 1, 1) - - case AFMOVD: - return LDSTR9S(3, 1, 1) - } - - c.ctxt.Diag("bad opldr9 %v\n%v", a, p) - return 0 -} - -func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { - return LD2STR(c.opldr9(p, a)) -} - -func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { - switch a { - case AMOVD: - return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ - - case AMOVW: - return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 - - case AMOVWU: - return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 - - case AMOVH: - return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 - - case AMOVHU: - return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 - - case AMOVB: - return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 - - case AMOVBU: - return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 - - case AFMOVS: - return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 - - case AFMOVD: - return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 - - case APRFM: - return 0xf9<<24 | 2<<22 - - } - - c.ctxt.Diag("bad opldr %v\n%v", a, p) - return 0 -} - -// olsxrr attaches register operands to a load/store opcode supplied in o. -// The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). -func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { - o |= int32(r1&31) << 5 - o |= int32(r2&31) << 16 - o |= int32(r & 31) - return uint32(o) -} - -// opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode -// for load instruction with register offset. -// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). -func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 { - OptionS := uint32(0x1a) - if extension { - OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset. - } - switch a { - case AMOVD: - return OptionS<<10 | 0x3<<21 | 0x1f<<27 - case AMOVW: - return OptionS<<10 | 0x5<<21 | 0x17<<27 - case AMOVWU: - return OptionS<<10 | 0x3<<21 | 0x17<<27 - case AMOVH: - return OptionS<<10 | 0x5<<21 | 0x0f<<27 - case AMOVHU: - return OptionS<<10 | 0x3<<21 | 0x0f<<27 - case AMOVB: - return OptionS<<10 | 0x5<<21 | 0x07<<27 - case AMOVBU: - return OptionS<<10 | 0x3<<21 | 0x07<<27 - case AFMOVS: - return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26 - case AFMOVD: - return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 - } - c.ctxt.Diag("bad opldrr %v\n%v", a, p) - return 0 -} - -// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode -// for store instruction with register offset. -// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). -func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 { - OptionS := uint32(0x1a) - if extension { - OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset. - } - switch a { - case AMOVD: - return OptionS<<10 | 0x1<<21 | 0x1f<<27 - case AMOVW, AMOVWU: - return OptionS<<10 | 0x1<<21 | 0x17<<27 - case AMOVH, AMOVHU: - return OptionS<<10 | 0x1<<21 | 0x0f<<27 - case AMOVB, AMOVBU: - return OptionS<<10 | 0x1<<21 | 0x07<<27 - case AFMOVS: - return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26 - case AFMOVD: - return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 - } - c.ctxt.Diag("bad opstrr %v\n%v", a, p) - return 0 -} - -func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { - if (v & 0xFFF000) != 0 { - if v&0xFFF != 0 { - c.ctxt.Diag("%v misuses oaddi", p) - } - v >>= 12 - o1 |= 1 << 22 - } - - o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) - return uint32(o1) -} - -/* - * load a literal value into dr - */ -func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { - var o1 int32 - if p.Pool == nil { /* not in literal pool */ - c.aclass(a) - c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) - - /* TODO: could be clever, and use general constant builder */ - o1 = int32(c.opirr(p, AADD)) - - v := int32(c.instoffset) - if v != 0 && (v&0xFFF) == 0 { - v >>= 12 - o1 |= 1 << 22 /* shift, by 12 */ - } - - o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) - } else { - fp, w := 0, 0 - switch as { - case AFMOVS: - fp = 1 - w = 0 /* 32-bit SIMD/FP */ - - case AFMOVD: - fp = 1 - w = 1 /* 64-bit SIMD/FP */ - - case AFMOVQ: - fp = 1 - w = 2 /* 128-bit SIMD/FP */ - - case AMOVD: - if p.Pool.As == ADWORD { - w = 1 /* 64-bit */ - } else if p.Pool.To.Offset < 0 { - w = 2 /* 32-bit, sign-extended to 64-bit */ - } else if p.Pool.To.Offset >= 0 { - w = 0 /* 32-bit, zero-extended to 64-bit */ - } else { - c.ctxt.Diag("invalid operand %v in %v", a, p) - } - - case AMOVBU, AMOVHU, AMOVWU: - w = 0 /* 32-bit, zero-extended to 64-bit */ - - case AMOVB, AMOVH, AMOVW: - w = 2 /* 32-bit, sign-extended to 64-bit */ - - default: - c.ctxt.Diag("invalid operation %v in %v", as, p) - } - - v := int32(c.brdist(p, 0, 19, 2)) - o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) - o1 |= (v & 0x7FFFF) << 5 - o1 |= int32(dr & 31) - } - - return uint32(o1) -} - -// load a constant (MOVCON or BITCON) in a into rt -func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { - if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { - // or $bitcon, REGZERO, rt - mode := 64 - var as1 obj.As - switch as { - case AMOVW: - as1 = AORRW - mode = 32 - case AMOVD: - as1 = AORR - } - o1 = c.opirr(p, as1) - o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) - return o1 - } - - if as == AMOVW { - d := uint32(a.Offset) - s := movcon(int64(d)) - if s < 0 || 16*s >= 32 { - d = ^d - s = movcon(int64(d)) - if s < 0 || 16*s >= 32 { - c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p) - } - o1 = c.opirr(p, AMOVNW) - } else { - o1 = c.opirr(p, AMOVZW) - } - o1 |= MOVCONST(int64(d), s, rt) - } - if as == AMOVD { - d := a.Offset - s := movcon(d) - if s < 0 || 16*s >= 64 { - d = ^d - s = movcon(d) - if s < 0 || 16*s >= 64 { - c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p) - } - o1 = c.opirr(p, AMOVN) - } else { - o1 = c.opirr(p, AMOVZ) - } - o1 |= MOVCONST(d, s, rt) - } - return o1 -} - -// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt -// put the instruction sequence in os and return the number of instructions. -func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) { - switch as { - case AMOVW: - d := uint32(a.Offset) - // use MOVZW and MOVKW to load a constant to rt - os[0] = c.opirr(p, AMOVZW) - os[0] |= MOVCONST(int64(d), 0, rt) - os[1] = c.opirr(p, AMOVKW) - os[1] |= MOVCONST(int64(d), 1, rt) - return 2 - - case AMOVD: - d := a.Offset - dn := ^d - var immh [4]uint64 - var i int - zeroCount := int(0) - negCount := int(0) - for i = 0; i < 4; i++ { - immh[i] = uint64((d >> uint(i*16)) & 0xffff) - if immh[i] == 0 { - zeroCount++ - } else if immh[i] == 0xffff { - negCount++ - } - } - - if zeroCount == 4 || negCount == 4 { - c.ctxt.Diag("the immediate should be MOVCON: %v", p) - } - switch { - case zeroCount == 3: - // one MOVZ - for i = 0; i < 4; i++ { - if immh[i] != 0 { - os[0] = c.opirr(p, AMOVZ) - os[0] |= MOVCONST(d, i, rt) - break - } - } - return 1 - - case negCount == 3: - // one MOVN - for i = 0; i < 4; i++ { - if immh[i] != 0xffff { - os[0] = c.opirr(p, AMOVN) - os[0] |= MOVCONST(dn, i, rt) - break - } - } - return 1 - - case zeroCount == 2: - // one MOVZ and one MOVK - for i = 0; i < 4; i++ { - if immh[i] != 0 { - os[0] = c.opirr(p, AMOVZ) - os[0] |= MOVCONST(d, i, rt) - i++ - break - } - } - for ; i < 4; i++ { - if immh[i] != 0 { - os[1] = c.opirr(p, AMOVK) - os[1] |= MOVCONST(d, i, rt) - } - } - return 2 - - case negCount == 2: - // one MOVN and one MOVK - for i = 0; i < 4; i++ { - if immh[i] != 0xffff { - os[0] = c.opirr(p, AMOVN) - os[0] |= MOVCONST(dn, i, rt) - i++ - break - } - } - for ; i < 4; i++ { - if immh[i] != 0xffff { - os[1] = c.opirr(p, AMOVK) - os[1] |= MOVCONST(d, i, rt) - } - } - return 2 - - case zeroCount == 1: - // one MOVZ and two MOVKs - for i = 0; i < 4; i++ { - if immh[i] != 0 { - os[0] = c.opirr(p, AMOVZ) - os[0] |= MOVCONST(d, i, rt) - i++ - break - } - } - - for j := 1; i < 4; i++ { - if immh[i] != 0 { - os[j] = c.opirr(p, AMOVK) - os[j] |= MOVCONST(d, i, rt) - j++ - } - } - return 3 - - case negCount == 1: - // one MOVN and two MOVKs - for i = 0; i < 4; i++ { - if immh[i] != 0xffff { - os[0] = c.opirr(p, AMOVN) - os[0] |= MOVCONST(dn, i, rt) - i++ - break - } - } - - for j := 1; i < 4; i++ { - if immh[i] != 0xffff { - os[j] = c.opirr(p, AMOVK) - os[j] |= MOVCONST(d, i, rt) - j++ - } - } - return 3 - - default: - // one MOVZ and 3 MOVKs - os[0] = c.opirr(p, AMOVZ) - os[0] |= MOVCONST(d, 0, rt) - for i = 1; i < 4; i++ { - os[i] = c.opirr(p, AMOVK) - os[i] |= MOVCONST(d, i, rt) - } - return 4 - } - default: - return 0 - } -} - -func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { - var b uint32 - o := c.opirr(p, a) - if (o & (1 << 31)) == 0 { - b = 32 - } else { - b = 64 - } - if r < 0 || uint32(r) >= b { - c.ctxt.Diag("illegal bit number\n%v", p) - } - o |= (uint32(r) & 0x3F) << 16 - if s < 0 || uint32(s) >= b { - c.ctxt.Diag("illegal bit number\n%v", p) - } - o |= (uint32(s) & 0x3F) << 10 - o |= (uint32(rf&31) << 5) | uint32(rt&31) - return o -} - -func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { - var b uint32 - o := c.opirr(p, a) - if (o & (1 << 31)) != 0 { - b = 63 - } else { - b = 31 - } - if v < 0 || uint32(v) > b { - c.ctxt.Diag("illegal bit number\n%v", p) - } - o |= uint32(v) << 10 - o |= uint32(rn&31) << 5 - o |= uint32(rm&31) << 16 - o |= uint32(rt & 31) - return o -} - -/* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */ -func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 { - wback := false - if o.scond == C_XPOST || o.scond == C_XPRE { - wback = true - } - switch p.As { - case ALDP, ALDPW, ALDPSW: - c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset)) - case ASTP, ASTPW: - if wback == true { - c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset)) - } - case AFLDPD, AFLDPS: - c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset)) - } - var ret uint32 - // check offset - switch p.As { - case AFLDPD, AFSTPD: - if vo < -512 || vo > 504 || vo%8 != 0 { - c.ctxt.Diag("invalid offset %v\n", p) - } - vo /= 8 - ret = 1<<30 | 1<<26 - case ALDP, ASTP: - if vo < -512 || vo > 504 || vo%8 != 0 { - c.ctxt.Diag("invalid offset %v\n", p) - } - vo /= 8 - ret = 2 << 30 - case AFLDPS, AFSTPS: - if vo < -256 || vo > 252 || vo%4 != 0 { - c.ctxt.Diag("invalid offset %v\n", p) - } - vo /= 4 - ret = 1 << 26 - case ALDPW, ASTPW: - if vo < -256 || vo > 252 || vo%4 != 0 { - c.ctxt.Diag("invalid offset %v\n", p) - } - vo /= 4 - ret = 0 - case ALDPSW: - if vo < -256 || vo > 252 || vo%4 != 0 { - c.ctxt.Diag("invalid offset %v\n", p) - } - vo /= 4 - ret = 1 << 30 - default: - c.ctxt.Diag("invalid instruction %v\n", p) - } - // check register pair - switch p.As { - case AFLDPD, AFLDPS, AFSTPD, AFSTPS: - if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh { - c.ctxt.Diag("invalid register pair %v\n", p) - } - case ALDP, ALDPW, ALDPSW: - if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh { - c.ctxt.Diag("invalid register pair %v\n", p) - } - case ASTP, ASTPW: - if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh { - c.ctxt.Diag("invalid register pair %v\n", p) - } - } - // other conditional flag bits - switch o.scond { - case C_XPOST: - ret |= 1 << 23 - case C_XPRE: - ret |= 3 << 23 - default: - ret |= 2 << 23 - } - ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31) - return ret -} - -func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 { - if p.As == AVLD1 || p.As == AVST1 { - return o1 - } - - o1 &^= 0xf000 // mask out "opcode" field (bit 12-15) - switch p.As { - case AVLD1R, AVLD2R: - o1 |= 0xC << 12 - case AVLD3R, AVLD4R: - o1 |= 0xE << 12 - case AVLD2, AVST2: - o1 |= 8 << 12 - case AVLD3, AVST3: - o1 |= 4 << 12 - case AVLD4, AVST4: - default: - c.ctxt.Diag("unsupported instruction:%v\n", p.As) - } - return o1 -} - -/* - * size in log2(bytes) - */ -func movesize(a obj.As) int { - switch a { - case AMOVD: - return 3 - - case AMOVW, AMOVWU: - return 2 - - case AMOVH, AMOVHU: - return 1 - - case AMOVB, AMOVBU: - return 0 - - case AFMOVS: - return 2 - - case AFMOVD: - return 3 - - default: - return -1 - } -} - -// rm is the Rm register value, o is the extension, amount is the left shift value. -func roff(rm int16, o uint32, amount int16) uint32 { - return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10 -} - -// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<> 5) & 7 - rm = r & 31 - switch { - case REG_UXTB <= r && r < REG_UXTH: - return roff(rm, 0, num) - case REG_UXTH <= r && r < REG_UXTW: - return roff(rm, 1, num) - case REG_UXTW <= r && r < REG_UXTX: - if a.Type == obj.TYPE_MEM { - if num == 0 { - return roff(rm, 2, 2) - } else { - return roff(rm, 2, 6) - } - } else { - return roff(rm, 2, num) - } - case REG_UXTX <= r && r < REG_SXTB: - return roff(rm, 3, num) - case REG_SXTB <= r && r < REG_SXTH: - return roff(rm, 4, num) - case REG_SXTH <= r && r < REG_SXTW: - return roff(rm, 5, num) - case REG_SXTW <= r && r < REG_SXTX: - if a.Type == obj.TYPE_MEM { - if num == 0 { - return roff(rm, 6, 2) - } else { - return roff(rm, 6, 6) - } - } else { - return roff(rm, 6, num) - } - case REG_SXTX <= r && r < REG_SPECIAL: - if a.Type == obj.TYPE_MEM { - if num == 0 { - return roff(rm, 7, 2) - } else { - return roff(rm, 7, 6) - } - } else { - return roff(rm, 7, num) - } - case REG_LSL <= r && r < (REG_LSL+1<<8): - return roff(rm, 3, 6) - default: - c.ctxt.Diag("unsupported register extension type.") - } - - return 0 -} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go b/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go deleted file mode 100644 index 751521754..000000000 --- a/vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package arm64 implements an ARM64 assembler. Go assembly syntax is different from GNU ARM64 -syntax, but we can still follow the general rules to map between them. - -Instructions mnemonics mapping rules - -1. Most instructions use width suffixes of instruction names to indicate operand width rather than -using different register names. - - Examples: - ADC R24, R14, R12 <=> adc x12, x24 - ADDW R26->24, R21, R15 <=> add w15, w21, w26, asr #24 - FCMPS F2, F3 <=> fcmp s3, s2 - FCMPD F2, F3 <=> fcmp d3, d2 - FCVTDH F2, F3 <=> fcvt h3, d2 - -2. Go uses .P and .W suffixes to indicate post-increment and pre-increment. - - Examples: - MOVD.P -8(R10), R8 <=> ldr x8, [x10],#-8 - MOVB.W 16(R16), R10 <=> ldrsb x10, [x16,#16]! - MOVBU.W 16(R16), R10 <=> ldrb x10, [x16,#16]! - -3. Go uses a series of MOV instructions as load and store. - -64-bit variant ldr, str, stur => MOVD; -32-bit variant str, stur, ldrsw => MOVW; -32-bit variant ldr => MOVWU; -ldrb => MOVBU; ldrh => MOVHU; -ldrsb, sturb, strb => MOVB; -ldrsh, sturh, strh => MOVH. - -4. Go moves conditions into opcode suffix, like BLT. - -5. Go adds a V prefix for most floating-point and SIMD instructions, except cryptographic extension -instructions and floating-point(scalar) instructions. - - Examples: - VADD V5.H8, V18.H8, V9.H8 <=> add v9.8h, v18.8h, v5.8h - VLD1.P (R6)(R11), [V31.D1] <=> ld1 {v31.1d}, [x6], x11 - VFMLA V29.S2, V20.S2, V14.S2 <=> fmla v14.2s, v20.2s, v29.2s - AESD V22.B16, V19.B16 <=> aesd v19.16b, v22.16b - SCVTFWS R3, F16 <=> scvtf s17, w6 - -6. Align directive - -Go asm supports the PCALIGN directive, which indicates that the next instruction should be aligned -to a specified boundary by padding with NOOP instruction. The alignment value supported on arm64 -must be a power of 2 and in the range of [8, 2048]. - - Examples: - PCALIGN $16 - MOVD $2, R0 // This instruction is aligned with 16 bytes. - PCALIGN $1024 - MOVD $3, R1 // This instruction is aligned with 1024 bytes. - -PCALIGN also changes the function alignment. If a function has one or more PCALIGN directives, -its address will be aligned to the same or coarser boundary, which is the maximum of all the -alignment values. - -In the following example, the function Add is aligned with 128 bytes. - Examples: - TEXT ·Add(SB),$40-16 - MOVD $2, R0 - PCALIGN $32 - MOVD $4, R1 - PCALIGN $128 - MOVD $8, R2 - RET - -On arm64, functions in Go are aligned to 16 bytes by default, we can also use PCALGIN to set the -function alignment. The functions that need to be aligned are preferably using NOFRAME and NOSPLIT -to avoid the impact of the prologues inserted by the assembler, so that the function address will -have the same alignment as the first hand-written instruction. - -In the following example, PCALIGN at the entry of the function Add will align its address to 2048 bytes. - - Examples: - TEXT ·Add(SB),NOSPLIT|NOFRAME,$0 - PCALIGN $2048 - MOVD $1, R0 - MOVD $1, R1 - RET - -Special Cases. - -(1) umov is written as VMOV. - -(2) br is renamed JMP, blr is renamed CALL. - -(3) No need to add "W" suffix: LDARB, LDARH, LDAXRB, LDAXRH, LDTRH, LDXRB, LDXRH. - -(4) In Go assembly syntax, NOP is a zero-width pseudo-instruction serves generic purpose, nothing -related to real ARM64 instruction. NOOP serves for the hardware nop instruction. NOOP is an alias of -HINT $0. - - Examples: - VMOV V13.B[1], R20 <=> mov x20, v13.b[1] - VMOV V13.H[1], R20 <=> mov w20, v13.h[1] - JMP (R3) <=> br x3 - CALL (R17) <=> blr x17 - LDAXRB (R19), R16 <=> ldaxrb w16, [x19] - NOOP <=> nop - - -Register mapping rules - -1. All basic register names are written as Rn. - -2. Go uses ZR as the zero register and RSP as the stack pointer. - -3. Bn, Hn, Dn, Sn and Qn instructions are written as Fn in floating-point instructions and as Vn -in SIMD instructions. - - -Argument mapping rules - -1. The operands appear in left-to-right assignment order. - -Go reverses the arguments of most instructions. - - Examples: - ADD R11.SXTB<<1, RSP, R25 <=> add x25, sp, w11, sxtb #1 - VADD V16, V19, V14 <=> add d14, d19, d16 - -Special Cases. - -(1) Argument order is the same as in the GNU ARM64 syntax: cbz, cbnz and some store instructions, -such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1. - - Examples: - MOVD R29, 384(R19) <=> str x29, [x19,#384] - MOVB.P R30, 30(R4) <=> strb w30, [x4],#30 - STLRH R21, (R19) <=> stlrh w21, [x19] - -(2) MADD, MADDW, MSUB, MSUBW, SMADDL, SMSUBL, UMADDL, UMSUBL , , , - - Examples: - MADD R2, R30, R22, R6 <=> madd x6, x22, x2, x30 - SMSUBL R10, R3, R17, R27 <=> smsubl x27, w17, w10, x3 - -(3) FMADDD, FMADDS, FMSUBD, FMSUBS, FNMADDD, FNMADDS, FNMSUBD, FNMSUBS , , , - - Examples: - FMADDD F30, F20, F3, F29 <=> fmadd d29, d3, d30, d20 - FNMSUBS F7, F25, F7, F22 <=> fnmsub s22, s7, s7, s25 - -(4) BFI, BFXIL, SBFIZ, SBFX, UBFIZ, UBFX $, , $, - - Examples: - BFIW $16, R20, $6, R0 <=> bfi w0, w20, #16, #6 - UBFIZ $34, R26, $5, R20 <=> ubfiz x20, x26, #34, #5 - -(5) FCCMPD, FCCMPS, FCCMPED, FCCMPES , Fm. Fn, $ - - Examples: - FCCMPD AL, F8, F26, $0 <=> fccmp d26, d8, #0x0, al - FCCMPS VS, F29, F4, $4 <=> fccmp s4, s29, #0x4, vs - FCCMPED LE, F20, F5, $13 <=> fccmpe d5, d20, #0xd, le - FCCMPES NE, F26, F10, $0 <=> fccmpe s10, s26, #0x0, ne - -(6) CCMN, CCMNW, CCMP, CCMPW , , $, $ - - Examples: - CCMP MI, R22, $12, $13 <=> ccmp x22, #0xc, #0xd, mi - CCMNW AL, R1, $11, $8 <=> ccmn w1, #0xb, #0x8, al - -(7) CCMN, CCMNW, CCMP, CCMPW , , , $ - - Examples: - CCMN VS, R13, R22, $10 <=> ccmn x13, x22, #0xa, vs - CCMPW HS, R19, R14, $11 <=> ccmp w19, w14, #0xb, cs - -(9) CSEL, CSELW, CSNEG, CSNEGW, CSINC, CSINCW , , , ; -FCSELD, FCSELS , , , - - Examples: - CSEL GT, R0, R19, R1 <=> csel x1, x0, x19, gt - CSNEGW GT, R7, R17, R8 <=> csneg w8, w7, w17, gt - FCSELD EQ, F15, F18, F16 <=> fcsel d16, d15, d18, eq - -(10) TBNZ, TBZ $, ,