1 // cmd/7l/noop.c, cmd/7l/obj.c, cmd/ld/pass.c from Vita Nuova.
2 // https://code.google.com/p/ken-cc/source/browse/
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.
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:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
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
40 var complements = []obj.As{
51 func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
52 // MOV g_stackguard(g), R1
53 p = obj.Appendp(p, c.newprog)
56 p.From.Type = obj.TYPE_MEM
58 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
60 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
62 p.To.Type = obj.TYPE_REG
66 if framesize <= objabi.StackSmall {
67 // small stack: SP < stackguard
70 p = obj.Appendp(p, c.newprog)
73 p.From.Type = obj.TYPE_REG
75 p.To.Type = obj.TYPE_REG
78 p = obj.Appendp(p, c.newprog)
80 p.From.Type = obj.TYPE_REG
83 } else if framesize <= objabi.StackBig {
84 // large stack: SP-framesize < stackguard-StackSmall
85 // SUB $(framesize-StackSmall), SP, R2
87 p = obj.Appendp(p, c.newprog)
90 p.From.Type = obj.TYPE_CONST
91 p.From.Offset = int64(framesize) - objabi.StackSmall
93 p.To.Type = obj.TYPE_REG
96 p = obj.Appendp(p, c.newprog)
98 p.From.Type = obj.TYPE_REG
102 // Such a large stack we need to protect against wraparound
103 // if SP is close to zero.
104 // SP-stackguard+StackGuard < framesize + (StackGuard-StackSmall)
105 // The +StackGuard on both sides is required to keep the left side positive:
106 // SP is allowed to be slightly below stackguard. See stack.h.
107 // CMP $StackPreempt, R1
108 // BEQ label_of_call_to_morestack
109 // ADD $StackGuard, SP, R2
111 // MOV $(framesize+(StackGuard-StackSmall)), R3
113 p = obj.Appendp(p, c.newprog)
116 p.From.Type = obj.TYPE_CONST
117 p.From.Offset = objabi.StackPreempt
120 p = obj.Appendp(p, c.newprog)
123 p.To.Type = obj.TYPE_BRANCH
125 p = obj.Appendp(p, c.newprog)
127 p.From.Type = obj.TYPE_CONST
128 p.From.Offset = int64(objabi.StackGuard)
130 p.To.Type = obj.TYPE_REG
133 p = obj.Appendp(p, c.newprog)
135 p.From.Type = obj.TYPE_REG
137 p.To.Type = obj.TYPE_REG
140 p = obj.Appendp(p, c.newprog)
142 p.From.Type = obj.TYPE_CONST
143 p.From.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall)
144 p.To.Type = obj.TYPE_REG
147 p = obj.Appendp(p, c.newprog)
149 p.From.Type = obj.TYPE_REG
155 bls := obj.Appendp(p, c.newprog)
157 bls.To.Type = obj.TYPE_BRANCH
160 for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
163 // Now we are at the end of the function, but logically
164 // we are still in function prologue. We need to fix the
165 // SP data and PCDATA.
166 spfix := obj.Appendp(last, c.newprog)
168 spfix.Spadj = -framesize
170 pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
173 movlr := obj.Appendp(pcdata, c.newprog)
175 movlr.From.Type = obj.TYPE_REG
176 movlr.From.Reg = REGLINK
177 movlr.To.Type = obj.TYPE_REG
178 movlr.To.Reg = REG_R3
186 debug = obj.Appendp(debug, c.newprog)
188 debug.From.Type = obj.TYPE_CONST
189 debug.From.Offset = int64(framesize)
190 debug.To.Type = obj.TYPE_REG
191 debug.To.Reg = REGTMP
194 // BL runtime.morestack(SB)
195 call := obj.Appendp(debug, c.newprog)
197 call.To.Type = obj.TYPE_BRANCH
198 morestack := "runtime.morestack"
200 case c.cursym.CFunc():
201 morestack = "runtime.morestackc"
202 case !c.cursym.Func.Text.From.Sym.NeedCtxt():
203 morestack = "runtime.morestack_noctxt"
205 call.To.Sym = c.ctxt.Lookup(morestack)
208 jmp := obj.Appendp(call, c.newprog)
210 jmp.To.Type = obj.TYPE_BRANCH
211 jmp.Pcond = c.cursym.Func.Text.Link
212 jmp.Spadj = +framesize
214 // placeholder for bls's jump target
215 // p = obj.Appendp(ctxt, p)
221 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
222 c := ctxt7{ctxt: ctxt, newprog: newprog}
227 // $0 results in C_ZCON, which matches both C_REG and various
228 // C_xCON, however the C_REG cases in asmout don't expect a
229 // constant, so they will use the register fields and assemble
230 // a R0. To prevent that, rewrite $0 as ZR.
231 if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 {
232 p.From.Type = obj.TYPE_REG
235 if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 {
236 p.To.Type = obj.TYPE_REG
240 // Rewrite BR/BL to symbol as TYPE_BRANCH.
248 p.To.Type = obj.TYPE_BRANCH
253 // Rewrite float constants to values stored in memory.
256 if p.From.Type == obj.TYPE_FCONST {
257 f64 := p.From.Val.(float64)
259 if c.chipfloat7(f64) > 0 {
262 if math.Float32bits(f32) == 0 {
263 p.From.Type = obj.TYPE_REG
267 p.From.Type = obj.TYPE_MEM
268 p.From.Sym = c.ctxt.Float32Sym(f32)
269 p.From.Name = obj.NAME_EXTERN
274 if p.From.Type == obj.TYPE_FCONST {
275 f64 := p.From.Val.(float64)
276 if c.chipfloat7(f64) > 0 {
279 if math.Float64bits(f64) == 0 {
280 p.From.Type = obj.TYPE_REG
284 p.From.Type = obj.TYPE_MEM
285 p.From.Sym = c.ctxt.Float64Sym(f64)
286 p.From.Name = obj.NAME_EXTERN
293 // Rewrite negative immediates as positive immediates with
294 // complementary instruction.
296 case AADD, ASUB, ACMP, ACMN:
297 if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
298 p.From.Offset = -p.From.Offset
299 p.As = complements[p.As]
301 case AADDW, ASUBW, ACMPW, ACMNW:
302 if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
303 p.From.Offset = -p.From.Offset
304 p.As = complements[p.As]
308 // For 32-bit logical instruction with constant,
309 // rewrite the high 32-bit to be a repetition of
310 // the low 32-bit, so that the BITCON test can be
311 // shared for both 32-bit and 64-bit. 32-bit ops
312 // will zero the high 32-bit of the destination
314 if isANDWop(p.As) && p.From.Type == obj.TYPE_CONST {
315 v := p.From.Offset & 0xffffffff
316 p.From.Offset = v | v<<32
319 if c.ctxt.Flag_dynlink {
324 // Rewrite p, if necessary, to access global data via the global offset table.
325 func (c *ctxt7) rewriteToUseGot(p *obj.Prog) {
326 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
329 // MOVD runtime.duffxxx@GOT, REGTMP
330 // ADD $offset, REGTMP
333 if p.As == obj.ADUFFZERO {
334 sym = c.ctxt.Lookup("runtime.duffzero")
336 sym = c.ctxt.Lookup("runtime.duffcopy")
338 offset := p.To.Offset
340 p.From.Type = obj.TYPE_MEM
341 p.From.Name = obj.NAME_GOTREF
343 p.To.Type = obj.TYPE_REG
345 p.To.Name = obj.NAME_NONE
348 p1 := obj.Appendp(p, c.newprog)
350 p1.From.Type = obj.TYPE_CONST
351 p1.From.Offset = offset
352 p1.To.Type = obj.TYPE_REG
354 p2 := obj.Appendp(p1, c.newprog)
356 p2.To.Type = obj.TYPE_REG
360 // We only care about global data: NAME_EXTERN means a global
361 // symbol in the Go sense, and p.Sym.Local is true for a few
362 // internally defined symbols.
363 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
364 // MOVD $sym, Rx becomes MOVD sym@GOT, Rx
365 // MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
367 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
369 if p.To.Type != obj.TYPE_REG {
370 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
372 p.From.Type = obj.TYPE_MEM
373 p.From.Name = obj.NAME_GOTREF
374 if p.From.Offset != 0 {
375 q := obj.Appendp(p, c.newprog)
377 q.From.Type = obj.TYPE_CONST
378 q.From.Offset = p.From.Offset
383 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
384 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
387 // MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
388 // MOVx Ry, sym becomes MOVD sym@GOT, REGTMP; MOVD Ry, (REGTMP)
389 // An addition may be inserted between the two MOVs if there is an offset.
390 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
391 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
392 c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
395 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
400 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
403 if source.Sym.Type == objabi.STLSBSS {
406 if source.Type != obj.TYPE_MEM {
407 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
409 p1 := obj.Appendp(p, c.newprog)
410 p2 := obj.Appendp(p1, c.newprog)
412 p1.From.Type = obj.TYPE_MEM
413 p1.From.Sym = source.Sym
414 p1.From.Name = obj.NAME_GOTREF
415 p1.To.Type = obj.TYPE_REG
421 if p.From.Name == obj.NAME_EXTERN {
423 p2.From.Name = obj.NAME_NONE
425 } else if p.To.Name == obj.NAME_EXTERN {
427 p2.To.Name = obj.NAME_NONE
435 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
436 if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
440 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym}
442 p := c.cursym.Func.Text
443 textstksiz := p.To.Offset
444 if textstksiz == -8 {
445 // Historical way to mark NOFRAME.
446 p.From.Sym.Set(obj.AttrNoFrame, true)
450 c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz)
452 if p.From.Sym.NoFrame() {
454 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
458 c.cursym.Func.Args = p.To.Val.(int32)
459 c.cursym.Func.Locals = int32(textstksiz)
462 * find leaf subroutines
466 q := (*obj.Prog)(nil)
468 for p := c.cursym.Func.Text; p != nil; p = p.Link {
479 q.Link = q1 /* q is non-nop */
487 c.cursym.Func.Text.Mark &^= LEAF
518 for q1.As == obj.ANOP {
531 for p := c.cursym.Func.Text; p != nil; p = p.Link {
535 c.cursym.Func.Text = p
536 c.autosize = int32(textstksiz)
538 if p.Mark&LEAF != 0 && c.autosize == 0 {
539 // A leaf function with no locals has no frame.
540 p.From.Sym.Set(obj.AttrNoFrame, true)
543 if !p.From.Sym.NoFrame() {
544 // If there is a stack frame at all, it includes
545 // space to save the LR.
550 extrasize := int32(0)
551 if c.autosize%16 == 8 {
552 // Allocate extra 8 bytes on the frame top to save FP
554 } else if c.autosize&(16-1) == 0 {
555 // Allocate extra 16 bytes to save FP for the old frame whose size is 8 mod 16
558 c.ctxt.Diag("%v: unaligned frame size %d - must be 16 aligned", p, c.autosize-8)
560 c.autosize += extrasize
561 c.cursym.Func.Locals += extrasize
563 // low 32 bits for autosize
564 // high 32 bits for extrasize
565 p.To.Offset = int64(c.autosize) | int64(extrasize)<<32
571 if c.autosize == 0 && c.cursym.Func.Text.Mark&LEAF == 0 {
572 if c.ctxt.Debugvlog {
573 c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name)
575 c.cursym.Func.Text.Mark |= LEAF
578 if cursym.Func.Text.Mark&LEAF != 0 {
579 cursym.Set(obj.AttrLeaf, true)
580 if p.From.Sym.NoFrame() {
585 if !p.From.Sym.NoSplit() {
586 p = c.stacksplit(p, c.autosize) // emit split check
589 aoffset := c.autosize
594 // Frame is non-empty. Make sure to save link register, even if
595 // it is a leaf function, so that traceback works.
597 if c.autosize > aoffset {
598 // Frame size is too large for a MOVD.W instruction.
599 // Store link register before decrementing SP, so if a signal comes
600 // during the execution of the function prologue, the traceback
601 // code will not see a half-updated stack frame.
602 // This sequence is not async preemptible, as if we open a frame
603 // at the current SP, it will clobber the saved LR.
604 q = c.ctxt.StartUnsafePoint(q, c.newprog)
606 q = obj.Appendp(q, c.newprog)
609 q.From.Type = obj.TYPE_CONST
610 q.From.Offset = int64(c.autosize)
612 q.To.Type = obj.TYPE_REG
615 q = obj.Appendp(q, c.newprog)
618 q.From.Type = obj.TYPE_REG
620 q.To.Type = obj.TYPE_MEM
623 q1 = obj.Appendp(q, c.newprog)
626 q1.From.Type = obj.TYPE_REG
628 q1.To.Type = obj.TYPE_REG
630 q1.Spadj = c.autosize
632 if c.ctxt.Headtype == objabi.Hdarwin {
633 // iOS does not support SA_ONSTACK. We will run the signal handler
634 // on the G stack. If we write below SP, it may be clobbered by
635 // the signal handler. So we save LR after decrementing SP.
636 q1 = obj.Appendp(q1, c.newprog)
639 q1.From.Type = obj.TYPE_REG
640 q1.From.Reg = REGLINK
641 q1.To.Type = obj.TYPE_MEM
645 q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
647 // small frame, update SP and save LR in a single MOVD.W instruction
648 q1 = obj.Appendp(q, c.newprog)
651 q1.From.Type = obj.TYPE_REG
652 q1.From.Reg = REGLINK
653 q1.To.Type = obj.TYPE_MEM
655 q1.To.Offset = int64(-aoffset)
660 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
661 q1 = obj.Appendp(q1, c.newprog)
664 q1.From.Type = obj.TYPE_REG
666 q1.To.Type = obj.TYPE_MEM
670 q1 = obj.Appendp(q1, c.newprog)
673 q1.From.Type = obj.TYPE_CONST
676 q1.To.Type = obj.TYPE_REG
680 if c.cursym.Func.Text.From.Sym.Wrapper() {
681 // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
683 // MOV g_panic(g), R1
687 // ... function body ...
689 // MOV panic_argp(R1), R2
690 // ADD $(autosize+8), RSP, R3
694 // MOVD R4, panic_argp(R1)
697 // The NOP is needed to give the jumps somewhere to land.
698 // It is a liblink NOP, not an ARM64 NOP: it encodes to 0 instruction bytes.
701 // MOV g_panic(g), R1
702 q = obj.Appendp(q, c.newprog)
704 q.From.Type = obj.TYPE_MEM
706 q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
707 q.To.Type = obj.TYPE_REG
710 // CBNZ R1, checkargp
711 cbnz := obj.Appendp(q, c.newprog)
713 cbnz.From.Type = obj.TYPE_REG
714 cbnz.From.Reg = REG_R1
715 cbnz.To.Type = obj.TYPE_BRANCH
717 // Empty branch target at the top of the function body
718 end := obj.Appendp(cbnz, c.newprog)
721 // find the end of the function
723 for last = end; last.Link != nil; last = last.Link {
726 // MOV panic_argp(R1), R2
727 mov := obj.Appendp(last, c.newprog)
729 mov.From.Type = obj.TYPE_MEM
730 mov.From.Reg = REG_R1
731 mov.From.Offset = 0 // Panic.argp
732 mov.To.Type = obj.TYPE_REG
735 // CBNZ branches to the MOV above
738 // ADD $(autosize+8), SP, R3
739 q = obj.Appendp(mov, c.newprog)
741 q.From.Type = obj.TYPE_CONST
742 q.From.Offset = int64(c.autosize) + 8
744 q.To.Type = obj.TYPE_REG
748 q = obj.Appendp(q, c.newprog)
750 q.From.Type = obj.TYPE_REG
755 q = obj.Appendp(q, c.newprog)
757 q.To.Type = obj.TYPE_BRANCH
761 q = obj.Appendp(q, c.newprog)
763 q.From.Type = obj.TYPE_CONST
766 q.To.Type = obj.TYPE_REG
769 // MOV R4, panic_argp(R1)
770 q = obj.Appendp(q, c.newprog)
772 q.From.Type = obj.TYPE_REG
774 q.To.Type = obj.TYPE_MEM
776 q.To.Offset = 0 // Panic.argp
779 q = obj.Appendp(q, c.newprog)
781 q.To.Type = obj.TYPE_BRANCH
787 if p.From.Type == obj.TYPE_CONST {
788 c.ctxt.Diag("using BECOME (%v) is not supported!", p)
794 if c.cursym.Func.Text.Mark&LEAF != 0 {
797 p.From.Type = obj.TYPE_CONST
798 p.From.Offset = int64(c.autosize)
799 p.To.Type = obj.TYPE_REG
801 p.Spadj = -c.autosize
803 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
804 p = obj.Appendp(p, c.newprog)
806 p.From.Type = obj.TYPE_CONST
809 p.To.Type = obj.TYPE_REG
814 /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
816 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
818 p.From.Type = obj.TYPE_MEM
821 p.To.Type = obj.TYPE_REG
823 p = obj.Appendp(p, c.newprog)
826 aoffset := c.autosize
830 p.From.Type = obj.TYPE_MEM
832 p.From.Offset = int64(aoffset)
834 p.To.Type = obj.TYPE_REG
839 p.From.Type = obj.TYPE_MEM
842 p.To.Type = obj.TYPE_REG
847 q.From.Type = obj.TYPE_CONST
848 q.From.Offset = int64(aoffset)
849 q.To.Type = obj.TYPE_REG
852 q.Spadj = int32(-q.From.Offset)
859 if p.As != obj.ARET {
867 if retjmp != nil { // retjmp
869 p.To.Type = obj.TYPE_BRANCH
871 p.Spadj = +c.autosize
876 p.To.Type = obj.TYPE_MEM
879 p.Spadj = +c.autosize
882 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
884 p.Spadj = int32(-p.From.Offset)
886 p.Spadj = int32(+p.From.Offset)
890 case obj.AGETCALLERPC:
894 p.From.Type = obj.TYPE_REG
899 p.From.Type = obj.TYPE_MEM
904 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
906 // STP (FP, R27), -24(SP)
913 // copy DUFFCOPY from q1 to q4
914 q4 := obj.Appendp(p, c.newprog)
916 q4.As = obj.ADUFFCOPY
920 q1.From.Type = obj.TYPE_BRANCH
921 q1.To.Type = obj.TYPE_REG
924 q2 := obj.Appendp(q1, c.newprog)
927 q2.From.Type = obj.TYPE_REGREG
929 q2.From.Offset = int64(REG_R27)
930 q2.To.Type = obj.TYPE_MEM
934 // maintaine FP for DUFFCOPY
935 q3 := obj.Appendp(q2, c.newprog)
938 q3.From.Type = obj.TYPE_CONST
941 q3.To.Type = obj.TYPE_REG
944 q5 := obj.Appendp(q4, c.newprog)
947 q5.From.Type = obj.TYPE_CONST
950 q5.To.Type = obj.TYPE_REG
957 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
959 // STP (FP, R27), -24(SP)
966 // copy DUFFZERO from q1 to q4
967 q4 := obj.Appendp(p, c.newprog)
969 q4.As = obj.ADUFFZERO
973 q1.From.Type = obj.TYPE_BRANCH
974 q1.To.Type = obj.TYPE_REG
977 q2 := obj.Appendp(q1, c.newprog)
980 q2.From.Type = obj.TYPE_REGREG
982 q2.From.Offset = int64(REG_R27)
983 q2.To.Type = obj.TYPE_MEM
987 // maintaine FP for DUFFZERO
988 q3 := obj.Appendp(q2, c.newprog)
991 q3.From.Type = obj.TYPE_CONST
994 q3.To.Type = obj.TYPE_REG
997 q5 := obj.Appendp(q4, c.newprog)
1000 q5.From.Type = obj.TYPE_CONST
1003 q5.To.Type = obj.TYPE_REG
1012 func nocache(p *obj.Prog) {
1018 var unaryDst = map[obj.As]bool{
1026 var Linkarm64 = obj.LinkArch{
1027 Arch: sys.ArchARM64,
1029 Preprocess: preprocess,
1033 DWARFRegisters: ARM64DWARFRegisters,