github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/cmd/link/internal/mips64/asm.go (about)

     1  // Inferno utils/5l/asm.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package mips64
    32  
    33  import (
    34  	"cmd/internal/obj"
    35  	"cmd/link/internal/ld"
    36  	"encoding/binary"
    37  	"fmt"
    38  	"log"
    39  )
    40  
    41  func gentext() {}
    42  
    43  func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
    44  	log.Fatalf("adddynrela not implemented")
    45  }
    46  
    47  func adddynrel(s *ld.LSym, r *ld.Reloc) {
    48  	log.Fatalf("adddynrel not implemented")
    49  }
    50  
    51  func elfreloc1(r *ld.Reloc, sectoff int64) int {
    52  	return -1
    53  }
    54  
    55  func elfsetupplt() {
    56  	return
    57  }
    58  
    59  func machoreloc1(r *ld.Reloc, sectoff int64) int {
    60  	return -1
    61  }
    62  
    63  func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
    64  	if ld.Linkmode == ld.LinkExternal {
    65  		return -1
    66  	}
    67  
    68  	switch r.Type {
    69  	case obj.R_CONST:
    70  		*val = r.Add
    71  		return 0
    72  
    73  	case obj.R_GOTOFF:
    74  		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
    75  		return 0
    76  
    77  	case obj.R_ADDRMIPS:
    78  		t := ld.Symaddr(r.Sym) + r.Add
    79  		if t >= 1<<32 || t < -1<<32 {
    80  			ld.Diag("program too large, address relocation = %v", t)
    81  		}
    82  
    83  		// the first instruction is always at the lower address, this is endian neutral;
    84  		// but note that o1 and o2 should still use the target endian.
    85  		o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
    86  		o2 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4:])
    87  		o1 = o1&0xffff0000 | uint32(t>>16)&0xffff
    88  		o2 = o2&0xffff0000 | uint32(t)&0xffff
    89  
    90  		// when laid out, the instruction order must always be o1, o2.
    91  		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
    92  			*val = int64(o1)<<32 | int64(o2)
    93  		} else {
    94  			*val = int64(o2)<<32 | int64(o1)
    95  		}
    96  		return 0
    97  
    98  	case obj.R_CALLMIPS,
    99  		obj.R_JMPMIPS:
   100  		// Low 26 bits = (S + A) >> 2
   101  		t := ld.Symaddr(r.Sym) + r.Add
   102  		o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
   103  		*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
   104  		return 0
   105  	}
   106  
   107  	return -1
   108  }
   109  
   110  func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
   111  	return -1
   112  }
   113  
   114  func asmb() {
   115  	if ld.Debug['v'] != 0 {
   116  		fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
   117  	}
   118  	ld.Bso.Flush()
   119  
   120  	if ld.Iself {
   121  		ld.Asmbelfsetup()
   122  	}
   123  
   124  	sect := ld.Segtext.Sect
   125  	ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   126  	ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
   127  	for sect = sect.Next; sect != nil; sect = sect.Next {
   128  		ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   129  		ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
   130  	}
   131  
   132  	if ld.Segrodata.Filelen > 0 {
   133  		if ld.Debug['v'] != 0 {
   134  			fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
   135  		}
   136  		ld.Bso.Flush()
   137  
   138  		ld.Cseek(int64(ld.Segrodata.Fileoff))
   139  		ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
   140  	}
   141  
   142  	if ld.Debug['v'] != 0 {
   143  		fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
   144  	}
   145  	ld.Bso.Flush()
   146  
   147  	ld.Cseek(int64(ld.Segdata.Fileoff))
   148  	ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
   149  
   150  	/* output symbol table */
   151  	ld.Symsize = 0
   152  
   153  	ld.Lcsize = 0
   154  	symo := uint32(0)
   155  	if ld.Debug['s'] == 0 {
   156  		// TODO: rationalize
   157  		if ld.Debug['v'] != 0 {
   158  			fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
   159  		}
   160  		ld.Bso.Flush()
   161  		switch ld.HEADTYPE {
   162  		default:
   163  			if ld.Iself {
   164  				symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
   165  				symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
   166  			}
   167  
   168  		case obj.Hplan9:
   169  			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
   170  		}
   171  
   172  		ld.Cseek(int64(symo))
   173  		switch ld.HEADTYPE {
   174  		default:
   175  			if ld.Iself {
   176  				if ld.Debug['v'] != 0 {
   177  					fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
   178  				}
   179  				ld.Asmelfsym()
   180  				ld.Cflush()
   181  				ld.Cwrite(ld.Elfstrdat)
   182  
   183  				if ld.Debug['v'] != 0 {
   184  					fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
   185  				}
   186  				ld.Dwarfemitdebugsections()
   187  
   188  				if ld.Linkmode == ld.LinkExternal {
   189  					ld.Elfemitreloc()
   190  				}
   191  			}
   192  
   193  		case obj.Hplan9:
   194  			ld.Asmplan9sym()
   195  			ld.Cflush()
   196  
   197  			sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
   198  			if sym != nil {
   199  				ld.Lcsize = int32(len(sym.P))
   200  				for i := 0; int32(i) < ld.Lcsize; i++ {
   201  					ld.Cput(uint8(sym.P[i]))
   202  				}
   203  
   204  				ld.Cflush()
   205  			}
   206  		}
   207  	}
   208  
   209  	ld.Ctxt.Cursym = nil
   210  	if ld.Debug['v'] != 0 {
   211  		fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
   212  	}
   213  	ld.Bso.Flush()
   214  	ld.Cseek(0)
   215  	switch ld.HEADTYPE {
   216  	default:
   217  	case obj.Hplan9: /* plan 9 */
   218  		magic := uint32(4*18*18 + 7)
   219  		if ld.Thestring == "mips64le" {
   220  			magic = uint32(4*26*26 + 7)
   221  		}
   222  		ld.Thearch.Lput(uint32(magic))              /* magic */
   223  		ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
   224  		ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
   225  		ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
   226  		ld.Thearch.Lput(uint32(ld.Symsize))      /* nsyms */
   227  		ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
   228  		ld.Thearch.Lput(0)
   229  		ld.Thearch.Lput(uint32(ld.Lcsize))
   230  
   231  	case obj.Hlinux,
   232  		obj.Hfreebsd,
   233  		obj.Hnetbsd,
   234  		obj.Hopenbsd,
   235  		obj.Hnacl:
   236  		ld.Asmbelf(int64(symo))
   237  	}
   238  
   239  	ld.Cflush()
   240  	if ld.Debug['c'] != 0 {
   241  		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
   242  		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
   243  		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
   244  		fmt.Printf("symsize=%d\n", ld.Symsize)
   245  		fmt.Printf("lcsize=%d\n", ld.Lcsize)
   246  		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
   247  	}
   248  }