github.com/bir3/gocompiler@v0.9.2202/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 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt) 19 if initfunc == nil { 20 return 21 } 22 23 o := func(op uint32) { 24 initfunc.AddUint32(ctxt.Arch, op) 25 } 26 27 // Emit the following function: 28 // 29 // local.dso_init: 30 // la.pcrel $a0, local.moduledata 31 // b runtime.addmoduledata 32 33 // 0000000000000000 <local.dso_init>: 34 // 0: 1a000004 pcalau12i $a0, 0 35 // 0: R_LARCH_PCALA_HI20 local.moduledata 36 o(0x1a000004) 37 rel, _ := initfunc.AddRel(objabi.R_ADDRLOONG64U) 38 rel.SetOff(0) 39 rel.SetSiz(4) 40 rel.SetSym(ctxt.Moduledata) 41 42 // 4: 02c00084 addi.d $a0, $a0, 0 43 // 4: R_LARCH_PCALA_LO12 local.moduledata 44 o(0x02c00084) 45 rel2, _ := initfunc.AddRel(objabi.R_ADDRLOONG64) 46 rel2.SetOff(4) 47 rel2.SetSiz(4) 48 rel2.SetSym(ctxt.Moduledata) 49 50 // 8: 50000000 b 0 51 // 8: R_LARCH_B26 runtime.addmoduledata 52 o(0x50000000) 53 rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64) 54 rel3.SetOff(8) 55 rel3.SetSiz(4) 56 rel3.SetSym(addmoduledata) 57 } 58 59 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 60 log.Fatalf("adddynrel not implemented") 61 return false 62 } 63 64 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 65 // loong64 ELF relocation (endian neutral) 66 // offset uint64 67 // symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type. 68 // addend int64 69 70 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 71 switch r.Type { 72 default: 73 return false 74 case objabi.R_ADDR, objabi.R_DWARFSECREF: 75 switch r.Size { 76 case 4: 77 out.Write64(uint64(sectoff)) 78 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32) 79 out.Write64(uint64(r.Xadd)) 80 case 8: 81 out.Write64(uint64(sectoff)) 82 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32) 83 out.Write64(uint64(r.Xadd)) 84 default: 85 return false 86 } 87 case objabi.R_ADDRLOONG64TLS: 88 out.Write64(uint64(sectoff)) 89 out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32) 90 out.Write64(uint64(r.Xadd)) 91 92 case objabi.R_ADDRLOONG64TLSU: 93 out.Write64(uint64(sectoff)) 94 out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32) 95 out.Write64(uint64(r.Xadd)) 96 97 case objabi.R_CALLLOONG64: 98 out.Write64(uint64(sectoff)) 99 out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32) 100 out.Write64(uint64(r.Xadd)) 101 102 case objabi.R_LOONG64_TLS_IE_PCREL_HI: 103 out.Write64(uint64(sectoff)) 104 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32) 105 out.Write64(uint64(0x0)) 106 107 case objabi.R_LOONG64_TLS_IE_LO: 108 out.Write64(uint64(sectoff)) 109 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32) 110 out.Write64(uint64(0x0)) 111 112 case objabi.R_ADDRLOONG64: 113 out.Write64(uint64(sectoff)) 114 out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32) 115 out.Write64(uint64(r.Xadd)) 116 117 case objabi.R_ADDRLOONG64U: 118 out.Write64(uint64(sectoff)) 119 out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32) 120 out.Write64(uint64(r.Xadd)) 121 122 case objabi.R_LOONG64_GOT_HI: 123 out.Write64(uint64(sectoff)) 124 out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32) 125 out.Write64(uint64(0x0)) 126 127 case objabi.R_LOONG64_GOT_LO: 128 out.Write64(uint64(sectoff)) 129 out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32) 130 out.Write64(uint64(0x0)) 131 } 132 133 return true 134 } 135 136 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { 137 return 138 } 139 140 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 141 return false 142 } 143 144 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) { 145 rs := r.Sym() 146 if target.IsExternal() { 147 switch r.Type() { 148 default: 149 return val, 0, false 150 case objabi.R_ADDRLOONG64, 151 objabi.R_ADDRLOONG64U: 152 // set up addend for eventual relocation via outer symbol. 153 rs, _ := ld.FoldSubSymbolOffset(ldr, rs) 154 rst := ldr.SymType(rs) 155 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil { 156 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs)) 157 } 158 return val, 1, true 159 case objabi.R_ADDRLOONG64TLS, 160 objabi.R_ADDRLOONG64TLSU, 161 objabi.R_CALLLOONG64, 162 objabi.R_JMPLOONG64, 163 objabi.R_LOONG64_TLS_IE_PCREL_HI, 164 objabi.R_LOONG64_TLS_IE_LO, 165 objabi.R_LOONG64_GOT_HI, 166 objabi.R_LOONG64_GOT_LO: 167 return val, 1, true 168 } 169 } 170 171 const isOk = true 172 const noExtReloc = 0 173 174 switch r.Type() { 175 case objabi.R_CONST: 176 return r.Add(), noExtReloc, isOk 177 case objabi.R_GOTOFF: 178 return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk 179 case objabi.R_ADDRLOONG64, 180 objabi.R_ADDRLOONG64U: 181 pc := ldr.SymValue(s) + int64(r.Off()) 182 t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc) 183 if r.Type() == objabi.R_ADDRLOONG64 { 184 return int64(val&0xffc003ff | (t << 10)), noExtReloc, isOk 185 } 186 return int64(val&0xfe00001f | (t << 5)), noExtReloc, isOk 187 case objabi.R_ADDRLOONG64TLS, 188 objabi.R_ADDRLOONG64TLSU: 189 t := ldr.SymAddr(rs) + r.Add() 190 if r.Type() == objabi.R_ADDRLOONG64TLS { 191 return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk 192 } 193 return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk 194 case objabi.R_CALLLOONG64, 195 objabi.R_JMPLOONG64: 196 pc := ldr.SymValue(s) + int64(r.Off()) 197 t := ldr.SymAddr(rs) + r.Add() - pc 198 return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk 199 } 200 201 return val, 0, false 202 } 203 204 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 { 205 return -1 206 } 207 208 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { 209 switch r.Type() { 210 case objabi.R_ADDRLOONG64, 211 objabi.R_ADDRLOONG64U, 212 objabi.R_LOONG64_GOT_HI, 213 objabi.R_LOONG64_GOT_LO: 214 215 return ld.ExtrelocViaOuterSym(ldr, r, s), true 216 217 case objabi.R_ADDRLOONG64TLS, 218 objabi.R_ADDRLOONG64TLSU, 219 objabi.R_CONST, 220 objabi.R_GOTOFF, 221 objabi.R_CALLLOONG64, 222 objabi.R_JMPLOONG64, 223 objabi.R_LOONG64_TLS_IE_PCREL_HI, 224 objabi.R_LOONG64_TLS_IE_LO: 225 return ld.ExtrelocSimple(ldr, r), true 226 } 227 return loader.ExtReloc{}, false 228 } 229 230 func isRequestingLowPageBits(t objabi.RelocType) bool { 231 switch t { 232 case objabi.R_ADDRLOONG64: 233 return true 234 } 235 return false 236 } 237 238 // Calculates the value to put into the immediate slot, according to the 239 // desired relocation type, target and PC. 240 // The value to use varies based on the reloc type. Namely, the absolute low 241 // bits of the target are to be used for the low part, while the page-aligned 242 // offset is to be used for the higher part. A "page" here is not related to 243 // the system's actual page size, but rather a fixed 12-bit range (designed to 244 // cooperate with ADDI/LD/ST's 12-bit immediates). 245 func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 { 246 if isRequestingLowPageBits(t) { 247 // corresponding immediate field is 12 bits wide 248 return tgt & 0xfff 249 } 250 251 pageDelta := (tgt >> 12) - (pc >> 12) 252 if tgt&0xfff >= 0x800 { 253 // adjust for sign-extended addition of the low bits 254 pageDelta += 1 255 } 256 // corresponding immediate field is 20 bits wide 257 return pageDelta & 0xfffff 258 }