github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/loong64/asm.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package loong64 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 9 "github.com/bir3/gocompiler/src/cmd/internal/sys" 10 "github.com/bir3/gocompiler/src/cmd/link/internal/ld" 11 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 12 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 13 "debug/elf" 14 "log" 15 ) 16 17 func gentext(ctxt *ld.Link, ldr *loader.Loader) {} 18 19 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 20 log.Fatalf("adddynrel not implemented") 21 return false 22 } 23 24 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 25 // loong64 ELF relocation (endian neutral) 26 // offset uint64 27 // symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type. 28 // addend int64 29 30 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 31 switch r.Type { 32 default: 33 return false 34 case objabi.R_ADDR, objabi.R_DWARFSECREF: 35 switch r.Size { 36 case 4: 37 out.Write64(uint64(sectoff)) 38 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32) 39 out.Write64(uint64(r.Xadd)) 40 case 8: 41 out.Write64(uint64(sectoff)) 42 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32) 43 out.Write64(uint64(r.Xadd)) 44 default: 45 return false 46 } 47 case objabi.R_ADDRLOONG64TLS: 48 out.Write64(uint64(sectoff)) 49 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32) 50 out.Write64(uint64(r.Xadd)) 51 52 out.Write64(uint64(sectoff)) 53 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE)) 54 out.Write64(uint64(0xfff)) 55 56 out.Write64(uint64(sectoff)) 57 out.Write64(uint64(elf.R_LARCH_SOP_AND)) 58 out.Write64(uint64(0x0)) 59 60 out.Write64(uint64(sectoff)) 61 out.Write64(uint64(elf.R_LARCH_SOP_POP_32_U_10_12)) 62 out.Write64(uint64(0x0)) 63 64 case objabi.R_ADDRLOONG64TLSU: 65 out.Write64(uint64(sectoff)) 66 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32) 67 out.Write64(uint64(r.Xadd)) 68 69 out.Write64(uint64(sectoff)) 70 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE)) 71 out.Write64(uint64(0xc)) 72 73 out.Write64(uint64(sectoff)) 74 out.Write64(uint64(elf.R_LARCH_SOP_SR)) 75 out.Write64(uint64(0x0)) 76 77 out.Write64(uint64(sectoff)) 78 out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32) 79 out.Write64(uint64(0x0)) 80 81 case objabi.R_CALLLOONG64: 82 out.Write64(uint64(sectoff)) 83 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PLT_PCREL) | uint64(elfsym)<<32) 84 out.Write64(uint64(r.Xadd)) 85 86 out.Write64(uint64(sectoff)) 87 out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2)) 88 out.Write64(uint64(0x0)) 89 // The pcaddu12i + addi.d instructions is used to obtain address of a symbol on Loong64. 90 // The low 12-bit of the symbol address need to be added. The addi.d instruction have 91 // signed 12-bit immediate operand. The 0x800 (addr+U12 <=> addr+0x800+S12) is introduced 92 // to do sign extending from 12 bits. The 0x804 is 0x800 + 4, 4 is instruction bit 93 // width on Loong64 and is used to correct the PC of the addi.d instruction. 94 case objabi.R_ADDRLOONG64: 95 out.Write64(uint64(sectoff)) 96 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32) 97 out.Write64(uint64(r.Xadd + 0x4)) 98 99 out.Write64(uint64(sectoff)) 100 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32) 101 out.Write64(uint64(r.Xadd + 0x804)) 102 103 out.Write64(uint64(sectoff)) 104 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE)) 105 out.Write64(uint64(0xc)) 106 107 out.Write64(uint64(sectoff)) 108 out.Write64(uint64(elf.R_LARCH_SOP_SR)) 109 out.Write64(uint64(0x0)) 110 111 out.Write64(uint64(sectoff)) 112 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE)) 113 out.Write64(uint64(0xc)) 114 115 out.Write64(uint64(sectoff)) 116 out.Write64(uint64(elf.R_LARCH_SOP_SL)) 117 out.Write64(uint64(0x0)) 118 119 out.Write64(uint64(sectoff)) 120 out.Write64(uint64(elf.R_LARCH_SOP_SUB)) 121 out.Write64(uint64(0x0)) 122 123 out.Write64(uint64(sectoff)) 124 out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_10_12)) 125 out.Write64(uint64(0x0)) 126 127 case objabi.R_ADDRLOONG64U: 128 out.Write64(uint64(sectoff)) 129 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32) 130 out.Write64(uint64(r.Xadd + 0x800)) 131 132 out.Write64(uint64(sectoff)) 133 out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE)) 134 out.Write64(uint64(0xc)) 135 136 out.Write64(uint64(sectoff)) 137 out.Write64(uint64(elf.R_LARCH_SOP_SR)) 138 out.Write64(uint64(0x0)) 139 140 out.Write64(uint64(sectoff)) 141 out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32) 142 out.Write64(uint64(0x0)) 143 } 144 145 return true 146 } 147 148 func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { 149 return 150 } 151 152 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 153 return false 154 } 155 156 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) { 157 rs := r.Sym() 158 if target.IsExternal() { 159 nExtReloc := 0 160 switch r.Type() { 161 default: 162 return val, 0, false 163 case objabi.R_ADDRLOONG64, 164 objabi.R_ADDRLOONG64U: 165 // set up addend for eventual relocation via outer symbol. 166 rs, _ := ld.FoldSubSymbolOffset(ldr, rs) 167 rst := ldr.SymType(rs) 168 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil { 169 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs)) 170 } 171 nExtReloc = 8 // need 8 ELF relocations. see elfreloc1 172 if r.Type() == objabi.R_ADDRLOONG64U { 173 nExtReloc = 4 174 } 175 return val, nExtReloc, true 176 case objabi.R_ADDRLOONG64TLS, 177 objabi.R_ADDRLOONG64TLSU, 178 objabi.R_CALLLOONG64, 179 objabi.R_JMPLOONG64: 180 nExtReloc = 4 181 if r.Type() == objabi.R_CALLLOONG64 || r.Type() == objabi.R_JMPLOONG64 { 182 nExtReloc = 2 183 } 184 return val, nExtReloc, true 185 } 186 } 187 188 const isOk = true 189 const noExtReloc = 0 190 191 switch r.Type() { 192 case objabi.R_CONST: 193 return r.Add(), noExtReloc, isOk 194 case objabi.R_GOTOFF: 195 return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk 196 case objabi.R_ADDRLOONG64, 197 objabi.R_ADDRLOONG64U: 198 pc := ldr.SymValue(s) + int64(r.Off()) 199 t := ldr.SymAddr(rs) + r.Add() - pc 200 if r.Type() == objabi.R_ADDRLOONG64 { 201 return int64(val&0xffc003ff | (((t + 4 - ((t + 4 + 1<<11) >> 12 << 12)) << 10) & 0x3ffc00)), noExtReloc, isOk 202 } 203 return int64(val&0xfe00001f | (((t + 1<<11) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk 204 case objabi.R_ADDRLOONG64TLS, 205 objabi.R_ADDRLOONG64TLSU: 206 t := ldr.SymAddr(rs) + r.Add() 207 if r.Type() == objabi.R_ADDRLOONG64TLS { 208 return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk 209 } 210 return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk 211 case objabi.R_CALLLOONG64, 212 objabi.R_JMPLOONG64: 213 pc := ldr.SymValue(s) + int64(r.Off()) 214 t := ldr.SymAddr(rs) + r.Add() - pc 215 return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk 216 } 217 218 return val, 0, false 219 } 220 221 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 { 222 return -1 223 } 224 225 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { 226 switch r.Type() { 227 case objabi.R_ADDRLOONG64, 228 objabi.R_ADDRLOONG64U: 229 return ld.ExtrelocViaOuterSym(ldr, r, s), true 230 231 case objabi.R_ADDRLOONG64TLS, 232 objabi.R_ADDRLOONG64TLSU, 233 objabi.R_CONST, 234 objabi.R_GOTOFF, 235 objabi.R_CALLLOONG64, 236 objabi.R_JMPLOONG64: 237 return ld.ExtrelocSimple(ldr, r), true 238 } 239 return loader.ExtReloc{}, false 240 }