summaryrefslogtreecommitdiffstats
path: root/src/cmd/link/internal/loong64
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:18:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:18:25 +0000
commit109be507377fe7f6e8819ac94041d3fdcdf6fd2f (patch)
tree2806a689f8fab4a2ec9fc949830ef270a91d667d /src/cmd/link/internal/loong64
parentInitial commit. (diff)
downloadgolang-1.19-upstream.tar.xz
golang-1.19-upstream.zip
Adding upstream version 1.19.8.upstream/1.19.8upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/link/internal/loong64')
-rw-r--r--src/cmd/link/internal/loong64/asm.go240
-rw-r--r--src/cmd/link/internal/loong64/l.go17
-rw-r--r--src/cmd/link/internal/loong64/obj.go58
3 files changed, 315 insertions, 0 deletions
diff --git a/src/cmd/link/internal/loong64/asm.go b/src/cmd/link/internal/loong64/asm.go
new file mode 100644
index 0000000..0eb3a81
--- /dev/null
+++ b/src/cmd/link/internal/loong64/asm.go
@@ -0,0 +1,240 @@
+// Copyright 2022 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 loong64
+
+import (
+ "cmd/internal/objabi"
+ "cmd/internal/sys"
+ "cmd/link/internal/ld"
+ "cmd/link/internal/loader"
+ "cmd/link/internal/sym"
+ "debug/elf"
+ "log"
+)
+
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
+
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
+ log.Fatalf("adddynrel not implemented")
+ return false
+}
+
+func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
+ // loong64 ELF relocation (endian neutral)
+ // offset uint64
+ // symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type.
+ // addend int64
+
+ elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
+ switch r.Type {
+ default:
+ return false
+ case objabi.R_ADDR, objabi.R_DWARFSECREF:
+ switch r.Size {
+ case 4:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+ case 8:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+ default:
+ return false
+ }
+ case objabi.R_ADDRLOONG64TLS:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
+ out.Write64(uint64(0xfff))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_AND))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_POP_32_U_10_12))
+ out.Write64(uint64(0x0))
+
+ case objabi.R_ADDRLOONG64TLSU:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
+ out.Write64(uint64(0xc))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_SR))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32)
+ out.Write64(uint64(0x0))
+
+ case objabi.R_CALLLOONG64:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PLT_PCREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2))
+ out.Write64(uint64(0x0))
+ // The pcaddu12i + addi.d instructions is used to obtain address of a symbol on Loong64.
+ // The low 12-bit of the symbol address need to be added. The addi.d instruction have
+ // signed 12-bit immediate operand. The 0x800 (addr+U12 <=> addr+0x800+S12) is introduced
+ // to do sign extending from 12 bits. The 0x804 is 0x800 + 4, 4 is instruction bit
+ // width on Loong64 and is used to correct the PC of the addi.d instruction.
+ case objabi.R_ADDRLOONG64:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd + 0x4))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd + 0x804))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
+ out.Write64(uint64(0xc))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_SR))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
+ out.Write64(uint64(0xc))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_SL))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_SUB))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_10_12))
+ out.Write64(uint64(0x0))
+
+ case objabi.R_ADDRLOONG64U:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd + 0x800))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
+ out.Write64(uint64(0xc))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_SR))
+ out.Write64(uint64(0x0))
+
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32)
+ out.Write64(uint64(0x0))
+ }
+
+ return true
+}
+
+func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
+ return
+}
+
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
+ return false
+}
+
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
+ rs := r.Sym()
+ if target.IsExternal() {
+ nExtReloc := 0
+ switch r.Type() {
+ default:
+ return val, 0, false
+ case objabi.R_ADDRLOONG64,
+ objabi.R_ADDRLOONG64U:
+ // set up addend for eventual relocation via outer symbol.
+ rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
+ rst := ldr.SymType(rs)
+ if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
+ ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
+ }
+ nExtReloc = 8 // need 8 ELF relocations. see elfreloc1
+ if r.Type() == objabi.R_ADDRLOONG64U {
+ nExtReloc = 4
+ }
+ return val, nExtReloc, true
+ case objabi.R_ADDRLOONG64TLS,
+ objabi.R_ADDRLOONG64TLSU,
+ objabi.R_CALLLOONG64,
+ objabi.R_JMPLOONG64:
+ nExtReloc = 4
+ if r.Type() == objabi.R_CALLLOONG64 || r.Type() == objabi.R_JMPLOONG64 {
+ nExtReloc = 2
+ }
+ return val, nExtReloc, true
+ }
+ }
+
+ const isOk = true
+ const noExtReloc = 0
+
+ switch r.Type() {
+ case objabi.R_CONST:
+ return r.Add(), noExtReloc, isOk
+ case objabi.R_GOTOFF:
+ return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
+ case objabi.R_ADDRLOONG64,
+ objabi.R_ADDRLOONG64U:
+ pc := ldr.SymValue(s) + int64(r.Off())
+ t := ldr.SymAddr(rs) + r.Add() - pc
+ if r.Type() == objabi.R_ADDRLOONG64 {
+ return int64(val&0xffc003ff | (((t + 4 - ((t + 4 + 1<<11) >> 12 << 12)) << 10) & 0x3ffc00)), noExtReloc, isOk
+ }
+ return int64(val&0xfe00001f | (((t + 1<<11) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
+ case objabi.R_ADDRLOONG64TLS,
+ objabi.R_ADDRLOONG64TLSU:
+ t := ldr.SymAddr(rs) + r.Add()
+ if r.Type() == objabi.R_ADDRLOONG64TLS {
+ return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk
+ }
+ return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
+ case objabi.R_CALLLOONG64,
+ objabi.R_JMPLOONG64:
+ pc := ldr.SymValue(s) + int64(r.Off())
+ t := ldr.SymAddr(rs) + r.Add() - pc
+ return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk
+ }
+
+ return val, 0, false
+}
+
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
+ return -1
+}
+
+func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
+ switch r.Type() {
+ case objabi.R_ADDRLOONG64,
+ objabi.R_ADDRLOONG64U:
+ return ld.ExtrelocViaOuterSym(ldr, r, s), true
+
+ case objabi.R_ADDRLOONG64TLS,
+ objabi.R_ADDRLOONG64TLSU,
+ objabi.R_CONST,
+ objabi.R_GOTOFF,
+ objabi.R_CALLLOONG64,
+ objabi.R_JMPLOONG64:
+ return ld.ExtrelocSimple(ldr, r), true
+ }
+ return loader.ExtReloc{}, false
+}
diff --git a/src/cmd/link/internal/loong64/l.go b/src/cmd/link/internal/loong64/l.go
new file mode 100644
index 0000000..e97a868
--- /dev/null
+++ b/src/cmd/link/internal/loong64/l.go
@@ -0,0 +1,17 @@
+// Copyright 2022 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 loong64
+
+const (
+ maxAlign = 32 // max data alignment
+ minAlign = 1 // min data alignment
+ funcAlign = 8
+)
+
+/* Used by ../../internal/ld/dwarf.go */
+const (
+ dwarfRegSP = 3
+ dwarfRegLR = 1
+)
diff --git a/src/cmd/link/internal/loong64/obj.go b/src/cmd/link/internal/loong64/obj.go
new file mode 100644
index 0000000..b564dfd
--- /dev/null
+++ b/src/cmd/link/internal/loong64/obj.go
@@ -0,0 +1,58 @@
+// Copyright 2022 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 loong64
+
+import (
+ "cmd/internal/objabi"
+ "cmd/internal/sys"
+ "cmd/link/internal/ld"
+)
+
+func Init() (*sys.Arch, ld.Arch) {
+ arch := sys.ArchLoong64
+
+ theArch := ld.Arch{
+ Funcalign: funcAlign,
+ Maxalign: maxAlign,
+ Minalign: minAlign,
+ Dwarfregsp: dwarfRegSP,
+ Dwarfreglr: dwarfRegLR,
+ Adddynrel: adddynrel,
+ Archinit: archinit,
+ Archreloc: archreloc,
+ Archrelocvariant: archrelocvariant,
+ Extreloc: extreloc,
+ Elfreloc1: elfreloc1,
+ ElfrelocSize: 24,
+ Elfsetupplt: elfsetupplt,
+ Machoreloc1: machoreloc1,
+ Gentext: gentext,
+
+ Linuxdynld: "/lib64/ld.so.1",
+ Freebsddynld: "XXX",
+ Openbsddynld: "XXX",
+ Netbsddynld: "XXX",
+ Dragonflydynld: "XXX",
+ Solarisdynld: "XXX",
+ }
+
+ return arch, theArch
+}
+
+func archinit(ctxt *ld.Link) {
+ switch ctxt.HeadType {
+ default:
+ ld.Exitf("unknown -H option: %v", ctxt.HeadType)
+ case objabi.Hlinux: /* loong64 elf */
+ ld.Elfinit(ctxt)
+ ld.HEADR = ld.ELFRESERVE
+ if *ld.FlagTextAddr == -1 {
+ *ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
+ }
+ if *ld.FlagRound == -1 {
+ *ld.FlagRound = 0x10000
+ }
+ }
+}