]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/mips64/asm.go
68d52ec954ff4cb459c926e90f2fbf4cf2d4c4a0
[gostls13.git] / src / cmd / link / internal / mips64 / asm.go
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/internal/sys"
36         "cmd/link/internal/ld"
37         "fmt"
38         "log"
39 )
40
41 func gentext() {}
42
43 func adddynrel(s *ld.LSym, r *ld.Reloc) {
44         log.Fatalf("adddynrel not implemented")
45 }
46
47 func elfreloc1(r *ld.Reloc, sectoff int64) int {
48         // mips64 ELF relocation (endian neutral)
49         //              offset  uint64
50         //              sym             uint32
51         //              ssym    uint8
52         //              type3   uint8
53         //              type2   uint8
54         //              type    uint8
55         //              addend  int64
56
57         ld.Thearch.Vput(uint64(sectoff))
58
59         elfsym := r.Xsym.ElfsymForReloc()
60         ld.Thearch.Lput(uint32(elfsym))
61         ld.Cput(0)
62         ld.Cput(0)
63         ld.Cput(0)
64         switch r.Type {
65         default:
66                 return -1
67
68         case obj.R_ADDR:
69                 switch r.Siz {
70                 case 4:
71                         ld.Cput(ld.R_MIPS_32)
72                 case 8:
73                         ld.Cput(ld.R_MIPS_64)
74                 default:
75                         return -1
76                 }
77
78         case obj.R_ADDRMIPS:
79                 ld.Cput(ld.R_MIPS_LO16)
80
81         case obj.R_ADDRMIPSU:
82                 ld.Cput(ld.R_MIPS_HI16)
83
84         case obj.R_ADDRMIPSTLS:
85                 ld.Cput(ld.R_MIPS_TLS_TPREL_LO16)
86
87         case obj.R_CALLMIPS,
88                 obj.R_JMPMIPS:
89                 ld.Cput(ld.R_MIPS_26)
90         }
91         ld.Thearch.Vput(uint64(r.Xadd))
92
93         return 0
94 }
95
96 func elfsetupplt() {
97         return
98 }
99
100 func machoreloc1(r *ld.Reloc, sectoff int64) int {
101         return -1
102 }
103
104 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
105         if ld.Linkmode == ld.LinkExternal {
106                 switch r.Type {
107                 default:
108                         return -1
109
110                 case obj.R_ADDRMIPS,
111                         obj.R_ADDRMIPSU:
112                         r.Done = 0
113
114                         // set up addend for eventual relocation via outer symbol.
115                         rs := r.Sym
116                         r.Xadd = r.Add
117                         for rs.Outer != nil {
118                                 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
119                                 rs = rs.Outer
120                         }
121
122                         if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
123                                 ld.Diag("missing section for %s", rs.Name)
124                         }
125                         r.Xsym = rs
126
127                         return 0
128
129                 case obj.R_ADDRMIPSTLS,
130                         obj.R_CALLMIPS,
131                         obj.R_JMPMIPS:
132                         r.Done = 0
133                         r.Xsym = r.Sym
134                         r.Xadd = r.Add
135                         return 0
136                 }
137         }
138
139         switch r.Type {
140         case obj.R_CONST:
141                 *val = r.Add
142                 return 0
143
144         case obj.R_GOTOFF:
145                 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
146                 return 0
147
148         case obj.R_ADDRMIPS,
149                 obj.R_ADDRMIPSU:
150                 t := ld.Symaddr(r.Sym) + r.Add
151                 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
152                 if r.Type == obj.R_ADDRMIPS {
153                         *val = int64(o1&0xffff0000 | uint32(t)&0xffff)
154                 } else {
155                         *val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
156                 }
157                 return 0
158
159         case obj.R_ADDRMIPSTLS:
160                 // thread pointer is at 0x7000 offset from the start of TLS data area
161                 t := ld.Symaddr(r.Sym) + r.Add - 0x7000
162                 if t < -32768 || t >= 32678 {
163                         ld.Diag("TLS offset out of range %d", t)
164                 }
165                 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
166                 *val = int64(o1&0xffff0000 | uint32(t)&0xffff)
167                 return 0
168
169         case obj.R_CALLMIPS,
170                 obj.R_JMPMIPS:
171                 // Low 26 bits = (S + A) >> 2
172                 t := ld.Symaddr(r.Sym) + r.Add
173                 o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
174                 *val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
175                 return 0
176         }
177
178         return -1
179 }
180
181 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
182         return -1
183 }
184
185 func asmb() {
186         if ld.Debug['v'] != 0 {
187                 fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
188         }
189         ld.Bso.Flush()
190
191         if ld.Iself {
192                 ld.Asmbelfsetup()
193         }
194
195         sect := ld.Segtext.Sect
196         ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
197         ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
198         for sect = sect.Next; sect != nil; sect = sect.Next {
199                 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
200                 ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
201         }
202
203         if ld.Segrodata.Filelen > 0 {
204                 if ld.Debug['v'] != 0 {
205                         fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
206                 }
207                 ld.Bso.Flush()
208
209                 ld.Cseek(int64(ld.Segrodata.Fileoff))
210                 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
211         }
212
213         if ld.Debug['v'] != 0 {
214                 fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
215         }
216         ld.Bso.Flush()
217
218         ld.Cseek(int64(ld.Segdata.Fileoff))
219         ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
220
221         ld.Cseek(int64(ld.Segdwarf.Fileoff))
222         ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
223
224         /* output symbol table */
225         ld.Symsize = 0
226
227         ld.Lcsize = 0
228         symo := uint32(0)
229         if ld.Debug['s'] == 0 {
230                 // TODO: rationalize
231                 if ld.Debug['v'] != 0 {
232                         fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
233                 }
234                 ld.Bso.Flush()
235                 switch ld.HEADTYPE {
236                 default:
237                         if ld.Iself {
238                                 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
239                                 symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
240                         }
241
242                 case obj.Hplan9:
243                         symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
244                 }
245
246                 ld.Cseek(int64(symo))
247                 switch ld.HEADTYPE {
248                 default:
249                         if ld.Iself {
250                                 if ld.Debug['v'] != 0 {
251                                         fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
252                                 }
253                                 ld.Asmelfsym()
254                                 ld.Cflush()
255                                 ld.Cwrite(ld.Elfstrdat)
256
257                                 if ld.Linkmode == ld.LinkExternal {
258                                         ld.Elfemitreloc()
259                                 }
260                         }
261
262                 case obj.Hplan9:
263                         ld.Asmplan9sym()
264                         ld.Cflush()
265
266                         sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
267                         if sym != nil {
268                                 ld.Lcsize = int32(len(sym.P))
269                                 for i := 0; int32(i) < ld.Lcsize; i++ {
270                                         ld.Cput(sym.P[i])
271                                 }
272
273                                 ld.Cflush()
274                         }
275                 }
276         }
277
278         ld.Ctxt.Cursym = nil
279         if ld.Debug['v'] != 0 {
280                 fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
281         }
282         ld.Bso.Flush()
283         ld.Cseek(0)
284         switch ld.HEADTYPE {
285         default:
286         case obj.Hplan9: /* plan 9 */
287                 magic := uint32(4*18*18 + 7)
288                 if ld.SysArch == sys.ArchMIPS64LE {
289                         magic = uint32(4*26*26 + 7)
290                 }
291                 ld.Thearch.Lput(magic)                      /* magic */
292                 ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
293                 ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
294                 ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
295                 ld.Thearch.Lput(uint32(ld.Symsize))      /* nsyms */
296                 ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
297                 ld.Thearch.Lput(0)
298                 ld.Thearch.Lput(uint32(ld.Lcsize))
299
300         case obj.Hlinux,
301                 obj.Hfreebsd,
302                 obj.Hnetbsd,
303                 obj.Hopenbsd,
304                 obj.Hnacl:
305                 ld.Asmbelf(int64(symo))
306         }
307
308         ld.Cflush()
309         if ld.Debug['c'] != 0 {
310                 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
311                 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
312                 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
313                 fmt.Printf("symsize=%d\n", ld.Symsize)
314                 fmt.Printf("lcsize=%d\n", ld.Lcsize)
315                 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
316         }
317 }