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  }