podman

Форк
0
1278 строк · 30.9 Кб
1
// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
2
//
3
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
4
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
5
//	Portions Copyright © 1997-1999 Vita Nuova Limited
6
//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
7
//	Portions Copyright © 2004,2006 Bruce Ellis
8
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
9
//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
10
//	Portions Copyright © 2009 The Go Authors. All rights reserved.
11
//
12
// Permission is hereby granted, free of charge, to any person obtaining a copy
13
// of this software and associated documentation files (the "Software"), to deal
14
// in the Software without restriction, including without limitation the rights
15
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
// copies of the Software, and to permit persons to whom the Software is
17
// furnished to do so, subject to the following conditions:
18
//
19
// The above copyright notice and this permission notice shall be included in
20
// all copies or substantial portions of the Software.
21
//
22
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
// THE SOFTWARE.
29

30
package ppc64
31

32
import (
33
	"github.com/twitchyliquid64/golang-asm/obj"
34
	"github.com/twitchyliquid64/golang-asm/objabi"
35
	"github.com/twitchyliquid64/golang-asm/sys"
36
)
37

38
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
39
	p.From.Class = 0
40
	p.To.Class = 0
41

42
	c := ctxt9{ctxt: ctxt, newprog: newprog}
43

44
	// Rewrite BR/BL to symbol as TYPE_BRANCH.
45
	switch p.As {
46
	case ABR,
47
		ABL,
48
		obj.ARET,
49
		obj.ADUFFZERO,
50
		obj.ADUFFCOPY:
51
		if p.To.Sym != nil {
52
			p.To.Type = obj.TYPE_BRANCH
53
		}
54
	}
55

56
	// Rewrite float constants to values stored in memory.
57
	switch p.As {
58
	case AFMOVS:
59
		if p.From.Type == obj.TYPE_FCONST {
60
			f32 := float32(p.From.Val.(float64))
61
			p.From.Type = obj.TYPE_MEM
62
			p.From.Sym = ctxt.Float32Sym(f32)
63
			p.From.Name = obj.NAME_EXTERN
64
			p.From.Offset = 0
65
		}
66

67
	case AFMOVD:
68
		if p.From.Type == obj.TYPE_FCONST {
69
			f64 := p.From.Val.(float64)
70
			// Constant not needed in memory for float +/- 0
71
			if f64 != 0 {
72
				p.From.Type = obj.TYPE_MEM
73
				p.From.Sym = ctxt.Float64Sym(f64)
74
				p.From.Name = obj.NAME_EXTERN
75
				p.From.Offset = 0
76
			}
77
		}
78

79
		// Put >32-bit constants in memory and load them
80
	case AMOVD:
81
		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
82
			p.From.Type = obj.TYPE_MEM
83
			p.From.Sym = ctxt.Int64Sym(p.From.Offset)
84
			p.From.Name = obj.NAME_EXTERN
85
			p.From.Offset = 0
86
		}
87
	}
88

89
	// Rewrite SUB constants into ADD.
90
	switch p.As {
91
	case ASUBC:
92
		if p.From.Type == obj.TYPE_CONST {
93
			p.From.Offset = -p.From.Offset
94
			p.As = AADDC
95
		}
96

97
	case ASUBCCC:
98
		if p.From.Type == obj.TYPE_CONST {
99
			p.From.Offset = -p.From.Offset
100
			p.As = AADDCCC
101
		}
102

103
	case ASUB:
104
		if p.From.Type == obj.TYPE_CONST {
105
			p.From.Offset = -p.From.Offset
106
			p.As = AADD
107
		}
108
	}
109
	if c.ctxt.Headtype == objabi.Haix {
110
		c.rewriteToUseTOC(p)
111
	} else if c.ctxt.Flag_dynlink {
112
		c.rewriteToUseGot(p)
113
	}
114
}
115

116
// Rewrite p, if necessary, to access a symbol using its TOC anchor.
117
// This code is for AIX only.
118
func (c *ctxt9) rewriteToUseTOC(p *obj.Prog) {
119
	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
120
		return
121
	}
122

123
	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
124
		// ADUFFZERO/ADUFFCOPY is considered as an ABL except in dynamic
125
		// link where it should be an indirect call.
126
		if !c.ctxt.Flag_dynlink {
127
			return
128
		}
129
		//     ADUFFxxx $offset
130
		// becomes
131
		//     MOVD runtime.duffxxx@TOC, R12
132
		//     ADD $offset, R12
133
		//     MOVD R12, LR
134
		//     BL (LR)
135
		var sym *obj.LSym
136
		if p.As == obj.ADUFFZERO {
137
			sym = c.ctxt.Lookup("runtime.duffzero")
138
		} else {
139
			sym = c.ctxt.Lookup("runtime.duffcopy")
140
		}
141
		// Retrieve or create the TOC anchor.
142
		symtoc := c.ctxt.LookupInit("TOC."+sym.Name, func(s *obj.LSym) {
143
			s.Type = objabi.SDATA
144
			s.Set(obj.AttrDuplicateOK, true)
145
			s.Set(obj.AttrStatic, true)
146
			c.ctxt.Data = append(c.ctxt.Data, s)
147
			s.WriteAddr(c.ctxt, 0, 8, sym, 0)
148
		})
149

150
		offset := p.To.Offset
151
		p.As = AMOVD
152
		p.From.Type = obj.TYPE_MEM
153
		p.From.Name = obj.NAME_TOCREF
154
		p.From.Sym = symtoc
155
		p.To.Type = obj.TYPE_REG
156
		p.To.Reg = REG_R12
157
		p.To.Name = obj.NAME_NONE
158
		p.To.Offset = 0
159
		p.To.Sym = nil
160
		p1 := obj.Appendp(p, c.newprog)
161
		p1.As = AADD
162
		p1.From.Type = obj.TYPE_CONST
163
		p1.From.Offset = offset
164
		p1.To.Type = obj.TYPE_REG
165
		p1.To.Reg = REG_R12
166
		p2 := obj.Appendp(p1, c.newprog)
167
		p2.As = AMOVD
168
		p2.From.Type = obj.TYPE_REG
169
		p2.From.Reg = REG_R12
170
		p2.To.Type = obj.TYPE_REG
171
		p2.To.Reg = REG_LR
172
		p3 := obj.Appendp(p2, c.newprog)
173
		p3.As = obj.ACALL
174
		p3.To.Type = obj.TYPE_REG
175
		p3.To.Reg = REG_LR
176
	}
177

178
	var source *obj.Addr
179
	if p.From.Name == obj.NAME_EXTERN || p.From.Name == obj.NAME_STATIC {
180
		if p.From.Type == obj.TYPE_ADDR {
181
			if p.As == ADWORD {
182
				// ADWORD $sym doesn't need TOC anchor
183
				return
184
			}
185
			if p.As != AMOVD {
186
				c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v", p)
187
				return
188
			}
189
			if p.To.Type != obj.TYPE_REG {
190
				c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v", p)
191
				return
192
			}
193
		} else if p.From.Type != obj.TYPE_MEM {
194
			c.ctxt.Diag("do not know how to handle %v without TYPE_MEM", p)
195
			return
196
		}
197
		source = &p.From
198

199
	} else if p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC {
200
		if p.To.Type != obj.TYPE_MEM {
201
			c.ctxt.Diag("do not know how to handle %v without TYPE_MEM", p)
202
			return
203
		}
204
		if source != nil {
205
			c.ctxt.Diag("cannot handle symbols on both sides in %v", p)
206
			return
207
		}
208
		source = &p.To
209
	} else {
210
		return
211

212
	}
213

214
	if source.Sym == nil {
215
		c.ctxt.Diag("do not know how to handle nil symbol in %v", p)
216
		return
217
	}
218

219
	if source.Sym.Type == objabi.STLSBSS {
220
		return
221
	}
222

223
	// Retrieve or create the TOC anchor.
224
	symtoc := c.ctxt.LookupInit("TOC."+source.Sym.Name, func(s *obj.LSym) {
225
		s.Type = objabi.SDATA
226
		s.Set(obj.AttrDuplicateOK, true)
227
		s.Set(obj.AttrStatic, true)
228
		c.ctxt.Data = append(c.ctxt.Data, s)
229
		s.WriteAddr(c.ctxt, 0, 8, source.Sym, 0)
230
	})
231

232
	if source.Type == obj.TYPE_ADDR {
233
		// MOVD $sym, Rx becomes MOVD symtoc, Rx
234
		// MOVD $sym+<off>, Rx becomes MOVD symtoc, Rx; ADD <off>, Rx
235
		p.From.Type = obj.TYPE_MEM
236
		p.From.Sym = symtoc
237
		p.From.Name = obj.NAME_TOCREF
238

239
		if p.From.Offset != 0 {
240
			q := obj.Appendp(p, c.newprog)
241
			q.As = AADD
242
			q.From.Type = obj.TYPE_CONST
243
			q.From.Offset = p.From.Offset
244
			p.From.Offset = 0
245
			q.To = p.To
246
		}
247
		return
248

249
	}
250

251
	// MOVx sym, Ry becomes MOVD symtoc, REGTMP; MOVx (REGTMP), Ry
252
	// MOVx Ry, sym becomes MOVD symtoc, REGTMP; MOVx Ry, (REGTMP)
253
	// An addition may be inserted between the two MOVs if there is an offset.
254

255
	q := obj.Appendp(p, c.newprog)
256
	q.As = AMOVD
257
	q.From.Type = obj.TYPE_MEM
258
	q.From.Sym = symtoc
259
	q.From.Name = obj.NAME_TOCREF
260
	q.To.Type = obj.TYPE_REG
261
	q.To.Reg = REGTMP
262

263
	q = obj.Appendp(q, c.newprog)
264
	q.As = p.As
265
	q.From = p.From
266
	q.To = p.To
267
	if p.From.Name != obj.NAME_NONE {
268
		q.From.Type = obj.TYPE_MEM
269
		q.From.Reg = REGTMP
270
		q.From.Name = obj.NAME_NONE
271
		q.From.Sym = nil
272
	} else if p.To.Name != obj.NAME_NONE {
273
		q.To.Type = obj.TYPE_MEM
274
		q.To.Reg = REGTMP
275
		q.To.Name = obj.NAME_NONE
276
		q.To.Sym = nil
277
	} else {
278
		c.ctxt.Diag("unreachable case in rewriteToUseTOC with %v", p)
279
	}
280

281
	obj.Nopout(p)
282
}
283

284
// Rewrite p, if necessary, to access global data via the global offset table.
285
func (c *ctxt9) rewriteToUseGot(p *obj.Prog) {
286
	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
287
		//     ADUFFxxx $offset
288
		// becomes
289
		//     MOVD runtime.duffxxx@GOT, R12
290
		//     ADD $offset, R12
291
		//     MOVD R12, LR
292
		//     BL (LR)
293
		var sym *obj.LSym
294
		if p.As == obj.ADUFFZERO {
295
			sym = c.ctxt.Lookup("runtime.duffzero")
296
		} else {
297
			sym = c.ctxt.Lookup("runtime.duffcopy")
298
		}
299
		offset := p.To.Offset
300
		p.As = AMOVD
301
		p.From.Type = obj.TYPE_MEM
302
		p.From.Name = obj.NAME_GOTREF
303
		p.From.Sym = sym
304
		p.To.Type = obj.TYPE_REG
305
		p.To.Reg = REG_R12
306
		p.To.Name = obj.NAME_NONE
307
		p.To.Offset = 0
308
		p.To.Sym = nil
309
		p1 := obj.Appendp(p, c.newprog)
310
		p1.As = AADD
311
		p1.From.Type = obj.TYPE_CONST
312
		p1.From.Offset = offset
313
		p1.To.Type = obj.TYPE_REG
314
		p1.To.Reg = REG_R12
315
		p2 := obj.Appendp(p1, c.newprog)
316
		p2.As = AMOVD
317
		p2.From.Type = obj.TYPE_REG
318
		p2.From.Reg = REG_R12
319
		p2.To.Type = obj.TYPE_REG
320
		p2.To.Reg = REG_LR
321
		p3 := obj.Appendp(p2, c.newprog)
322
		p3.As = obj.ACALL
323
		p3.To.Type = obj.TYPE_REG
324
		p3.To.Reg = REG_LR
325
	}
326

327
	// We only care about global data: NAME_EXTERN means a global
328
	// symbol in the Go sense, and p.Sym.Local is true for a few
329
	// internally defined symbols.
330
	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
331
		// MOVD $sym, Rx becomes MOVD sym@GOT, Rx
332
		// MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
333
		if p.As != AMOVD {
334
			c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
335
		}
336
		if p.To.Type != obj.TYPE_REG {
337
			c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
338
		}
339
		p.From.Type = obj.TYPE_MEM
340
		p.From.Name = obj.NAME_GOTREF
341
		if p.From.Offset != 0 {
342
			q := obj.Appendp(p, c.newprog)
343
			q.As = AADD
344
			q.From.Type = obj.TYPE_CONST
345
			q.From.Offset = p.From.Offset
346
			q.To = p.To
347
			p.From.Offset = 0
348
		}
349
	}
350
	if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
351
		c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
352
	}
353
	var source *obj.Addr
354
	// MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
355
	// MOVx Ry, sym becomes MOVD sym@GOT, REGTMP; MOVx Ry, (REGTMP)
356
	// An addition may be inserted between the two MOVs if there is an offset.
357
	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
358
		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
359
			c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
360
		}
361
		source = &p.From
362
	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
363
		source = &p.To
364
	} else {
365
		return
366
	}
367
	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
368
		return
369
	}
370
	if source.Sym.Type == objabi.STLSBSS {
371
		return
372
	}
373
	if source.Type != obj.TYPE_MEM {
374
		c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
375
	}
376
	p1 := obj.Appendp(p, c.newprog)
377
	p2 := obj.Appendp(p1, c.newprog)
378

379
	p1.As = AMOVD
380
	p1.From.Type = obj.TYPE_MEM
381
	p1.From.Sym = source.Sym
382
	p1.From.Name = obj.NAME_GOTREF
383
	p1.To.Type = obj.TYPE_REG
384
	p1.To.Reg = REGTMP
385

386
	p2.As = p.As
387
	p2.From = p.From
388
	p2.To = p.To
389
	if p.From.Name == obj.NAME_EXTERN {
390
		p2.From.Reg = REGTMP
391
		p2.From.Name = obj.NAME_NONE
392
		p2.From.Sym = nil
393
	} else if p.To.Name == obj.NAME_EXTERN {
394
		p2.To.Reg = REGTMP
395
		p2.To.Name = obj.NAME_NONE
396
		p2.To.Sym = nil
397
	} else {
398
		return
399
	}
400
	obj.Nopout(p)
401
}
402

403
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
404
	// TODO(minux): add morestack short-cuts with small fixed frame-size.
405
	if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
406
		return
407
	}
408

409
	c := ctxt9{ctxt: ctxt, cursym: cursym, newprog: newprog}
410

411
	p := c.cursym.Func.Text
412
	textstksiz := p.To.Offset
413
	if textstksiz == -8 {
414
		// Compatibility hack.
415
		p.From.Sym.Set(obj.AttrNoFrame, true)
416
		textstksiz = 0
417
	}
418
	if textstksiz%8 != 0 {
419
		c.ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
420
	}
421
	if p.From.Sym.NoFrame() {
422
		if textstksiz != 0 {
423
			c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
424
		}
425
	}
426

427
	c.cursym.Func.Args = p.To.Val.(int32)
428
	c.cursym.Func.Locals = int32(textstksiz)
429

430
	/*
431
	 * find leaf subroutines
432
	 * expand RET
433
	 * expand BECOME pseudo
434
	 */
435

436
	var q *obj.Prog
437
	var q1 *obj.Prog
438
	for p := c.cursym.Func.Text; p != nil; p = p.Link {
439
		switch p.As {
440
		/* too hard, just leave alone */
441
		case obj.ATEXT:
442
			q = p
443

444
			p.Mark |= LABEL | LEAF | SYNC
445
			if p.Link != nil {
446
				p.Link.Mark |= LABEL
447
			}
448

449
		case ANOR:
450
			q = p
451
			if p.To.Type == obj.TYPE_REG {
452
				if p.To.Reg == REGZERO {
453
					p.Mark |= LABEL | SYNC
454
				}
455
			}
456

457
		case ALWAR,
458
			ALBAR,
459
			ASTBCCC,
460
			ASTWCCC,
461
			AECIWX,
462
			AECOWX,
463
			AEIEIO,
464
			AICBI,
465
			AISYNC,
466
			ATLBIE,
467
			ATLBIEL,
468
			ASLBIA,
469
			ASLBIE,
470
			ASLBMFEE,
471
			ASLBMFEV,
472
			ASLBMTE,
473
			ADCBF,
474
			ADCBI,
475
			ADCBST,
476
			ADCBT,
477
			ADCBTST,
478
			ADCBZ,
479
			ASYNC,
480
			ATLBSYNC,
481
			APTESYNC,
482
			ALWSYNC,
483
			ATW,
484
			AWORD,
485
			ARFI,
486
			ARFCI,
487
			ARFID,
488
			AHRFID:
489
			q = p
490
			p.Mark |= LABEL | SYNC
491
			continue
492

493
		case AMOVW, AMOVWZ, AMOVD:
494
			q = p
495
			if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
496
				p.Mark |= LABEL | SYNC
497
			}
498
			continue
499

500
		case AFABS,
501
			AFABSCC,
502
			AFADD,
503
			AFADDCC,
504
			AFCTIW,
505
			AFCTIWCC,
506
			AFCTIWZ,
507
			AFCTIWZCC,
508
			AFDIV,
509
			AFDIVCC,
510
			AFMADD,
511
			AFMADDCC,
512
			AFMOVD,
513
			AFMOVDU,
514
			/* case AFMOVDS: */
515
			AFMOVS,
516
			AFMOVSU,
517

518
			/* case AFMOVSD: */
519
			AFMSUB,
520
			AFMSUBCC,
521
			AFMUL,
522
			AFMULCC,
523
			AFNABS,
524
			AFNABSCC,
525
			AFNEG,
526
			AFNEGCC,
527
			AFNMADD,
528
			AFNMADDCC,
529
			AFNMSUB,
530
			AFNMSUBCC,
531
			AFRSP,
532
			AFRSPCC,
533
			AFSUB,
534
			AFSUBCC:
535
			q = p
536

537
			p.Mark |= FLOAT
538
			continue
539

540
		case ABL,
541
			ABCL,
542
			obj.ADUFFZERO,
543
			obj.ADUFFCOPY:
544
			c.cursym.Func.Text.Mark &^= LEAF
545
			fallthrough
546

547
		case ABC,
548
			ABEQ,
549
			ABGE,
550
			ABGT,
551
			ABLE,
552
			ABLT,
553
			ABNE,
554
			ABR,
555
			ABVC,
556
			ABVS:
557
			p.Mark |= BRANCH
558
			q = p
559
			q1 = p.To.Target()
560
			if q1 != nil {
561
				// NOPs are not removed due to #40689.
562

563
				if q1.Mark&LEAF == 0 {
564
					q1.Mark |= LABEL
565
				}
566
			} else {
567
				p.Mark |= LABEL
568
			}
569
			q1 = p.Link
570
			if q1 != nil {
571
				q1.Mark |= LABEL
572
			}
573
			continue
574

575
		case AFCMPO, AFCMPU:
576
			q = p
577
			p.Mark |= FCMP | FLOAT
578
			continue
579

580
		case obj.ARET:
581
			q = p
582
			if p.Link != nil {
583
				p.Link.Mark |= LABEL
584
			}
585
			continue
586

587
		case obj.ANOP:
588
			// NOPs are not removed due to
589
			// #40689
590
			continue
591

592
		default:
593
			q = p
594
			continue
595
		}
596
	}
597

598
	autosize := int32(0)
599
	var p1 *obj.Prog
600
	var p2 *obj.Prog
601
	for p := c.cursym.Func.Text; p != nil; p = p.Link {
602
		o := p.As
603
		switch o {
604
		case obj.ATEXT:
605
			autosize = int32(textstksiz)
606

607
			if p.Mark&LEAF != 0 && autosize == 0 {
608
				// A leaf function with no locals has no frame.
609
				p.From.Sym.Set(obj.AttrNoFrame, true)
610
			}
611

612
			if !p.From.Sym.NoFrame() {
613
				// If there is a stack frame at all, it includes
614
				// space to save the LR.
615
				autosize += int32(c.ctxt.FixedFrameSize())
616
			}
617

618
			if p.Mark&LEAF != 0 && autosize < objabi.StackSmall {
619
				// A leaf function with a small stack can be marked
620
				// NOSPLIT, avoiding a stack check.
621
				p.From.Sym.Set(obj.AttrNoSplit, true)
622
			}
623

624
			p.To.Offset = int64(autosize)
625

626
			q = p
627

628
			if c.ctxt.Flag_shared && c.cursym.Name != "runtime.duffzero" && c.cursym.Name != "runtime.duffcopy" {
629
				// When compiling Go into PIC, all functions must start
630
				// with instructions to load the TOC pointer into r2:
631
				//
632
				//	addis r2, r12, .TOC.-func@ha
633
				//	addi r2, r2, .TOC.-func@l+4
634
				//
635
				// We could probably skip this prologue in some situations
636
				// but it's a bit subtle. However, it is both safe and
637
				// necessary to leave the prologue off duffzero and
638
				// duffcopy as we rely on being able to jump to a specific
639
				// instruction offset for them.
640
				//
641
				// These are AWORDS because there is no (afaict) way to
642
				// generate the addis instruction except as part of the
643
				// load of a large constant, and in that case there is no
644
				// way to use r12 as the source.
645
				//
646
				// Note that the same condition is tested in
647
				// putelfsym in cmd/link/internal/ld/symtab.go
648
				// where we set the st_other field to indicate
649
				// the presence of these instructions.
650
				q = obj.Appendp(q, c.newprog)
651
				q.As = AWORD
652
				q.Pos = p.Pos
653
				q.From.Type = obj.TYPE_CONST
654
				q.From.Offset = 0x3c4c0000
655
				q = obj.Appendp(q, c.newprog)
656
				q.As = AWORD
657
				q.Pos = p.Pos
658
				q.From.Type = obj.TYPE_CONST
659
				q.From.Offset = 0x38420000
660
				rel := obj.Addrel(c.cursym)
661
				rel.Off = 0
662
				rel.Siz = 8
663
				rel.Sym = c.ctxt.Lookup(".TOC.")
664
				rel.Type = objabi.R_ADDRPOWER_PCREL
665
			}
666

667
			if !c.cursym.Func.Text.From.Sym.NoSplit() {
668
				q = c.stacksplit(q, autosize) // emit split check
669
			}
670

671
			// Special handling of the racecall thunk. Assume that its asm code will
672
			// save the link register and update the stack, since that code is
673
			// called directly from C/C++ and can't clobber REGTMP (R31).
674
			if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
675
				// Save the link register and update the SP.  MOVDU is used unless
676
				// the frame size is too large.  The link register must be saved
677
				// even for non-empty leaf functions so that traceback works.
678
				if autosize >= -BIG && autosize <= BIG {
679
					// Use MOVDU to adjust R1 when saving R31, if autosize is small.
680
					q = obj.Appendp(q, c.newprog)
681
					q.As = AMOVD
682
					q.Pos = p.Pos
683
					q.From.Type = obj.TYPE_REG
684
					q.From.Reg = REG_LR
685
					q.To.Type = obj.TYPE_REG
686
					q.To.Reg = REGTMP
687

688
					q = obj.Appendp(q, c.newprog)
689
					q.As = AMOVDU
690
					q.Pos = p.Pos
691
					q.From.Type = obj.TYPE_REG
692
					q.From.Reg = REGTMP
693
					q.To.Type = obj.TYPE_MEM
694
					q.To.Offset = int64(-autosize)
695
					q.To.Reg = REGSP
696
					q.Spadj = autosize
697
				} else {
698
					// Frame size is too large for a MOVDU instruction.
699
					// Store link register before decrementing SP, so if a signal comes
700
					// during the execution of the function prologue, the traceback
701
					// code will not see a half-updated stack frame.
702
					// This sequence is not async preemptible, as if we open a frame
703
					// at the current SP, it will clobber the saved LR.
704
					q = obj.Appendp(q, c.newprog)
705
					q.As = AMOVD
706
					q.Pos = p.Pos
707
					q.From.Type = obj.TYPE_REG
708
					q.From.Reg = REG_LR
709
					q.To.Type = obj.TYPE_REG
710
					q.To.Reg = REG_R29 // REGTMP may be used to synthesize large offset in the next instruction
711

712
					q = c.ctxt.StartUnsafePoint(q, c.newprog)
713

714
					q = obj.Appendp(q, c.newprog)
715
					q.As = AMOVD
716
					q.Pos = p.Pos
717
					q.From.Type = obj.TYPE_REG
718
					q.From.Reg = REG_R29
719
					q.To.Type = obj.TYPE_MEM
720
					q.To.Offset = int64(-autosize)
721
					q.To.Reg = REGSP
722

723
					q = obj.Appendp(q, c.newprog)
724
					q.As = AADD
725
					q.Pos = p.Pos
726
					q.From.Type = obj.TYPE_CONST
727
					q.From.Offset = int64(-autosize)
728
					q.To.Type = obj.TYPE_REG
729
					q.To.Reg = REGSP
730
					q.Spadj = +autosize
731

732
					q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
733

734
				}
735
			} else if c.cursym.Func.Text.Mark&LEAF == 0 {
736
				// A very few functions that do not return to their caller
737
				// (e.g. gogo) are not identified as leaves but still have
738
				// no frame.
739
				c.cursym.Func.Text.Mark |= LEAF
740
			}
741

742
			if c.cursym.Func.Text.Mark&LEAF != 0 {
743
				c.cursym.Set(obj.AttrLeaf, true)
744
				break
745
			}
746

747
			if c.ctxt.Flag_shared {
748
				q = obj.Appendp(q, c.newprog)
749
				q.As = AMOVD
750
				q.Pos = p.Pos
751
				q.From.Type = obj.TYPE_REG
752
				q.From.Reg = REG_R2
753
				q.To.Type = obj.TYPE_MEM
754
				q.To.Reg = REGSP
755
				q.To.Offset = 24
756
			}
757

758
			if c.cursym.Func.Text.From.Sym.Wrapper() {
759
				// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
760
				//
761
				//	MOVD g_panic(g), R3
762
				//	CMP R0, R3
763
				//	BEQ end
764
				//	MOVD panic_argp(R3), R4
765
				//	ADD $(autosize+8), R1, R5
766
				//	CMP R4, R5
767
				//	BNE end
768
				//	ADD $8, R1, R6
769
				//	MOVD R6, panic_argp(R3)
770
				// end:
771
				//	NOP
772
				//
773
				// The NOP is needed to give the jumps somewhere to land.
774
				// It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes.
775

776
				q = obj.Appendp(q, c.newprog)
777

778
				q.As = AMOVD
779
				q.From.Type = obj.TYPE_MEM
780
				q.From.Reg = REGG
781
				q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
782
				q.To.Type = obj.TYPE_REG
783
				q.To.Reg = REG_R3
784

785
				q = obj.Appendp(q, c.newprog)
786
				q.As = ACMP
787
				q.From.Type = obj.TYPE_REG
788
				q.From.Reg = REG_R0
789
				q.To.Type = obj.TYPE_REG
790
				q.To.Reg = REG_R3
791

792
				q = obj.Appendp(q, c.newprog)
793
				q.As = ABEQ
794
				q.To.Type = obj.TYPE_BRANCH
795
				p1 = q
796

797
				q = obj.Appendp(q, c.newprog)
798
				q.As = AMOVD
799
				q.From.Type = obj.TYPE_MEM
800
				q.From.Reg = REG_R3
801
				q.From.Offset = 0 // Panic.argp
802
				q.To.Type = obj.TYPE_REG
803
				q.To.Reg = REG_R4
804

805
				q = obj.Appendp(q, c.newprog)
806
				q.As = AADD
807
				q.From.Type = obj.TYPE_CONST
808
				q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
809
				q.Reg = REGSP
810
				q.To.Type = obj.TYPE_REG
811
				q.To.Reg = REG_R5
812

813
				q = obj.Appendp(q, c.newprog)
814
				q.As = ACMP
815
				q.From.Type = obj.TYPE_REG
816
				q.From.Reg = REG_R4
817
				q.To.Type = obj.TYPE_REG
818
				q.To.Reg = REG_R5
819

820
				q = obj.Appendp(q, c.newprog)
821
				q.As = ABNE
822
				q.To.Type = obj.TYPE_BRANCH
823
				p2 = q
824

825
				q = obj.Appendp(q, c.newprog)
826
				q.As = AADD
827
				q.From.Type = obj.TYPE_CONST
828
				q.From.Offset = c.ctxt.FixedFrameSize()
829
				q.Reg = REGSP
830
				q.To.Type = obj.TYPE_REG
831
				q.To.Reg = REG_R6
832

833
				q = obj.Appendp(q, c.newprog)
834
				q.As = AMOVD
835
				q.From.Type = obj.TYPE_REG
836
				q.From.Reg = REG_R6
837
				q.To.Type = obj.TYPE_MEM
838
				q.To.Reg = REG_R3
839
				q.To.Offset = 0 // Panic.argp
840

841
				q = obj.Appendp(q, c.newprog)
842

843
				q.As = obj.ANOP
844
				p1.To.SetTarget(q)
845
				p2.To.SetTarget(q)
846
			}
847

848
		case obj.ARET:
849
			if p.From.Type == obj.TYPE_CONST {
850
				c.ctxt.Diag("using BECOME (%v) is not supported!", p)
851
				break
852
			}
853

854
			retTarget := p.To.Sym
855

856
			if c.cursym.Func.Text.Mark&LEAF != 0 {
857
				if autosize == 0 || c.cursym.Name == "runtime.racecallbackthunk" {
858
					p.As = ABR
859
					p.From = obj.Addr{}
860
					if retTarget == nil {
861
						p.To.Type = obj.TYPE_REG
862
						p.To.Reg = REG_LR
863
					} else {
864
						p.To.Type = obj.TYPE_BRANCH
865
						p.To.Sym = retTarget
866
					}
867
					p.Mark |= BRANCH
868
					break
869
				}
870

871
				p.As = AADD
872
				p.From.Type = obj.TYPE_CONST
873
				p.From.Offset = int64(autosize)
874
				p.To.Type = obj.TYPE_REG
875
				p.To.Reg = REGSP
876
				p.Spadj = -autosize
877

878
				q = c.newprog()
879
				q.As = ABR
880
				q.Pos = p.Pos
881
				q.To.Type = obj.TYPE_REG
882
				q.To.Reg = REG_LR
883
				q.Mark |= BRANCH
884
				q.Spadj = +autosize
885

886
				q.Link = p.Link
887
				p.Link = q
888
				break
889
			}
890

891
			p.As = AMOVD
892
			p.From.Type = obj.TYPE_MEM
893
			p.From.Offset = 0
894
			p.From.Reg = REGSP
895
			p.To.Type = obj.TYPE_REG
896
			p.To.Reg = REGTMP
897

898
			q = c.newprog()
899
			q.As = AMOVD
900
			q.Pos = p.Pos
901
			q.From.Type = obj.TYPE_REG
902
			q.From.Reg = REGTMP
903
			q.To.Type = obj.TYPE_REG
904
			q.To.Reg = REG_LR
905

906
			q.Link = p.Link
907
			p.Link = q
908
			p = q
909

910
			if false {
911
				// Debug bad returns
912
				q = c.newprog()
913

914
				q.As = AMOVD
915
				q.Pos = p.Pos
916
				q.From.Type = obj.TYPE_MEM
917
				q.From.Offset = 0
918
				q.From.Reg = REGTMP
919
				q.To.Type = obj.TYPE_REG
920
				q.To.Reg = REGTMP
921

922
				q.Link = p.Link
923
				p.Link = q
924
				p = q
925
			}
926
			prev := p
927
			if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
928
				q = c.newprog()
929
				q.As = AADD
930
				q.Pos = p.Pos
931
				q.From.Type = obj.TYPE_CONST
932
				q.From.Offset = int64(autosize)
933
				q.To.Type = obj.TYPE_REG
934
				q.To.Reg = REGSP
935
				q.Spadj = -autosize
936

937
				q.Link = p.Link
938
				prev.Link = q
939
				prev = q
940
			}
941

942
			q1 = c.newprog()
943
			q1.As = ABR
944
			q1.Pos = p.Pos
945
			if retTarget == nil {
946
				q1.To.Type = obj.TYPE_REG
947
				q1.To.Reg = REG_LR
948
			} else {
949
				q1.To.Type = obj.TYPE_BRANCH
950
				q1.To.Sym = retTarget
951
			}
952
			q1.Mark |= BRANCH
953
			q1.Spadj = +autosize
954

955
			q1.Link = q.Link
956
			prev.Link = q1
957
		case AADD:
958
			if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
959
				p.Spadj = int32(-p.From.Offset)
960
			}
961
		case AMOVDU:
962
			if p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
963
				p.Spadj = int32(-p.To.Offset)
964
			}
965
			if p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP {
966
				p.Spadj = int32(-p.From.Offset)
967
			}
968
		case obj.AGETCALLERPC:
969
			if cursym.Leaf() {
970
				/* MOVD LR, Rd */
971
				p.As = AMOVD
972
				p.From.Type = obj.TYPE_REG
973
				p.From.Reg = REG_LR
974
			} else {
975
				/* MOVD (RSP), Rd */
976
				p.As = AMOVD
977
				p.From.Type = obj.TYPE_MEM
978
				p.From.Reg = REGSP
979
			}
980
		}
981
	}
982
}
983

984
/*
985
// instruction scheduling
986
	if(debug['Q'] == 0)
987
		return;
988

989
	curtext = nil;
990
	q = nil;	// p - 1
991
	q1 = firstp;	// top of block
992
	o = 0;		// count of instructions
993
	for(p = firstp; p != nil; p = p1) {
994
		p1 = p->link;
995
		o++;
996
		if(p->mark & NOSCHED){
997
			if(q1 != p){
998
				sched(q1, q);
999
			}
1000
			for(; p != nil; p = p->link){
1001
				if(!(p->mark & NOSCHED))
1002
					break;
1003
				q = p;
1004
			}
1005
			p1 = p;
1006
			q1 = p;
1007
			o = 0;
1008
			continue;
1009
		}
1010
		if(p->mark & (LABEL|SYNC)) {
1011
			if(q1 != p)
1012
				sched(q1, q);
1013
			q1 = p;
1014
			o = 1;
1015
		}
1016
		if(p->mark & (BRANCH|SYNC)) {
1017
			sched(q1, p);
1018
			q1 = p1;
1019
			o = 0;
1020
		}
1021
		if(o >= NSCHED) {
1022
			sched(q1, p);
1023
			q1 = p1;
1024
			o = 0;
1025
		}
1026
		q = p;
1027
	}
1028
*/
1029
func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
1030
	p0 := p // save entry point, but skipping the two instructions setting R2 in shared mode
1031

1032
	// MOVD	g_stackguard(g), R3
1033
	p = obj.Appendp(p, c.newprog)
1034

1035
	p.As = AMOVD
1036
	p.From.Type = obj.TYPE_MEM
1037
	p.From.Reg = REGG
1038
	p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
1039
	if c.cursym.CFunc() {
1040
		p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
1041
	}
1042
	p.To.Type = obj.TYPE_REG
1043
	p.To.Reg = REG_R3
1044

1045
	// Mark the stack bound check and morestack call async nonpreemptible.
1046
	// If we get preempted here, when resumed the preemption request is
1047
	// cleared, but we'll still call morestack, which will double the stack
1048
	// unnecessarily. See issue #35470.
1049
	p = c.ctxt.StartUnsafePoint(p, c.newprog)
1050

1051
	var q *obj.Prog
1052
	if framesize <= objabi.StackSmall {
1053
		// small stack: SP < stackguard
1054
		//	CMP	stackguard, SP
1055
		p = obj.Appendp(p, c.newprog)
1056

1057
		p.As = ACMPU
1058
		p.From.Type = obj.TYPE_REG
1059
		p.From.Reg = REG_R3
1060
		p.To.Type = obj.TYPE_REG
1061
		p.To.Reg = REGSP
1062
	} else if framesize <= objabi.StackBig {
1063
		// large stack: SP-framesize < stackguard-StackSmall
1064
		//	ADD $-(framesize-StackSmall), SP, R4
1065
		//	CMP stackguard, R4
1066
		p = obj.Appendp(p, c.newprog)
1067

1068
		p.As = AADD
1069
		p.From.Type = obj.TYPE_CONST
1070
		p.From.Offset = -(int64(framesize) - objabi.StackSmall)
1071
		p.Reg = REGSP
1072
		p.To.Type = obj.TYPE_REG
1073
		p.To.Reg = REG_R4
1074

1075
		p = obj.Appendp(p, c.newprog)
1076
		p.As = ACMPU
1077
		p.From.Type = obj.TYPE_REG
1078
		p.From.Reg = REG_R3
1079
		p.To.Type = obj.TYPE_REG
1080
		p.To.Reg = REG_R4
1081
	} else {
1082
		// Such a large stack we need to protect against wraparound.
1083
		// If SP is close to zero:
1084
		//	SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
1085
		// The +StackGuard on both sides is required to keep the left side positive:
1086
		// SP is allowed to be slightly below stackguard. See stack.h.
1087
		//
1088
		// Preemption sets stackguard to StackPreempt, a very large value.
1089
		// That breaks the math above, so we have to check for that explicitly.
1090
		//	// stackguard is R3
1091
		//	CMP	R3, $StackPreempt
1092
		//	BEQ	label-of-call-to-morestack
1093
		//	ADD	$StackGuard, SP, R4
1094
		//	SUB	R3, R4
1095
		//	MOVD	$(framesize+(StackGuard-StackSmall)), R31
1096
		//	CMPU	R31, R4
1097
		p = obj.Appendp(p, c.newprog)
1098

1099
		p.As = ACMP
1100
		p.From.Type = obj.TYPE_REG
1101
		p.From.Reg = REG_R3
1102
		p.To.Type = obj.TYPE_CONST
1103
		p.To.Offset = objabi.StackPreempt
1104

1105
		p = obj.Appendp(p, c.newprog)
1106
		q = p
1107
		p.As = ABEQ
1108
		p.To.Type = obj.TYPE_BRANCH
1109

1110
		p = obj.Appendp(p, c.newprog)
1111
		p.As = AADD
1112
		p.From.Type = obj.TYPE_CONST
1113
		p.From.Offset = int64(objabi.StackGuard)
1114
		p.Reg = REGSP
1115
		p.To.Type = obj.TYPE_REG
1116
		p.To.Reg = REG_R4
1117

1118
		p = obj.Appendp(p, c.newprog)
1119
		p.As = ASUB
1120
		p.From.Type = obj.TYPE_REG
1121
		p.From.Reg = REG_R3
1122
		p.To.Type = obj.TYPE_REG
1123
		p.To.Reg = REG_R4
1124

1125
		p = obj.Appendp(p, c.newprog)
1126
		p.As = AMOVD
1127
		p.From.Type = obj.TYPE_CONST
1128
		p.From.Offset = int64(framesize) + int64(objabi.StackGuard) - objabi.StackSmall
1129
		p.To.Type = obj.TYPE_REG
1130
		p.To.Reg = REGTMP
1131

1132
		p = obj.Appendp(p, c.newprog)
1133
		p.As = ACMPU
1134
		p.From.Type = obj.TYPE_REG
1135
		p.From.Reg = REGTMP
1136
		p.To.Type = obj.TYPE_REG
1137
		p.To.Reg = REG_R4
1138
	}
1139

1140
	// q1: BLT	done
1141
	p = obj.Appendp(p, c.newprog)
1142
	q1 := p
1143

1144
	p.As = ABLT
1145
	p.To.Type = obj.TYPE_BRANCH
1146

1147
	// MOVD	LR, R5
1148
	p = obj.Appendp(p, c.newprog)
1149

1150
	p.As = AMOVD
1151
	p.From.Type = obj.TYPE_REG
1152
	p.From.Reg = REG_LR
1153
	p.To.Type = obj.TYPE_REG
1154
	p.To.Reg = REG_R5
1155
	if q != nil {
1156
		q.To.SetTarget(p)
1157
	}
1158

1159
	p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
1160

1161
	var morestacksym *obj.LSym
1162
	if c.cursym.CFunc() {
1163
		morestacksym = c.ctxt.Lookup("runtime.morestackc")
1164
	} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
1165
		morestacksym = c.ctxt.Lookup("runtime.morestack_noctxt")
1166
	} else {
1167
		morestacksym = c.ctxt.Lookup("runtime.morestack")
1168
	}
1169

1170
	if c.ctxt.Flag_shared {
1171
		// In PPC64 PIC code, R2 is used as TOC pointer derived from R12
1172
		// which is the address of function entry point when entering
1173
		// the function. We need to preserve R2 across call to morestack.
1174
		// Fortunately, in shared mode, 8(SP) and 16(SP) are reserved in
1175
		// the caller's frame, but not used (0(SP) is caller's saved LR,
1176
		// 24(SP) is caller's saved R2). Use 8(SP) to save this function's R2.
1177

1178
		// MOVD R12, 8(SP)
1179
		p = obj.Appendp(p, c.newprog)
1180
		p.As = AMOVD
1181
		p.From.Type = obj.TYPE_REG
1182
		p.From.Reg = REG_R2
1183
		p.To.Type = obj.TYPE_MEM
1184
		p.To.Reg = REGSP
1185
		p.To.Offset = 8
1186
	}
1187

1188
	if c.ctxt.Flag_dynlink {
1189
		// Avoid calling morestack via a PLT when dynamically linking. The
1190
		// PLT stubs generated by the system linker on ppc64le when "std r2,
1191
		// 24(r1)" to save the TOC pointer in their callers stack
1192
		// frame. Unfortunately (and necessarily) morestack is called before
1193
		// the function that calls it sets up its frame and so the PLT ends
1194
		// up smashing the saved TOC pointer for its caller's caller.
1195
		//
1196
		// According to the ABI documentation there is a mechanism to avoid
1197
		// the TOC save that the PLT stub does (put a R_PPC64_TOCSAVE
1198
		// relocation on the nop after the call to morestack) but at the time
1199
		// of writing it is not supported at all by gold and my attempt to
1200
		// use it with ld.bfd caused an internal linker error. So this hack
1201
		// seems preferable.
1202

1203
		// MOVD $runtime.morestack(SB), R12
1204
		p = obj.Appendp(p, c.newprog)
1205
		p.As = AMOVD
1206
		p.From.Type = obj.TYPE_MEM
1207
		p.From.Sym = morestacksym
1208
		p.From.Name = obj.NAME_GOTREF
1209
		p.To.Type = obj.TYPE_REG
1210
		p.To.Reg = REG_R12
1211

1212
		// MOVD R12, LR
1213
		p = obj.Appendp(p, c.newprog)
1214
		p.As = AMOVD
1215
		p.From.Type = obj.TYPE_REG
1216
		p.From.Reg = REG_R12
1217
		p.To.Type = obj.TYPE_REG
1218
		p.To.Reg = REG_LR
1219

1220
		// BL LR
1221
		p = obj.Appendp(p, c.newprog)
1222
		p.As = obj.ACALL
1223
		p.To.Type = obj.TYPE_REG
1224
		p.To.Reg = REG_LR
1225
	} else {
1226
		// BL	runtime.morestack(SB)
1227
		p = obj.Appendp(p, c.newprog)
1228

1229
		p.As = ABL
1230
		p.To.Type = obj.TYPE_BRANCH
1231
		p.To.Sym = morestacksym
1232
	}
1233

1234
	if c.ctxt.Flag_shared {
1235
		// MOVD 8(SP), R2
1236
		p = obj.Appendp(p, c.newprog)
1237
		p.As = AMOVD
1238
		p.From.Type = obj.TYPE_MEM
1239
		p.From.Reg = REGSP
1240
		p.From.Offset = 8
1241
		p.To.Type = obj.TYPE_REG
1242
		p.To.Reg = REG_R2
1243
	}
1244

1245
	p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
1246

1247
	// BR	start
1248
	p = obj.Appendp(p, c.newprog)
1249
	p.As = ABR
1250
	p.To.Type = obj.TYPE_BRANCH
1251
	p.To.SetTarget(p0.Link)
1252

1253
	// placeholder for q1's jump target
1254
	p = obj.Appendp(p, c.newprog)
1255

1256
	p.As = obj.ANOP // zero-width place holder
1257
	q1.To.SetTarget(p)
1258

1259
	return p
1260
}
1261

1262
var Linkppc64 = obj.LinkArch{
1263
	Arch:           sys.ArchPPC64,
1264
	Init:           buildop,
1265
	Preprocess:     preprocess,
1266
	Assemble:       span9,
1267
	Progedit:       progedit,
1268
	DWARFRegisters: PPC64DWARFRegisters,
1269
}
1270

1271
var Linkppc64le = obj.LinkArch{
1272
	Arch:           sys.ArchPPC64LE,
1273
	Init:           buildop,
1274
	Preprocess:     preprocess,
1275
	Assemble:       span9,
1276
	Progedit:       progedit,
1277
	DWARFRegisters: PPC64DWARFRegisters,
1278
}
1279

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.