@@ -486,6 +486,116 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
486
486
}
487
487
}
488
488
489
+ // Split immediates larger than 12-bits.
490
+ for p := cursym .Func .Text ; p != nil ; p = p .Link {
491
+ switch p .As {
492
+ // <opi> $imm, REG, TO
493
+ case AADDI , AANDI , AORI , AXORI :
494
+ // LUI $high, TMP
495
+ // ADDI $low, TMP, TMP
496
+ // <op> TMP, REG, TO
497
+ q := * p
498
+ low , high , err := Split32BitImmediate (p .From .Offset )
499
+ if err != nil {
500
+ ctxt .Diag ("%v: constant %d too large" , p , p .From .Offset , err )
501
+ }
502
+ if high == 0 {
503
+ break // no need to split
504
+ }
505
+
506
+ p .As = ALUI
507
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : high }
508
+ p .Reg = 0
509
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
510
+ p .Spadj = 0 // needed if TO is SP
511
+ p = obj .Appendp (p , newprog )
512
+
513
+ p .As = AADDIW
514
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : low }
515
+ p .Reg = REG_TMP
516
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
517
+ p = obj .Appendp (p , newprog )
518
+
519
+ switch q .As {
520
+ case AADDI :
521
+ p .As = AADD
522
+ case AANDI :
523
+ p .As = AAND
524
+ case AORI :
525
+ p .As = AOR
526
+ case AXORI :
527
+ p .As = AXOR
528
+ default :
529
+ ctxt .Diag ("progedit: unsupported inst %v for splitting" , q )
530
+ }
531
+ p .Spadj = q .Spadj
532
+ p .To = q .To
533
+ p .Reg = q .Reg
534
+ p .From = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
535
+
536
+ // <load> $imm, REG, TO (load $imm+(REG), TO)
537
+ // <store> $imm, REG, TO (store $imm+(TO), REG)
538
+ case ALD , ALB , ALH , ALW , ALBU , ALHU , ALWU ,
539
+ ASD , ASB , ASH , ASW :
540
+ // LUI $high, TMP
541
+ // ADDI $low, TMP, TMP
542
+ q := * p
543
+ low , high , err := Split32BitImmediate (p .From .Offset )
544
+ if err != nil {
545
+ ctxt .Diag ("%v: constant %d too large" , p , p .From .Offset )
546
+ }
547
+ if high == 0 {
548
+ break // no need to split
549
+ }
550
+
551
+ switch q .As {
552
+ case ALD , ALB , ALH , ALW , ALBU , ALHU , ALWU :
553
+ // LUI $high, TMP
554
+ // ADD TMP, REG, TMP
555
+ // <load> $low, TMP, TO
556
+ p .As = ALUI
557
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : high }
558
+ p .Reg = 0
559
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
560
+ p .Spadj = 0 // needed if TO is SP
561
+ p = obj .Appendp (p , newprog )
562
+
563
+ p .As = AADD
564
+ p .From = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
565
+ p .Reg = q .Reg
566
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
567
+ p = obj .Appendp (p , newprog )
568
+
569
+ p .As = q .As
570
+ p .To = q .To
571
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : low }
572
+ p .Reg = REG_TMP
573
+
574
+ case ASD , ASB , ASH , ASW :
575
+ // LUI $high, TMP
576
+ // ADD TMP, TO, TMP
577
+ // <store> $low, REG, TMP
578
+ p .As = ALUI
579
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : high }
580
+ p .Reg = 0
581
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
582
+ p .Spadj = 0 // needed if TO is SP
583
+ p = obj .Appendp (p , newprog )
584
+
585
+ p .As = AADD
586
+ p .From = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
587
+ p .Reg = q .To .Reg
588
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
589
+ p = obj .Appendp (p , newprog )
590
+
591
+ p .As = q .As
592
+ p .Reg = q .Reg
593
+ p .To = obj.Addr {Type : obj .TYPE_REG , Reg : REG_TMP }
594
+ p .From = obj.Addr {Type : obj .TYPE_CONST , Offset : low }
595
+ }
596
+ }
597
+ }
598
+
489
599
setPCs (cursym .Func .Text , 0 )
490
600
491
601
// Resolve branch and jump targets.
0 commit comments