podman

Форк
0
735 строк · 18.6 Кб
1
// Based on cmd/internal/obj/ppc64/obj9.go.
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 s390x
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
	"math"
37
)
38

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

43
	c := ctxtz{ctxt: ctxt, newprog: newprog}
44

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

53
	// Rewrite float constants to values stored in memory unless they are +0.
54
	switch p.As {
55
	case AFMOVS:
56
		if p.From.Type == obj.TYPE_FCONST {
57
			f32 := float32(p.From.Val.(float64))
58
			if math.Float32bits(f32) == 0 { // +0
59
				break
60
			}
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
			if math.Float64bits(f64) == 0 { // +0
71
				break
72
			}
73
			p.From.Type = obj.TYPE_MEM
74
			p.From.Sym = ctxt.Float64Sym(f64)
75
			p.From.Name = obj.NAME_EXTERN
76
			p.From.Offset = 0
77
		}
78

79
		// put constants not loadable by LOAD IMMEDIATE into memory
80
	case AMOVD:
81
		if p.From.Type == obj.TYPE_CONST {
82
			val := p.From.Offset
83
			if int64(int32(val)) != val &&
84
				int64(uint32(val)) != val &&
85
				int64(uint64(val)&(0xffffffff<<32)) != val {
86
				p.From.Type = obj.TYPE_MEM
87
				p.From.Sym = ctxt.Int64Sym(p.From.Offset)
88
				p.From.Name = obj.NAME_EXTERN
89
				p.From.Offset = 0
90
			}
91
		}
92
	}
93

94
	// Rewrite SUB constants into ADD.
95
	switch p.As {
96
	case ASUBC:
97
		if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
98
			p.From.Offset = -p.From.Offset
99
			p.As = AADDC
100
		}
101

102
	case ASUB:
103
		if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
104
			p.From.Offset = -p.From.Offset
105
			p.As = AADD
106
		}
107
	}
108

109
	if c.ctxt.Flag_dynlink {
110
		c.rewriteToUseGot(p)
111
	}
112
}
113

114
// Rewrite p, if necessary, to access global data via the global offset table.
115
func (c *ctxtz) rewriteToUseGot(p *obj.Prog) {
116
	// At the moment EXRL instructions are not emitted by the compiler and only reference local symbols in
117
	// assembly code.
118
	if p.As == AEXRL {
119
		return
120
	}
121

122
	// We only care about global data: NAME_EXTERN means a global
123
	// symbol in the Go sense, and p.Sym.Local is true for a few
124
	// internally defined symbols.
125
	// Rewrites must not clobber flags and therefore cannot use the
126
	// ADD instruction.
127
	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
128
		// MOVD $sym, Rx becomes MOVD sym@GOT, Rx
129
		// MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx or REGTMP2; MOVD $<off>(Rx or REGTMP2), Rx
130
		if p.To.Type != obj.TYPE_REG || p.As != AMOVD {
131
			c.ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
132
		}
133
		p.From.Type = obj.TYPE_MEM
134
		p.From.Name = obj.NAME_GOTREF
135
		q := p
136
		if p.From.Offset != 0 {
137
			target := p.To.Reg
138
			if target == REG_R0 {
139
				// Cannot use R0 as input to address calculation.
140
				// REGTMP might be used by the assembler.
141
				p.To.Reg = REGTMP2
142
			}
143
			q = obj.Appendp(q, c.newprog)
144
			q.As = AMOVD
145
			q.From.Type = obj.TYPE_ADDR
146
			q.From.Offset = p.From.Offset
147
			q.From.Reg = p.To.Reg
148
			q.To.Type = obj.TYPE_REG
149
			q.To.Reg = target
150
			p.From.Offset = 0
151
		}
152
	}
153
	if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
154
		c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
155
	}
156
	var source *obj.Addr
157
	// MOVD sym, Ry becomes MOVD sym@GOT, REGTMP2; MOVD (REGTMP2), Ry
158
	// MOVD Ry, sym becomes MOVD sym@GOT, REGTMP2; MOVD Ry, (REGTMP2)
159
	// An addition may be inserted between the two MOVs if there is an offset.
160
	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
161
		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
162
			c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
163
		}
164
		source = &p.From
165
	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
166
		source = &p.To
167
	} else {
168
		return
169
	}
170
	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
171
		return
172
	}
173
	if source.Sym.Type == objabi.STLSBSS {
174
		return
175
	}
176
	if source.Type != obj.TYPE_MEM {
177
		c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
178
	}
179
	p1 := obj.Appendp(p, c.newprog)
180
	p2 := obj.Appendp(p1, c.newprog)
181

182
	p1.As = AMOVD
183
	p1.From.Type = obj.TYPE_MEM
184
	p1.From.Sym = source.Sym
185
	p1.From.Name = obj.NAME_GOTREF
186
	p1.To.Type = obj.TYPE_REG
187
	p1.To.Reg = REGTMP2
188

189
	p2.As = p.As
190
	p2.From = p.From
191
	p2.To = p.To
192
	if p.From.Name == obj.NAME_EXTERN {
193
		p2.From.Reg = REGTMP2
194
		p2.From.Name = obj.NAME_NONE
195
		p2.From.Sym = nil
196
	} else if p.To.Name == obj.NAME_EXTERN {
197
		p2.To.Reg = REGTMP2
198
		p2.To.Name = obj.NAME_NONE
199
		p2.To.Sym = nil
200
	} else {
201
		return
202
	}
203
	obj.Nopout(p)
204
}
205

206
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
207
	// TODO(minux): add morestack short-cuts with small fixed frame-size.
208
	if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
209
		return
210
	}
211

212
	c := ctxtz{ctxt: ctxt, cursym: cursym, newprog: newprog}
213

214
	p := c.cursym.Func.Text
215
	textstksiz := p.To.Offset
216
	if textstksiz == -8 {
217
		// Compatibility hack.
218
		p.From.Sym.Set(obj.AttrNoFrame, true)
219
		textstksiz = 0
220
	}
221
	if textstksiz%8 != 0 {
222
		c.ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
223
	}
224
	if p.From.Sym.NoFrame() {
225
		if textstksiz != 0 {
226
			c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
227
		}
228
	}
229

230
	c.cursym.Func.Args = p.To.Val.(int32)
231
	c.cursym.Func.Locals = int32(textstksiz)
232

233
	/*
234
	 * find leaf subroutines
235
	 * strip NOPs
236
	 * expand RET
237
	 */
238

239
	var q *obj.Prog
240
	for p := c.cursym.Func.Text; p != nil; p = p.Link {
241
		switch p.As {
242
		case obj.ATEXT:
243
			q = p
244
			p.Mark |= LEAF
245

246
		case ABL, ABCL:
247
			q = p
248
			c.cursym.Func.Text.Mark &^= LEAF
249
			fallthrough
250

251
		case ABC,
252
			ABRC,
253
			ABEQ,
254
			ABGE,
255
			ABGT,
256
			ABLE,
257
			ABLT,
258
			ABLEU,
259
			ABLTU,
260
			ABNE,
261
			ABR,
262
			ABVC,
263
			ABVS,
264
			ACRJ,
265
			ACGRJ,
266
			ACLRJ,
267
			ACLGRJ,
268
			ACIJ,
269
			ACGIJ,
270
			ACLIJ,
271
			ACLGIJ,
272
			ACMPBEQ,
273
			ACMPBGE,
274
			ACMPBGT,
275
			ACMPBLE,
276
			ACMPBLT,
277
			ACMPBNE,
278
			ACMPUBEQ,
279
			ACMPUBGE,
280
			ACMPUBGT,
281
			ACMPUBLE,
282
			ACMPUBLT,
283
			ACMPUBNE:
284
			q = p
285
			p.Mark |= BRANCH
286

287
		default:
288
			q = p
289
		}
290
	}
291

292
	autosize := int32(0)
293
	var pLast *obj.Prog
294
	var pPre *obj.Prog
295
	var pPreempt *obj.Prog
296
	wasSplit := false
297
	for p := c.cursym.Func.Text; p != nil; p = p.Link {
298
		pLast = p
299
		switch p.As {
300
		case obj.ATEXT:
301
			autosize = int32(textstksiz)
302

303
			if p.Mark&LEAF != 0 && autosize == 0 {
304
				// A leaf function with no locals has no frame.
305
				p.From.Sym.Set(obj.AttrNoFrame, true)
306
			}
307

308
			if !p.From.Sym.NoFrame() {
309
				// If there is a stack frame at all, it includes
310
				// space to save the LR.
311
				autosize += int32(c.ctxt.FixedFrameSize())
312
			}
313

314
			if p.Mark&LEAF != 0 && autosize < objabi.StackSmall {
315
				// A leaf function with a small stack can be marked
316
				// NOSPLIT, avoiding a stack check.
317
				p.From.Sym.Set(obj.AttrNoSplit, true)
318
			}
319

320
			p.To.Offset = int64(autosize)
321

322
			q := p
323

324
			if !p.From.Sym.NoSplit() {
325
				p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check
326
				pPre = p
327
				p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
328
				wasSplit = true //need post part of split
329
			}
330

331
			if autosize != 0 {
332
				// Make sure to save link register for non-empty frame, even if
333
				// it is a leaf function, so that traceback works.
334
				// Store link register before decrementing SP, so if a signal comes
335
				// during the execution of the function prologue, the traceback
336
				// code will not see a half-updated stack frame.
337
				// This sequence is not async preemptible, as if we open a frame
338
				// at the current SP, it will clobber the saved LR.
339
				q = c.ctxt.StartUnsafePoint(p, c.newprog)
340

341
				q = obj.Appendp(q, c.newprog)
342
				q.As = AMOVD
343
				q.From.Type = obj.TYPE_REG
344
				q.From.Reg = REG_LR
345
				q.To.Type = obj.TYPE_MEM
346
				q.To.Reg = REGSP
347
				q.To.Offset = int64(-autosize)
348

349
				q = obj.Appendp(q, c.newprog)
350
				q.As = AMOVD
351
				q.From.Type = obj.TYPE_ADDR
352
				q.From.Offset = int64(-autosize)
353
				q.From.Reg = REGSP // not actually needed - REGSP is assumed if no reg is provided
354
				q.To.Type = obj.TYPE_REG
355
				q.To.Reg = REGSP
356
				q.Spadj = autosize
357

358
				q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
359
			} else if c.cursym.Func.Text.Mark&LEAF == 0 {
360
				// A very few functions that do not return to their caller
361
				// (e.g. gogo) are not identified as leaves but still have
362
				// no frame.
363
				c.cursym.Func.Text.Mark |= LEAF
364
			}
365

366
			if c.cursym.Func.Text.Mark&LEAF != 0 {
367
				c.cursym.Set(obj.AttrLeaf, true)
368
				break
369
			}
370

371
			if c.cursym.Func.Text.From.Sym.Wrapper() {
372
				// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
373
				//
374
				//	MOVD g_panic(g), R3
375
				//	CMP R3, $0
376
				//	BEQ end
377
				//	MOVD panic_argp(R3), R4
378
				//	ADD $(autosize+8), R1, R5
379
				//	CMP R4, R5
380
				//	BNE end
381
				//	ADD $8, R1, R6
382
				//	MOVD R6, panic_argp(R3)
383
				// end:
384
				//	NOP
385
				//
386
				// The NOP is needed to give the jumps somewhere to land.
387
				// It is a liblink NOP, not a s390x NOP: it encodes to 0 instruction bytes.
388

389
				q = obj.Appendp(q, c.newprog)
390

391
				q.As = AMOVD
392
				q.From.Type = obj.TYPE_MEM
393
				q.From.Reg = REGG
394
				q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
395
				q.To.Type = obj.TYPE_REG
396
				q.To.Reg = REG_R3
397

398
				q = obj.Appendp(q, c.newprog)
399
				q.As = ACMP
400
				q.From.Type = obj.TYPE_REG
401
				q.From.Reg = REG_R3
402
				q.To.Type = obj.TYPE_CONST
403
				q.To.Offset = 0
404

405
				q = obj.Appendp(q, c.newprog)
406
				q.As = ABEQ
407
				q.To.Type = obj.TYPE_BRANCH
408
				p1 := q
409

410
				q = obj.Appendp(q, c.newprog)
411
				q.As = AMOVD
412
				q.From.Type = obj.TYPE_MEM
413
				q.From.Reg = REG_R3
414
				q.From.Offset = 0 // Panic.argp
415
				q.To.Type = obj.TYPE_REG
416
				q.To.Reg = REG_R4
417

418
				q = obj.Appendp(q, c.newprog)
419
				q.As = AADD
420
				q.From.Type = obj.TYPE_CONST
421
				q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
422
				q.Reg = REGSP
423
				q.To.Type = obj.TYPE_REG
424
				q.To.Reg = REG_R5
425

426
				q = obj.Appendp(q, c.newprog)
427
				q.As = ACMP
428
				q.From.Type = obj.TYPE_REG
429
				q.From.Reg = REG_R4
430
				q.To.Type = obj.TYPE_REG
431
				q.To.Reg = REG_R5
432

433
				q = obj.Appendp(q, c.newprog)
434
				q.As = ABNE
435
				q.To.Type = obj.TYPE_BRANCH
436
				p2 := q
437

438
				q = obj.Appendp(q, c.newprog)
439
				q.As = AADD
440
				q.From.Type = obj.TYPE_CONST
441
				q.From.Offset = c.ctxt.FixedFrameSize()
442
				q.Reg = REGSP
443
				q.To.Type = obj.TYPE_REG
444
				q.To.Reg = REG_R6
445

446
				q = obj.Appendp(q, c.newprog)
447
				q.As = AMOVD
448
				q.From.Type = obj.TYPE_REG
449
				q.From.Reg = REG_R6
450
				q.To.Type = obj.TYPE_MEM
451
				q.To.Reg = REG_R3
452
				q.To.Offset = 0 // Panic.argp
453

454
				q = obj.Appendp(q, c.newprog)
455

456
				q.As = obj.ANOP
457
				p1.To.SetTarget(q)
458
				p2.To.SetTarget(q)
459
			}
460

461
		case obj.ARET:
462
			retTarget := p.To.Sym
463

464
			if c.cursym.Func.Text.Mark&LEAF != 0 {
465
				if autosize == 0 {
466
					p.As = ABR
467
					p.From = obj.Addr{}
468
					if retTarget == nil {
469
						p.To.Type = obj.TYPE_REG
470
						p.To.Reg = REG_LR
471
					} else {
472
						p.To.Type = obj.TYPE_BRANCH
473
						p.To.Sym = retTarget
474
					}
475
					p.Mark |= BRANCH
476
					break
477
				}
478

479
				p.As = AADD
480
				p.From.Type = obj.TYPE_CONST
481
				p.From.Offset = int64(autosize)
482
				p.To.Type = obj.TYPE_REG
483
				p.To.Reg = REGSP
484
				p.Spadj = -autosize
485

486
				q = obj.Appendp(p, c.newprog)
487
				q.As = ABR
488
				q.From = obj.Addr{}
489
				q.To.Type = obj.TYPE_REG
490
				q.To.Reg = REG_LR
491
				q.Mark |= BRANCH
492
				q.Spadj = autosize
493
				break
494
			}
495

496
			p.As = AMOVD
497
			p.From.Type = obj.TYPE_MEM
498
			p.From.Reg = REGSP
499
			p.From.Offset = 0
500
			p.To.Type = obj.TYPE_REG
501
			p.To.Reg = REG_LR
502

503
			q = p
504

505
			if autosize != 0 {
506
				q = obj.Appendp(q, c.newprog)
507
				q.As = AADD
508
				q.From.Type = obj.TYPE_CONST
509
				q.From.Offset = int64(autosize)
510
				q.To.Type = obj.TYPE_REG
511
				q.To.Reg = REGSP
512
				q.Spadj = -autosize
513
			}
514

515
			q = obj.Appendp(q, c.newprog)
516
			q.As = ABR
517
			q.From = obj.Addr{}
518
			if retTarget == nil {
519
				q.To.Type = obj.TYPE_REG
520
				q.To.Reg = REG_LR
521
			} else {
522
				q.To.Type = obj.TYPE_BRANCH
523
				q.To.Sym = retTarget
524
			}
525
			q.Mark |= BRANCH
526
			q.Spadj = autosize
527

528
		case AADD:
529
			if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
530
				p.Spadj = int32(-p.From.Offset)
531
			}
532

533
		case obj.AGETCALLERPC:
534
			if cursym.Leaf() {
535
				/* MOVD LR, Rd */
536
				p.As = AMOVD
537
				p.From.Type = obj.TYPE_REG
538
				p.From.Reg = REG_LR
539
			} else {
540
				/* MOVD (RSP), Rd */
541
				p.As = AMOVD
542
				p.From.Type = obj.TYPE_MEM
543
				p.From.Reg = REGSP
544
			}
545
		}
546
	}
547
	if wasSplit {
548
		c.stacksplitPost(pLast, pPre, pPreempt, autosize) // emit post part of split check
549
	}
550
}
551

552
func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) {
553
	var q *obj.Prog
554

555
	// MOVD	g_stackguard(g), R3
556
	p = obj.Appendp(p, c.newprog)
557

558
	p.As = AMOVD
559
	p.From.Type = obj.TYPE_MEM
560
	p.From.Reg = REGG
561
	p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
562
	if c.cursym.CFunc() {
563
		p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
564
	}
565
	p.To.Type = obj.TYPE_REG
566
	p.To.Reg = REG_R3
567

568
	// Mark the stack bound check and morestack call async nonpreemptible.
569
	// If we get preempted here, when resumed the preemption request is
570
	// cleared, but we'll still call morestack, which will double the stack
571
	// unnecessarily. See issue #35470.
572
	p = c.ctxt.StartUnsafePoint(p, c.newprog)
573

574
	q = nil
575
	if framesize <= objabi.StackSmall {
576
		// small stack: SP < stackguard
577
		//	CMPUBGE	stackguard, SP, label-of-call-to-morestack
578

579
		p = obj.Appendp(p, c.newprog)
580
		//q1 = p
581
		p.From.Type = obj.TYPE_REG
582
		p.From.Reg = REG_R3
583
		p.Reg = REGSP
584
		p.As = ACMPUBGE
585
		p.To.Type = obj.TYPE_BRANCH
586

587
	} else if framesize <= objabi.StackBig {
588
		// large stack: SP-framesize < stackguard-StackSmall
589
		//	ADD $-(framesize-StackSmall), SP, R4
590
		//	CMPUBGE stackguard, R4, label-of-call-to-morestack
591
		p = obj.Appendp(p, c.newprog)
592

593
		p.As = AADD
594
		p.From.Type = obj.TYPE_CONST
595
		p.From.Offset = -(int64(framesize) - objabi.StackSmall)
596
		p.Reg = REGSP
597
		p.To.Type = obj.TYPE_REG
598
		p.To.Reg = REG_R4
599

600
		p = obj.Appendp(p, c.newprog)
601
		p.From.Type = obj.TYPE_REG
602
		p.From.Reg = REG_R3
603
		p.Reg = REG_R4
604
		p.As = ACMPUBGE
605
		p.To.Type = obj.TYPE_BRANCH
606

607
	} else {
608
		// Such a large stack we need to protect against wraparound.
609
		// If SP is close to zero:
610
		//	SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
611
		// The +StackGuard on both sides is required to keep the left side positive:
612
		// SP is allowed to be slightly below stackguard. See stack.h.
613
		//
614
		// Preemption sets stackguard to StackPreempt, a very large value.
615
		// That breaks the math above, so we have to check for that explicitly.
616
		//	// stackguard is R3
617
		//	CMP	R3, $StackPreempt
618
		//	BEQ	label-of-call-to-morestack
619
		//	ADD	$StackGuard, SP, R4
620
		//	SUB	R3, R4
621
		//	MOVD	$(framesize+(StackGuard-StackSmall)), TEMP
622
		//	CMPUBGE	TEMP, R4, label-of-call-to-morestack
623
		p = obj.Appendp(p, c.newprog)
624

625
		p.As = ACMP
626
		p.From.Type = obj.TYPE_REG
627
		p.From.Reg = REG_R3
628
		p.To.Type = obj.TYPE_CONST
629
		p.To.Offset = objabi.StackPreempt
630

631
		p = obj.Appendp(p, c.newprog)
632
		q = p
633
		p.As = ABEQ
634
		p.To.Type = obj.TYPE_BRANCH
635

636
		p = obj.Appendp(p, c.newprog)
637
		p.As = AADD
638
		p.From.Type = obj.TYPE_CONST
639
		p.From.Offset = int64(objabi.StackGuard)
640
		p.Reg = REGSP
641
		p.To.Type = obj.TYPE_REG
642
		p.To.Reg = REG_R4
643

644
		p = obj.Appendp(p, c.newprog)
645
		p.As = ASUB
646
		p.From.Type = obj.TYPE_REG
647
		p.From.Reg = REG_R3
648
		p.To.Type = obj.TYPE_REG
649
		p.To.Reg = REG_R4
650

651
		p = obj.Appendp(p, c.newprog)
652
		p.As = AMOVD
653
		p.From.Type = obj.TYPE_CONST
654
		p.From.Offset = int64(framesize) + int64(objabi.StackGuard) - objabi.StackSmall
655
		p.To.Type = obj.TYPE_REG
656
		p.To.Reg = REGTMP
657

658
		p = obj.Appendp(p, c.newprog)
659
		p.From.Type = obj.TYPE_REG
660
		p.From.Reg = REGTMP
661
		p.Reg = REG_R4
662
		p.As = ACMPUBGE
663
		p.To.Type = obj.TYPE_BRANCH
664
	}
665

666
	return p, q
667
}
668

669
func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, framesize int32) *obj.Prog {
670
	// Now we are at the end of the function, but logically
671
	// we are still in function prologue. We need to fix the
672
	// SP data and PCDATA.
673
	spfix := obj.Appendp(p, c.newprog)
674
	spfix.As = obj.ANOP
675
	spfix.Spadj = -framesize
676

677
	pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
678
	pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
679

680
	// MOVD	LR, R5
681
	p = obj.Appendp(pcdata, c.newprog)
682
	pPre.To.SetTarget(p)
683
	p.As = AMOVD
684
	p.From.Type = obj.TYPE_REG
685
	p.From.Reg = REG_LR
686
	p.To.Type = obj.TYPE_REG
687
	p.To.Reg = REG_R5
688
	if pPreempt != nil {
689
		pPreempt.To.SetTarget(p)
690
	}
691

692
	// BL	runtime.morestack(SB)
693
	p = obj.Appendp(p, c.newprog)
694

695
	p.As = ABL
696
	p.To.Type = obj.TYPE_BRANCH
697
	if c.cursym.CFunc() {
698
		p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
699
	} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
700
		p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
701
	} else {
702
		p.To.Sym = c.ctxt.Lookup("runtime.morestack")
703
	}
704

705
	p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
706

707
	// BR	start
708
	p = obj.Appendp(p, c.newprog)
709

710
	p.As = ABR
711
	p.To.Type = obj.TYPE_BRANCH
712
	p.To.SetTarget(c.cursym.Func.Text.Link)
713
	return p
714
}
715

716
var unaryDst = map[obj.As]bool{
717
	ASTCK:  true,
718
	ASTCKC: true,
719
	ASTCKE: true,
720
	ASTCKF: true,
721
	ANEG:   true,
722
	ANEGW:  true,
723
	AVONE:  true,
724
	AVZERO: true,
725
}
726

727
var Links390x = obj.LinkArch{
728
	Arch:           sys.ArchS390X,
729
	Init:           buildop,
730
	Preprocess:     preprocess,
731
	Assemble:       spanz,
732
	Progedit:       progedit,
733
	UnaryDst:       unaryDst,
734
	DWARFRegisters: S390XDWARFRegisters,
735
}
736

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

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

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

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