github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/obj/arm64/obj7.go (about) 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/ 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 arm64 32 33 import ( 34 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj" 35 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi" 36 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/src" 37 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/sys" 38 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/abi" 39 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/buildcfg" 40 "log" 41 "math" 42 ) 43 44 45 46 var zrReplace = map[obj.As]bool{ 47 AMOVD: true, 48 AMOVW: true, 49 AMOVWU: true, 50 AMOVH: true, 51 AMOVHU: true, 52 AMOVB: true, 53 AMOVBU: true, 54 ASBC: true, 55 ASBCW: true, 56 ASBCS: true, 57 ASBCSW: true, 58 AADC: true, 59 AADCW: true, 60 AADCS: true, 61 AADCSW: true, 62 AFMOVD: true, 63 AFMOVS: true, 64 AMSR: true, 65 } 66 67 func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { 68 if c.ctxt.Flag_maymorestack != "" { 69 p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) 70 71 72 73 const frameSize = 32 74 p = obj.Appendp(p, c.newprog) 75 p.As = AMOVD 76 p.From.Type = obj.TYPE_REG 77 p.From.Reg = REGLINK 78 p.To.Type = obj.TYPE_MEM 79 p.Scond = C_XPRE 80 p.To.Offset = -frameSize 81 p.To.Reg = REGSP 82 p.Spadj = frameSize 83 84 85 p = obj.Appendp(p, c.newprog) 86 p.As = AMOVD 87 p.From.Type = obj.TYPE_REG 88 p.From.Reg = REGFP 89 p.To.Type = obj.TYPE_MEM 90 p.To.Reg = REGSP 91 p.To.Offset = -8 92 93 p = obj.Appendp(p, c.newprog) 94 p.As = ASUB 95 p.From.Type = obj.TYPE_CONST 96 p.From.Offset = 8 97 p.Reg = REGSP 98 p.To.Type = obj.TYPE_REG 99 p.To.Reg = REGFP 100 101 102 103 p = obj.Appendp(p, c.newprog) 104 p.As = AMOVD 105 p.From.Type = obj.TYPE_REG 106 p.From.Reg = REGCTXT 107 p.To.Type = obj.TYPE_MEM 108 p.To.Reg = REGSP 109 p.To.Offset = 8 110 111 112 p = obj.Appendp(p, c.newprog) 113 p.As = ABL 114 p.To.Type = obj.TYPE_BRANCH 115 116 p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) 117 118 119 p = obj.Appendp(p, c.newprog) 120 p.As = AMOVD 121 p.From.Type = obj.TYPE_MEM 122 p.From.Reg = REGSP 123 p.From.Offset = 8 124 p.To.Type = obj.TYPE_REG 125 p.To.Reg = REGCTXT 126 127 128 p = obj.Appendp(p, c.newprog) 129 p.As = AMOVD 130 p.From.Type = obj.TYPE_MEM 131 p.From.Reg = REGSP 132 p.From.Offset = -8 133 p.To.Type = obj.TYPE_REG 134 p.To.Reg = REGFP 135 136 137 p = obj.Appendp(p, c.newprog) 138 p.As = AMOVD 139 p.From.Type = obj.TYPE_MEM 140 p.Scond = C_XPOST 141 p.From.Offset = frameSize 142 p.From.Reg = REGSP 143 p.To.Type = obj.TYPE_REG 144 p.To.Reg = REGLINK 145 p.Spadj = -frameSize 146 147 p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) 148 } 149 150 151 startPred := p 152 153 154 p = obj.Appendp(p, c.newprog) 155 156 p.As = AMOVD 157 p.From.Type = obj.TYPE_MEM 158 p.From.Reg = REGG 159 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) 160 if c.cursym.CFunc() { 161 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) 162 } 163 p.To.Type = obj.TYPE_REG 164 p.To.Reg = REGRT1 165 166 167 168 169 170 p = c.ctxt.StartUnsafePoint(p, c.newprog) 171 172 q := (*obj.Prog)(nil) 173 if framesize <= abi.StackSmall { 174 175 176 177 p = obj.Appendp(p, c.newprog) 178 p.As = ACMP 179 p.From.Type = obj.TYPE_REG 180 p.From.Reg = REGRT1 181 p.Reg = REGSP 182 } else if framesize <= abi.StackBig { 183 184 185 186 p = obj.Appendp(p, c.newprog) 187 188 p.As = ASUB 189 p.From.Type = obj.TYPE_CONST 190 p.From.Offset = int64(framesize) - abi.StackSmall 191 p.Reg = REGSP 192 p.To.Type = obj.TYPE_REG 193 p.To.Reg = REGRT2 194 195 p = obj.Appendp(p, c.newprog) 196 p.As = ACMP 197 p.From.Type = obj.TYPE_REG 198 p.From.Reg = REGRT1 199 p.Reg = REGRT2 200 } else { 201 202 203 204 205 206 207 208 209 210 211 212 213 p = obj.Appendp(p, c.newprog) 214 p.As = ASUBS 215 p.From.Type = obj.TYPE_CONST 216 p.From.Offset = int64(framesize) - abi.StackSmall 217 p.Reg = REGSP 218 p.To.Type = obj.TYPE_REG 219 p.To.Reg = REGRT2 220 221 p = obj.Appendp(p, c.newprog) 222 q = p 223 p.As = ABLO 224 p.To.Type = obj.TYPE_BRANCH 225 226 p = obj.Appendp(p, c.newprog) 227 p.As = ACMP 228 p.From.Type = obj.TYPE_REG 229 p.From.Reg = REGRT1 230 p.Reg = REGRT2 231 } 232 233 234 bls := obj.Appendp(p, c.newprog) 235 bls.As = ABLS 236 bls.To.Type = obj.TYPE_BRANCH 237 238 end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1) 239 240 var last *obj.Prog 241 for last = c.cursym.Func().Text; last.Link != nil; last = last.Link { 242 } 243 244 245 246 247 spfix := obj.Appendp(last, c.newprog) 248 spfix.As = obj.ANOP 249 spfix.Spadj = -framesize 250 251 pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog) 252 pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog) 253 254 if q != nil { 255 q.To.SetTarget(pcdata) 256 } 257 bls.To.SetTarget(pcdata) 258 259 spill := c.cursym.Func().SpillRegisterArgs(pcdata, c.newprog) 260 261 262 movlr := obj.Appendp(spill, c.newprog) 263 movlr.As = AMOVD 264 movlr.From.Type = obj.TYPE_REG 265 movlr.From.Reg = REGLINK 266 movlr.To.Type = obj.TYPE_REG 267 movlr.To.Reg = REG_R3 268 269 debug := movlr 270 if false { 271 debug = obj.Appendp(debug, c.newprog) 272 debug.As = AMOVD 273 debug.From.Type = obj.TYPE_CONST 274 debug.From.Offset = int64(framesize) 275 debug.To.Type = obj.TYPE_REG 276 debug.To.Reg = REGTMP 277 } 278 279 280 call := obj.Appendp(debug, c.newprog) 281 call.As = ABL 282 call.To.Type = obj.TYPE_BRANCH 283 morestack := "runtime.morestack" 284 switch { 285 case c.cursym.CFunc(): 286 morestack = "runtime.morestackc" 287 case !c.cursym.Func().Text.From.Sym.NeedCtxt(): 288 morestack = "runtime.morestack_noctxt" 289 } 290 call.To.Sym = c.ctxt.Lookup(morestack) 291 292 unspill := c.cursym.Func().UnspillRegisterArgs(call, c.newprog) 293 pcdata = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1) 294 295 296 jmp := obj.Appendp(pcdata, c.newprog) 297 jmp.As = AB 298 jmp.To.Type = obj.TYPE_BRANCH 299 jmp.To.SetTarget(startPred.Link) 300 jmp.Spadj = +framesize 301 302 return end 303 } 304 305 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { 306 c := ctxt7{ctxt: ctxt, newprog: newprog} 307 308 p.From.Class = 0 309 p.To.Class = 0 310 311 312 313 314 if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 && zrReplace[p.As] { 315 p.From.Type = obj.TYPE_REG 316 p.From.Reg = REGZERO 317 } 318 319 320 switch p.As { 321 case AB, 322 ABL, 323 obj.ARET, 324 obj.ADUFFZERO, 325 obj.ADUFFCOPY: 326 if p.To.Sym != nil { 327 p.To.Type = obj.TYPE_BRANCH 328 } 329 break 330 } 331 332 333 switch p.As { 334 case AFMOVS: 335 if p.From.Type == obj.TYPE_FCONST { 336 f64 := p.From.Val.(float64) 337 f32 := float32(f64) 338 if c.chipfloat7(f64) > 0 { 339 break 340 } 341 if math.Float32bits(f32) == 0 { 342 p.From.Type = obj.TYPE_REG 343 p.From.Reg = REGZERO 344 break 345 } 346 p.From.Type = obj.TYPE_MEM 347 p.From.Sym = c.ctxt.Float32Sym(f32) 348 p.From.Name = obj.NAME_EXTERN 349 p.From.Offset = 0 350 } 351 352 case AFMOVD: 353 if p.From.Type == obj.TYPE_FCONST { 354 f64 := p.From.Val.(float64) 355 if c.chipfloat7(f64) > 0 { 356 break 357 } 358 if math.Float64bits(f64) == 0 { 359 p.From.Type = obj.TYPE_REG 360 p.From.Reg = REGZERO 361 break 362 } 363 p.From.Type = obj.TYPE_MEM 364 p.From.Sym = c.ctxt.Float64Sym(f64) 365 p.From.Name = obj.NAME_EXTERN 366 p.From.Offset = 0 367 } 368 369 break 370 } 371 372 if c.ctxt.Flag_dynlink { 373 c.rewriteToUseGot(p) 374 } 375 } 376 377 378 func (c *ctxt7) rewriteToUseGot(p *obj.Prog) { 379 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { 380 381 382 383 384 385 var sym *obj.LSym 386 if p.As == obj.ADUFFZERO { 387 sym = c.ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) 388 } else { 389 sym = c.ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) 390 } 391 offset := p.To.Offset 392 p.As = AMOVD 393 p.From.Type = obj.TYPE_MEM 394 p.From.Name = obj.NAME_GOTREF 395 p.From.Sym = sym 396 p.To.Type = obj.TYPE_REG 397 p.To.Reg = REGTMP 398 p.To.Name = obj.NAME_NONE 399 p.To.Offset = 0 400 p.To.Sym = nil 401 p1 := obj.Appendp(p, c.newprog) 402 p1.As = AADD 403 p1.From.Type = obj.TYPE_CONST 404 p1.From.Offset = offset 405 p1.To.Type = obj.TYPE_REG 406 p1.To.Reg = REGTMP 407 p2 := obj.Appendp(p1, c.newprog) 408 p2.As = obj.ACALL 409 p2.To.Type = obj.TYPE_REG 410 p2.To.Reg = REGTMP 411 } 412 413 414 415 416 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { 417 418 419 if p.As != AMOVD { 420 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) 421 } 422 if p.To.Type != obj.TYPE_REG { 423 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p) 424 } 425 p.From.Type = obj.TYPE_MEM 426 p.From.Name = obj.NAME_GOTREF 427 if p.From.Offset != 0 { 428 q := obj.Appendp(p, c.newprog) 429 q.As = AADD 430 q.From.Type = obj.TYPE_CONST 431 q.From.Offset = p.From.Offset 432 q.To = p.To 433 p.From.Offset = 0 434 } 435 } 436 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { 437 c.ctxt.Diag("don't know how to handle %v with -dynlink", p) 438 } 439 var source *obj.Addr 440 441 442 443 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { 444 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { 445 c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) 446 } 447 source = &p.From 448 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { 449 source = &p.To 450 } else { 451 return 452 } 453 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { 454 return 455 } 456 if source.Sym.Type == objabi.STLSBSS { 457 return 458 } 459 if source.Type != obj.TYPE_MEM { 460 c.ctxt.Diag("don't know how to handle %v with -dynlink", p) 461 } 462 p1 := obj.Appendp(p, c.newprog) 463 p2 := obj.Appendp(p1, c.newprog) 464 p1.As = AMOVD 465 p1.From.Type = obj.TYPE_MEM 466 p1.From.Sym = source.Sym 467 p1.From.Name = obj.NAME_GOTREF 468 p1.To.Type = obj.TYPE_REG 469 p1.To.Reg = REGTMP 470 471 p2.As = p.As 472 p2.From = p.From 473 p2.To = p.To 474 if p.From.Name == obj.NAME_EXTERN { 475 p2.From.Reg = REGTMP 476 p2.From.Name = obj.NAME_NONE 477 p2.From.Sym = nil 478 } else if p.To.Name == obj.NAME_EXTERN { 479 p2.To.Reg = REGTMP 480 p2.To.Name = obj.NAME_NONE 481 p2.To.Sym = nil 482 } else { 483 return 484 } 485 obj.Nopout(p) 486 } 487 488 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 489 if cursym.Func().Text == nil || cursym.Func().Text.Link == nil { 490 return 491 } 492 493 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym} 494 495 p := c.cursym.Func().Text 496 textstksiz := p.To.Offset 497 if textstksiz == -8 { 498 499 p.From.Sym.Set(obj.AttrNoFrame, true) 500 textstksiz = 0 501 } 502 if textstksiz < 0 { 503 c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz) 504 } 505 if p.From.Sym.NoFrame() { 506 if textstksiz != 0 { 507 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz) 508 } 509 } 510 511 c.cursym.Func().Args = p.To.Val.(int32) 512 c.cursym.Func().Locals = int32(textstksiz) 513 514 515 for p := c.cursym.Func().Text; p != nil; p = p.Link { 516 switch p.As { 517 case obj.ATEXT: 518 p.Mark |= LEAF 519 520 case ABL, 521 obj.ADUFFZERO, 522 obj.ADUFFCOPY: 523 c.cursym.Func().Text.Mark &^= LEAF 524 } 525 } 526 527 var q *obj.Prog 528 var q1 *obj.Prog 529 var retjmp *obj.LSym 530 for p := c.cursym.Func().Text; p != nil; p = p.Link { 531 o := p.As 532 switch o { 533 case obj.ATEXT: 534 c.cursym.Func().Text = p 535 c.autosize = int32(textstksiz) 536 537 if p.Mark&LEAF != 0 && c.autosize == 0 { 538 539 p.From.Sym.Set(obj.AttrNoFrame, true) 540 } 541 542 if !p.From.Sym.NoFrame() { 543 544 545 c.autosize += 8 546 } 547 548 if c.autosize != 0 { 549 extrasize := int32(0) 550 if c.autosize%16 == 8 { 551 552 extrasize = 8 553 } else if c.autosize&(16-1) == 0 { 554 555 extrasize = 16 556 } else { 557 c.ctxt.Diag("%v: unaligned frame size %d - must be 16 aligned", p, c.autosize-8) 558 } 559 c.autosize += extrasize 560 c.cursym.Func().Locals += extrasize 561 562 563 564 p.To.Offset = int64(c.autosize) | int64(extrasize)<<32 565 } else { 566 567 p.To.Offset = 0 568 } 569 570 if c.autosize == 0 && c.cursym.Func().Text.Mark&LEAF == 0 { 571 if c.ctxt.Debugvlog { 572 c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func().Text.From.Sym.Name) 573 } 574 c.cursym.Func().Text.Mark |= LEAF 575 } 576 577 if cursym.Func().Text.Mark&LEAF != 0 { 578 cursym.Set(obj.AttrLeaf, true) 579 if p.From.Sym.NoFrame() { 580 break 581 } 582 } 583 584 if p.Mark&LEAF != 0 && c.autosize < abi.StackSmall { 585 586 587 p.From.Sym.Set(obj.AttrNoSplit, true) 588 } 589 590 if !p.From.Sym.NoSplit() { 591 p = c.stacksplit(p, c.autosize) 592 } 593 594 var prologueEnd *obj.Prog 595 596 aoffset := c.autosize 597 if aoffset > 0xf0 { 598 599 600 aoffset = 0xf0 601 } 602 603 604 605 q = p 606 if c.autosize > aoffset { 607 608 609 610 611 612 613 q1 = obj.Appendp(q, c.newprog) 614 q1.Pos = p.Pos 615 q1.As = ASUB 616 q1.From.Type = obj.TYPE_CONST 617 q1.From.Offset = int64(c.autosize) 618 q1.Reg = REGSP 619 q1.To.Type = obj.TYPE_REG 620 q1.To.Reg = REG_R20 621 622 prologueEnd = q1 623 624 625 q1 = obj.Appendp(q1, c.newprog) 626 q1.Pos = p.Pos 627 q1.As = ASTP 628 q1.From.Type = obj.TYPE_REGREG 629 q1.From.Reg = REGFP 630 q1.From.Offset = REGLINK 631 q1.To.Type = obj.TYPE_MEM 632 q1.To.Reg = REG_R20 633 q1.To.Offset = -8 634 635 636 637 q1 = c.ctxt.StartUnsafePoint(q1, c.newprog) 638 639 640 q1 = obj.Appendp(q1, c.newprog) 641 q1.Pos = p.Pos 642 q1.As = AMOVD 643 q1.From.Type = obj.TYPE_REG 644 q1.From.Reg = REG_R20 645 q1.To.Type = obj.TYPE_REG 646 q1.To.Reg = REGSP 647 q1.Spadj = c.autosize 648 649 q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1) 650 651 if buildcfg.GOOS == "ios" { 652 653 654 655 656 q1 = obj.Appendp(q1, c.newprog) 657 q1.Pos = p.Pos 658 q1.As = ASTP 659 q1.From.Type = obj.TYPE_REGREG 660 q1.From.Reg = REGFP 661 q1.From.Offset = REGLINK 662 q1.To.Type = obj.TYPE_MEM 663 q1.To.Reg = REGSP 664 q1.To.Offset = -8 665 } 666 } else { 667 668 669 670 671 672 673 674 675 676 q1 = obj.Appendp(q, c.newprog) 677 q1.As = AMOVD 678 q1.Pos = p.Pos 679 q1.From.Type = obj.TYPE_REG 680 q1.From.Reg = REGLINK 681 q1.To.Type = obj.TYPE_MEM 682 q1.Scond = C_XPRE 683 q1.To.Offset = int64(-aoffset) 684 q1.To.Reg = REGSP 685 q1.Spadj = aoffset 686 687 prologueEnd = q1 688 689 690 q1 = obj.Appendp(q1, c.newprog) 691 q1.Pos = p.Pos 692 q1.As = AMOVD 693 q1.From.Type = obj.TYPE_REG 694 q1.From.Reg = REGFP 695 q1.To.Type = obj.TYPE_MEM 696 q1.To.Reg = REGSP 697 q1.To.Offset = -8 698 } 699 700 prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd) 701 702 q1 = obj.Appendp(q1, c.newprog) 703 q1.Pos = p.Pos 704 q1.As = ASUB 705 q1.From.Type = obj.TYPE_CONST 706 q1.From.Offset = 8 707 q1.Reg = REGSP 708 q1.To.Type = obj.TYPE_REG 709 q1.To.Reg = REGFP 710 711 if c.cursym.Func().Text.From.Sym.Wrapper() { 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 q = q1 731 732 733 q = obj.Appendp(q, c.newprog) 734 q.As = AMOVD 735 q.From.Type = obj.TYPE_MEM 736 q.From.Reg = REGG 737 q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) 738 q.To.Type = obj.TYPE_REG 739 q.To.Reg = REGRT1 740 741 742 cbnz := obj.Appendp(q, c.newprog) 743 cbnz.As = ACBNZ 744 cbnz.From.Type = obj.TYPE_REG 745 cbnz.From.Reg = REGRT1 746 cbnz.To.Type = obj.TYPE_BRANCH 747 748 749 end := obj.Appendp(cbnz, c.newprog) 750 end.As = obj.ANOP 751 752 753 var last *obj.Prog 754 for last = end; last.Link != nil; last = last.Link { 755 } 756 757 758 mov := obj.Appendp(last, c.newprog) 759 mov.As = AMOVD 760 mov.From.Type = obj.TYPE_MEM 761 mov.From.Reg = REGRT1 762 mov.From.Offset = 0 763 mov.To.Type = obj.TYPE_REG 764 mov.To.Reg = REGRT2 765 766 767 cbnz.To.SetTarget(mov) 768 769 770 q = obj.Appendp(mov, c.newprog) 771 q.As = AADD 772 q.From.Type = obj.TYPE_CONST 773 q.From.Offset = int64(c.autosize) + 8 774 q.Reg = REGSP 775 q.To.Type = obj.TYPE_REG 776 q.To.Reg = REG_R20 777 778 779 q = obj.Appendp(q, c.newprog) 780 q.As = ACMP 781 q.From.Type = obj.TYPE_REG 782 q.From.Reg = REGRT2 783 q.Reg = REG_R20 784 785 786 q = obj.Appendp(q, c.newprog) 787 q.As = ABNE 788 q.To.Type = obj.TYPE_BRANCH 789 q.To.SetTarget(end) 790 791 792 q = obj.Appendp(q, c.newprog) 793 q.As = AADD 794 q.From.Type = obj.TYPE_CONST 795 q.From.Offset = 8 796 q.Reg = REGSP 797 q.To.Type = obj.TYPE_REG 798 q.To.Reg = REG_R20 799 800 801 q = obj.Appendp(q, c.newprog) 802 q.As = AMOVD 803 q.From.Type = obj.TYPE_REG 804 q.From.Reg = REG_R20 805 q.To.Type = obj.TYPE_MEM 806 q.To.Reg = REGRT1 807 q.To.Offset = 0 808 809 810 q = obj.Appendp(q, c.newprog) 811 q.As = AB 812 q.To.Type = obj.TYPE_BRANCH 813 q.To.SetTarget(end) 814 } 815 816 case obj.ARET: 817 nocache(p) 818 if p.From.Type == obj.TYPE_CONST { 819 c.ctxt.Diag("using BECOME (%v) is not supported!", p) 820 break 821 } 822 823 retjmp = p.To.Sym 824 p.To = obj.Addr{} 825 if c.cursym.Func().Text.Mark&LEAF != 0 { 826 if c.autosize != 0 { 827 p.As = AADD 828 p.From.Type = obj.TYPE_CONST 829 p.From.Offset = int64(c.autosize) 830 p.To.Type = obj.TYPE_REG 831 p.To.Reg = REGSP 832 p.Spadj = -c.autosize 833 834 835 p = obj.Appendp(p, c.newprog) 836 p.As = ASUB 837 p.From.Type = obj.TYPE_CONST 838 p.From.Offset = 8 839 p.Reg = REGSP 840 p.To.Type = obj.TYPE_REG 841 p.To.Reg = REGFP 842 } 843 } else { 844 aoffset := c.autosize 845 846 p.As = ALDP 847 p.From.Type = obj.TYPE_MEM 848 p.From.Offset = -8 849 p.From.Reg = REGSP 850 p.To.Type = obj.TYPE_REGREG 851 p.To.Reg = REGFP 852 p.To.Offset = REGLINK 853 854 855 q = newprog() 856 q.As = AADD 857 q.From.Type = obj.TYPE_CONST 858 q.From.Offset = int64(aoffset) 859 q.To.Type = obj.TYPE_REG 860 q.To.Reg = REGSP 861 q.Spadj = -aoffset 862 q.Pos = p.Pos 863 q.Link = p.Link 864 p.Link = q 865 p = q 866 } 867 868 869 870 871 872 873 const debugRETZERO = false 874 if debugRETZERO { 875 if p.As != obj.ARET { 876 q = newprog() 877 q.Pos = p.Pos 878 q.Link = p.Link 879 p.Link = q 880 p = q 881 } 882 p.As = AADR 883 p.From.Type = obj.TYPE_BRANCH 884 p.From.Offset = 0 885 p.To.Type = obj.TYPE_REG 886 p.To.Reg = REGTMP 887 888 } 889 890 if p.As != obj.ARET { 891 q = newprog() 892 q.Pos = p.Pos 893 q.Link = p.Link 894 p.Link = q 895 p = q 896 } 897 898 if retjmp != nil { 899 p.As = AB 900 p.To.Type = obj.TYPE_BRANCH 901 p.To.Sym = retjmp 902 p.Spadj = +c.autosize 903 break 904 } 905 906 p.As = obj.ARET 907 p.To.Type = obj.TYPE_MEM 908 p.To.Offset = 0 909 p.To.Reg = REGLINK 910 p.Spadj = +c.autosize 911 912 case AADD, ASUB: 913 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST { 914 if p.As == AADD { 915 p.Spadj = int32(-p.From.Offset) 916 } else { 917 p.Spadj = int32(+p.From.Offset) 918 } 919 } 920 921 case obj.AGETCALLERPC: 922 if cursym.Leaf() { 923 924 p.As = AMOVD 925 p.From.Type = obj.TYPE_REG 926 p.From.Reg = REGLINK 927 } else { 928 929 p.As = AMOVD 930 p.From.Type = obj.TYPE_MEM 931 p.From.Reg = REGSP 932 } 933 934 case obj.ADUFFCOPY: 935 936 937 938 939 940 941 942 q1 := p 943 944 q4 := obj.Appendp(p, c.newprog) 945 q4.Pos = p.Pos 946 q4.As = obj.ADUFFCOPY 947 q4.To = p.To 948 949 q1.As = AADR 950 q1.From.Type = obj.TYPE_BRANCH 951 q1.To.Type = obj.TYPE_REG 952 q1.To.Reg = REG_R27 953 954 q2 := obj.Appendp(q1, c.newprog) 955 q2.Pos = p.Pos 956 q2.As = ASTP 957 q2.From.Type = obj.TYPE_REGREG 958 q2.From.Reg = REGFP 959 q2.From.Offset = int64(REG_R27) 960 q2.To.Type = obj.TYPE_MEM 961 q2.To.Reg = REGSP 962 q2.To.Offset = -24 963 964 965 q3 := obj.Appendp(q2, c.newprog) 966 q3.Pos = p.Pos 967 q3.As = ASUB 968 q3.From.Type = obj.TYPE_CONST 969 q3.From.Offset = 24 970 q3.Reg = REGSP 971 q3.To.Type = obj.TYPE_REG 972 q3.To.Reg = REGFP 973 974 q5 := obj.Appendp(q4, c.newprog) 975 q5.Pos = p.Pos 976 q5.As = ASUB 977 q5.From.Type = obj.TYPE_CONST 978 q5.From.Offset = 8 979 q5.Reg = REGSP 980 q5.To.Type = obj.TYPE_REG 981 q5.To.Reg = REGFP 982 q1.From.SetTarget(q5) 983 p = q5 984 985 case obj.ADUFFZERO: 986 987 988 989 990 991 992 993 q1 := p 994 995 q4 := obj.Appendp(p, c.newprog) 996 q4.Pos = p.Pos 997 q4.As = obj.ADUFFZERO 998 q4.To = p.To 999 1000 q1.As = AADR 1001 q1.From.Type = obj.TYPE_BRANCH 1002 q1.To.Type = obj.TYPE_REG 1003 q1.To.Reg = REG_R27 1004 1005 q2 := obj.Appendp(q1, c.newprog) 1006 q2.Pos = p.Pos 1007 q2.As = ASTP 1008 q2.From.Type = obj.TYPE_REGREG 1009 q2.From.Reg = REGFP 1010 q2.From.Offset = int64(REG_R27) 1011 q2.To.Type = obj.TYPE_MEM 1012 q2.To.Reg = REGSP 1013 q2.To.Offset = -24 1014 1015 1016 q3 := obj.Appendp(q2, c.newprog) 1017 q3.Pos = p.Pos 1018 q3.As = ASUB 1019 q3.From.Type = obj.TYPE_CONST 1020 q3.From.Offset = 24 1021 q3.Reg = REGSP 1022 q3.To.Type = obj.TYPE_REG 1023 q3.To.Reg = REGFP 1024 1025 q5 := obj.Appendp(q4, c.newprog) 1026 q5.Pos = p.Pos 1027 q5.As = ASUB 1028 q5.From.Type = obj.TYPE_CONST 1029 q5.From.Offset = 8 1030 q5.Reg = REGSP 1031 q5.To.Type = obj.TYPE_REG 1032 q5.To.Reg = REGFP 1033 q1.From.SetTarget(q5) 1034 p = q5 1035 } 1036 1037 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 { 1038 f := c.cursym.Func() 1039 if f.FuncFlag&abi.FuncFlagSPWrite == 0 { 1040 c.cursym.Func().FuncFlag |= abi.FuncFlagSPWrite 1041 if ctxt.Debugvlog || !ctxt.IsAsm { 1042 ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p) 1043 if !ctxt.IsAsm { 1044 ctxt.Diag("invalid auto-SPWRITE in non-assembly") 1045 ctxt.DiagFlush() 1046 log.Fatalf("bad SPWRITE") 1047 } 1048 } 1049 } 1050 } 1051 if p.From.Type == obj.TYPE_SHIFT && (p.To.Reg == REG_RSP || p.Reg == REG_RSP) { 1052 offset := p.From.Offset 1053 op := offset & (3 << 22) 1054 if op != SHIFT_LL { 1055 ctxt.Diag("illegal combination: %v", p) 1056 } 1057 r := (offset >> 16) & 31 1058 shift := (offset >> 10) & 63 1059 if shift > 4 { 1060 1061 1062 1063 shift = 7 1064 } 1065 p.From.Type = obj.TYPE_REG 1066 p.From.Reg = int16(REG_LSL + r + (shift&7)<<5) 1067 p.From.Offset = 0 1068 } 1069 } 1070 } 1071 1072 func nocache(p *obj.Prog) { 1073 p.Optab = 0 1074 p.From.Class = 0 1075 p.To.Class = 0 1076 } 1077 1078 var unaryDst = map[obj.As]bool{ 1079 AWORD: true, 1080 ADWORD: true, 1081 ABL: true, 1082 AB: true, 1083 ACLREX: true, 1084 } 1085 1086 var Linkarm64 = obj.LinkArch{ 1087 Arch: sys.ArchARM64, 1088 Init: buildop, 1089 Preprocess: preprocess, 1090 Assemble: span7, 1091 Progedit: progedit, 1092 UnaryDst: unaryDst, 1093 DWARFRegisters: ARM64DWARFRegisters, 1094 }