~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/cmd/8g/ggen.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
markautoused(Prog* p)
28
28
{
29
29
        for (; p; p = p->link) {
 
30
                if (p->as == ATYPE)
 
31
                        continue;
 
32
 
30
33
                if (p->from.type == D_AUTO && p->from.node)
31
34
                        p->from.node->used = 1;
32
35
 
39
42
void
40
43
fixautoused(Prog* p)
41
44
{
42
 
        for (; p; p = p->link) {
 
45
        Prog **lp;
 
46
 
 
47
        for (lp=&p; (p=*lp) != P; ) {
 
48
                if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
 
49
                        *lp = p->link;
 
50
                        continue;
 
51
                }
 
52
 
43
53
                if (p->from.type == D_AUTO && p->from.node)
44
54
                        p->from.offset += p->from.node->stkdelta;
45
55
 
46
56
                if (p->to.type == D_AUTO && p->to.node)
47
57
                        p->to.offset += p->to.node->stkdelta;
 
58
 
 
59
                lp = &p->link;
48
60
        }
49
61
}
50
62
 
59
71
                dump("\nclearfat", nl);
60
72
 
61
73
        w = nl->type->width;
 
74
        // Avoid taking the address for simple enough types.
 
75
        if(componentgen(N, nl))
 
76
                return;
 
77
 
62
78
        c = w % 4;      // bytes
63
79
        q = w / 4;      // quads
64
80
 
65
 
        gconreg(AMOVL, 0, D_AX);
66
81
        nodreg(&n1, types[tptr], D_DI);
67
82
        agen(nl, &n1);
 
83
        gconreg(AMOVL, 0, D_AX);
68
84
 
69
85
        if(q >= 4) {
70
86
                gconreg(AMOVL, q, D_CX);
90
106
/*
91
107
 * generate:
92
108
 *      call f
 
109
 *      proc=-1 normal call but no return
93
110
 *      proc=0  normal call
94
111
 *      proc=1  goroutine run in new proc
95
112
 *      proc=2  defer call save away stack
 
113
  *     proc=3  normal call to C pointer (not Go func value)
96
114
 */
97
115
void
98
116
ginscall(Node *f, int proc)
99
117
{
100
118
        Prog *p;
101
 
        Node reg, con;
 
119
        Node reg, r1, con;
102
120
 
103
121
        switch(proc) {
104
122
        default:
106
124
                break;
107
125
 
108
126
        case 0: // normal call
109
 
                p = gins(ACALL, N, f);
110
 
                afunclit(&p->to);
 
127
        case -1:        // normal call but no return
 
128
                if(f->op == ONAME && f->class == PFUNC) {
 
129
                        p = gins(ACALL, N, f);
 
130
                        afunclit(&p->to, f);
 
131
                        if(proc == -1 || noreturn(p))
 
132
                                gins(AUNDEF, N, N);
 
133
                        break;
 
134
                }
 
135
                nodreg(&reg, types[tptr], D_DX);
 
136
                nodreg(&r1, types[tptr], D_BX);
 
137
                gmove(f, &reg);
 
138
                reg.op = OINDREG;
 
139
                gmove(&reg, &r1);
 
140
                reg.op = OREGISTER;
 
141
                gins(ACALL, &reg, &r1);
 
142
                break;
 
143
        
 
144
        case 3: // normal call of c function pointer
 
145
                gins(ACALL, N, f);
111
146
                break;
112
147
 
113
148
        case 1: // call in new proc (go)
125
160
                if(proc == 2) {
126
161
                        nodreg(&reg, types[TINT64], D_AX);
127
162
                        gins(ATESTL, &reg, &reg);
128
 
                        patch(gbranch(AJNE, T), retpc);
 
163
                        patch(gbranch(AJNE, T, -1), retpc);
129
164
                }
130
165
                break;
131
166
        }
139
174
cgen_callinter(Node *n, Node *res, int proc)
140
175
{
141
176
        Node *i, *f;
142
 
        Node tmpi, nodo, nodr, nodsp;
 
177
        Node tmpi, nodi, nodo, nodr, nodsp;
143
178
 
144
179
        i = n->left;
145
180
        if(i->op != ODOTINTER)
159
194
 
160
195
        genlist(n->list);               // assign the args
161
196
 
162
 
        // Can regalloc now; i is known to be addable,
163
 
        // so the agen will be easy.
164
 
        regalloc(&nodr, types[tptr], res);
165
 
        regalloc(&nodo, types[tptr], &nodr);
166
 
        nodo.op = OINDREG;
167
 
 
168
 
        agen(i, &nodr);         // REG = &inter
 
197
        // i is now addable, prepare an indirected
 
198
        // register to hold its address.
 
199
        igen(i, &nodi, res);            // REG = &inter
169
200
 
170
201
        nodindreg(&nodsp, types[tptr], D_SP);
171
 
        nodo.xoffset += widthptr;
172
 
        cgen(&nodo, &nodsp);    // 0(SP) = 4(REG) -- i.data
173
 
 
174
 
        nodo.xoffset -= widthptr;
175
 
        cgen(&nodo, &nodr);     // REG = 0(REG) -- i.tab
176
 
 
 
202
        nodi.type = types[tptr];
 
203
        nodi.xoffset += widthptr;
 
204
        cgen(&nodi, &nodsp);    // 0(SP) = 4(REG) -- i.data
 
205
 
 
206
        regalloc(&nodo, types[tptr], res);
 
207
        nodi.type = types[tptr];
 
208
        nodi.xoffset -= widthptr;
 
209
        cgen(&nodi, &nodo);     // REG = 0(REG) -- i.tab
 
210
        regfree(&nodi);
 
211
 
 
212
        regalloc(&nodr, types[tptr], &nodo);
177
213
        if(n->left->xoffset == BADWIDTH)
178
214
                fatal("cgen_callinter: badwidth");
 
215
        nodo.op = OINDREG;
179
216
        nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
180
 
        cgen(&nodo, &nodr);     // REG = 20+offset(REG) -- i.tab->fun[f]
 
217
        
 
218
        if(proc == 0) {
 
219
                // plain call: use direct c function pointer - more efficient
 
220
                cgen(&nodo, &nodr);     // REG = 20+offset(REG) -- i.tab->fun[f]
 
221
                proc = 3;
 
222
        } else {
 
223
                // go/defer. generate go func value.
 
224
                gins(ALEAL, &nodo, &nodr);      // REG = &(20+offset(REG)) -- i.tab->fun[f]
 
225
        }
181
226
 
182
227
        // BOTCH nodr.type = fntype;
183
228
        nodr.type = n->left->type;
486
531
        int check;
487
532
        Node n1, t1, t2, t3, t4, n4, nz;
488
533
        Type *t, *t0;
489
 
        Prog *p1, *p2, *p3;
 
534
        Prog *p1, *p2;
490
535
 
491
536
        // Have to be careful about handling
492
537
        // most negative int divided by -1 correctly.
535
580
                regalloc(&n1, t, N);
536
581
        gmove(&t2, &n1);
537
582
        gmove(&t1, ax);
538
 
        p3 = P;
 
583
        p2 = P;
539
584
        if(check) {
540
585
                nodconst(&n4, t, -1);
541
586
                gins(optoas(OCMP, t), &n1, &n4);
542
 
                p1 = gbranch(optoas(ONE, t), T);
543
 
                nodconst(&n4, t, -1LL<<(t->width*8-1));
544
 
                gins(optoas(OCMP, t), ax, &n4);
545
 
                p2 = gbranch(optoas(ONE, t), T);
546
 
                if(op == ODIV)
547
 
                        gmove(&n4, res);
548
 
                if(op == OMOD) {
 
587
                p1 = gbranch(optoas(ONE, t), T, +1);
 
588
                if(op == ODIV) {
 
589
                        // a / (-1) is -a.
 
590
                        gins(optoas(OMINUS, t), N, ax);
 
591
                        gmove(ax, res);
 
592
                } else {
 
593
                        // a % (-1) is 0.
549
594
                        nodconst(&n4, t, 0);
550
595
                        gmove(&n4, res);
551
596
                }
552
 
                p3 = gbranch(AJMP, T);
 
597
                p2 = gbranch(AJMP, T, 0);
553
598
                patch(p1, pc);
554
 
                patch(p2, pc);
555
599
        }
556
600
        if(!issigned[t->etype]) {
557
601
                nodconst(&nz, t, 0);
566
610
        else
567
611
                gmove(dx, res);
568
612
        if(check)
569
 
                patch(p3, pc);
 
613
                patch(p2, pc);
570
614
}
571
615
 
572
616
static void
630
674
 *      res = nl >> nr
631
675
 */
632
676
void
633
 
cgen_shift(int op, Node *nl, Node *nr, Node *res)
 
677
cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
634
678
{
635
679
        Node n1, n2, nt, cx, oldcx, hi, lo;
636
680
        int a, w;
651
695
                gmove(&n2, &n1);
652
696
                sc = mpgetfix(nr->val.u.xval);
653
697
                if(sc >= nl->type->width*8) {
654
 
                        // large shift gets 2 shifts by width
 
698
                        // large shift gets 2 shifts by width-1
655
699
                        gins(a, ncon(w-1), &n1);
656
700
                        gins(a, ncon(w-1), &n1);
657
701
                } else
689
733
        }
690
734
 
691
735
        // test and fix up large shifts
692
 
        if(nr->type->width > 4) {
693
 
                // delayed reg alloc
694
 
                nodreg(&n1, types[TUINT32], D_CX);
695
 
                regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
696
 
                split64(&nt, &lo, &hi);
697
 
                gmove(&lo, &n1);
698
 
                gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
699
 
                p2 = gbranch(optoas(ONE, types[TUINT32]), T);
700
 
                gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
701
 
                p1 = gbranch(optoas(OLT, types[TUINT32]), T);
702
 
                patch(p2, pc);
703
 
        } else {
704
 
                gins(optoas(OCMP, nr->type), &n1, ncon(w));
705
 
                p1 = gbranch(optoas(OLT, types[TUINT32]), T);
706
 
        }
707
 
        if(op == ORSH && issigned[nl->type->etype]) {
708
 
                gins(a, ncon(w-1), &n2);
709
 
        } else {
710
 
                gmove(ncon(0), &n2);
711
 
        }
712
 
        patch(p1, pc);
 
736
        if(bounded) {
 
737
                if(nr->type->width > 4) {
 
738
                        // delayed reg alloc
 
739
                        nodreg(&n1, types[TUINT32], D_CX);
 
740
                        regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
 
741
                        split64(&nt, &lo, &hi);
 
742
                        gmove(&lo, &n1);
 
743
                        splitclean();
 
744
                }
 
745
        } else {
 
746
                if(nr->type->width > 4) {
 
747
                        // delayed reg alloc
 
748
                        nodreg(&n1, types[TUINT32], D_CX);
 
749
                        regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
 
750
                        split64(&nt, &lo, &hi);
 
751
                        gmove(&lo, &n1);
 
752
                        gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
 
753
                        p2 = gbranch(optoas(ONE, types[TUINT32]), T, +1);
 
754
                        gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
 
755
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 
756
                        splitclean();
 
757
                        patch(p2, pc);
 
758
                } else {
 
759
                        gins(optoas(OCMP, nr->type), &n1, ncon(w));
 
760
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 
761
                }
 
762
                if(op == ORSH && issigned[nl->type->etype]) {
 
763
                        gins(a, ncon(w-1), &n2);
 
764
                } else {
 
765
                        gmove(ncon(0), &n2);
 
766
                }
 
767
                patch(p1, pc);
 
768
        }
713
769
        gins(a, &n1, &n2);
714
770
 
715
771
        if(oldcx.op != 0)
724
780
/*
725
781
 * generate byte multiply:
726
782
 *      res = nl * nr
727
 
 * no byte multiply instruction so have to do
728
 
 * 16-bit multiply and take bottom half.
 
783
 * there is no 2-operand byte multiply instruction so
 
784
 * we do a full-width multiplication and truncate afterwards.
729
785
 */
730
786
void
731
787
cgen_bmul(int op, Node *nl, Node *nr, Node *res)
732
788
{
733
 
        Node n1b, n2b, n1w, n2w;
 
789
        Node n1, n2, nt, *tmp;
734
790
        Type *t;
735
791
        int a;
736
792
 
737
 
        if(nl->ullman >= nr->ullman) {
738
 
                regalloc(&n1b, nl->type, res);
739
 
                cgen(nl, &n1b);
740
 
                regalloc(&n2b, nr->type, N);
741
 
                cgen(nr, &n2b);
742
 
        } else {
743
 
                regalloc(&n2b, nr->type, N);
744
 
                cgen(nr, &n2b);
745
 
                regalloc(&n1b, nl->type, res);
746
 
                cgen(nl, &n1b);
 
793
        // copy from byte to full registers
 
794
        t = types[TUINT32];
 
795
        if(issigned[nl->type->etype])
 
796
                t = types[TINT32];
 
797
 
 
798
        // largest ullman on left.
 
799
        if(nl->ullman < nr->ullman) {
 
800
                tmp = nl;
 
801
                nl = nr;
 
802
                nr = tmp;
747
803
        }
748
804
 
749
 
        // copy from byte to short registers
750
 
        t = types[TUINT16];
751
 
        if(issigned[nl->type->etype])
752
 
                t = types[TINT16];
753
 
 
754
 
        regalloc(&n2w, t, &n2b);
755
 
        cgen(&n2b, &n2w);
756
 
 
757
 
        regalloc(&n1w, t, &n1b);
758
 
        cgen(&n1b, &n1w);
759
 
 
 
805
        tempname(&nt, nl->type);
 
806
        cgen(nl, &nt);
 
807
        regalloc(&n1, t, res);
 
808
        cgen(nr, &n1);
 
809
        regalloc(&n2, t, N);
 
810
        gmove(&nt, &n2);
760
811
        a = optoas(op, t);
761
 
        gins(a, &n2w, &n1w);
762
 
        cgen(&n1w, &n1b);
763
 
        cgen(&n1b, res);
764
 
 
765
 
        regfree(&n1w);
766
 
        regfree(&n2w);
767
 
        regfree(&n1b);
768
 
        regfree(&n2b);
769
 
}
770
 
 
771
 
static int
772
 
regcmp(const void *va, const void *vb)
773
 
{
774
 
        Node *ra, *rb;
775
 
 
776
 
        ra = (Node*)va;
777
 
        rb = (Node*)vb;
778
 
        return ra->local - rb->local;
779
 
}
780
 
 
781
 
static  Prog*   throwpc;
782
 
 
783
 
// We're only going to bother inlining if we can
784
 
// convert all the arguments to 32 bits safely.  Can we?
785
 
static int
786
 
fix64(NodeList *nn, int n)
787
 
{
788
 
        NodeList *l;
789
 
        Node *r;
790
 
        int i;
791
 
        
792
 
        l = nn;
793
 
        for(i=0; i<n; i++) {
794
 
                r = l->n->right;
795
 
                if(is64(r->type) && !smallintconst(r)) {
796
 
                        if(r->op == OCONV)
797
 
                                r = r->left;
798
 
                        if(is64(r->type))
799
 
                                return 0;
800
 
                }
801
 
                l = l->next;
802
 
        }
803
 
        return 1;
804
 
}
805
 
 
806
 
void
807
 
getargs(NodeList *nn, Node *reg, int n)
808
 
{
809
 
        NodeList *l;
810
 
        Node *r;
811
 
        int i;
812
 
 
813
 
        throwpc = nil;
814
 
 
815
 
        l = nn;
816
 
        for(i=0; i<n; i++) {
817
 
                r = l->n->right;
818
 
                if(is64(r->type)) {
819
 
                        if(r->op == OCONV)
820
 
                                r = r->left;
821
 
                        else if(smallintconst(r))
822
 
                                r->type = types[TUINT32];
823
 
                        if(is64(r->type))
824
 
                                fatal("getargs");
825
 
                }
826
 
                if(!smallintconst(r) && !isslice(r->type)) {
827
 
                        if(i < 3)       // AX CX DX
828
 
                                nodreg(reg+i, r->type, D_AX+i);
829
 
                        else
830
 
                                reg[i].op = OXXX;
831
 
                        regalloc(reg+i, r->type, reg+i);
832
 
                        cgen(r, reg+i);
833
 
                } else
834
 
                        reg[i] = *r;
835
 
                if(reg[i].local != 0)
836
 
                        yyerror("local used");
837
 
                reg[i].local = l->n->left->xoffset;
838
 
                l = l->next;
839
 
        }
840
 
        qsort((void*)reg, n, sizeof(*reg), regcmp);
841
 
        for(i=0; i<n; i++)
842
 
                reg[i].local = 0;
843
 
}
844
 
 
845
 
void
846
 
cmpandthrow(Node *nl, Node *nr)
847
 
{
848
 
        vlong cl;
849
 
        Prog *p1;
850
 
        int op;
851
 
        Node *c, n1;
 
812
        gins(a, &n2, &n1);
 
813
        regfree(&n2);
 
814
        gmove(&n1, res);
 
815
        regfree(&n1);
 
816
}
 
817
 
 
818
/*
 
819
 * generate high multiply:
 
820
 *   res = (nl*nr) >> width
 
821
 */
 
822
void
 
823
cgen_hmul(Node *nl, Node *nr, Node *res)
 
824
{
852
825
        Type *t;
853
 
 
854
 
        op = OLE;
855
 
        if(smallintconst(nl)) {
856
 
                cl = mpgetfix(nl->val.u.xval);
857
 
                if(cl == 0)
858
 
                        return;
859
 
                if(smallintconst(nr))
860
 
                        return;
861
 
                // put the constant on the right
862
 
                op = brrev(op);
863
 
                c = nl;
 
826
        int a;
 
827
        Node n1, n2, ax, dx;
 
828
 
 
829
        t = nl->type;
 
830
        a = optoas(OHMUL, t);
 
831
        // gen nl in n1.
 
832
        tempname(&n1, t);
 
833
        cgen(nl, &n1);
 
834
        // gen nr in n2.
 
835
        regalloc(&n2, t, res);
 
836
        cgen(nr, &n2);
 
837
 
 
838
        // multiply.
 
839
        nodreg(&ax, t, D_AX);
 
840
        gmove(&n2, &ax);
 
841
        gins(a, &n1, N);
 
842
        regfree(&n2);
 
843
 
 
844
        if(t->width == 1) {
 
845
                // byte multiply behaves differently.
 
846
                nodreg(&ax, t, D_AH);
 
847
                nodreg(&dx, t, D_DL);
 
848
                gmove(&ax, &dx);
 
849
        }
 
850
        nodreg(&dx, t, D_DX);
 
851
        gmove(&dx, res);
 
852
}
 
853
 
 
854
static void cgen_float387(Node *n, Node *res);
 
855
static void cgen_floatsse(Node *n, Node *res);
 
856
 
 
857
/*
 
858
 * generate floating-point operation.
 
859
 */
 
860
void
 
861
cgen_float(Node *n, Node *res)
 
862
{
 
863
        Node *nl;
 
864
        Node n1, n2;
 
865
        Prog *p1, *p2, *p3;
 
866
 
 
867
        nl = n->left;
 
868
        switch(n->op) {
 
869
        case OEQ:
 
870
        case ONE:
 
871
        case OLT:
 
872
        case OLE:
 
873
        case OGE:
 
874
                p1 = gbranch(AJMP, T, 0);
 
875
                p2 = pc;
 
876
                gmove(nodbool(1), res);
 
877
                p3 = gbranch(AJMP, T, 0);
 
878
                patch(p1, pc);
 
879
                bgen(n, 1, 0, p2);
 
880
                gmove(nodbool(0), res);
 
881
                patch(p3, pc);
 
882
                return;
 
883
 
 
884
        case OPLUS:
 
885
                cgen(nl, res);
 
886
                return;
 
887
 
 
888
        case OCONV:
 
889
                if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
 
890
                        cgen(nl, res);
 
891
                        return;
 
892
                }
 
893
 
 
894
                tempname(&n2, n->type);
 
895
                mgen(nl, &n1, res);
 
896
                gmove(&n1, &n2);
 
897
                gmove(&n2, res);
 
898
                mfree(&n1);
 
899
                return;
 
900
        }
 
901
 
 
902
        if(use_sse)
 
903
                cgen_floatsse(n, res);
 
904
        else
 
905
                cgen_float387(n, res);
 
906
}
 
907
 
 
908
// floating-point.  387 (not SSE2)
 
909
static void
 
910
cgen_float387(Node *n, Node *res)
 
911
{
 
912
        Node f0, f1;
 
913
        Node *nl, *nr;
 
914
 
 
915
        nl = n->left;
 
916
        nr = n->right;
 
917
        nodreg(&f0, nl->type, D_F0);
 
918
        nodreg(&f1, n->type, D_F0+1);
 
919
        if(nr != N)
 
920
                goto flt2;
 
921
 
 
922
        // unary
 
923
        cgen(nl, &f0);
 
924
        if(n->op != OCONV && n->op != OPLUS)
 
925
                gins(foptoas(n->op, n->type, 0), N, N);
 
926
        gmove(&f0, res);
 
927
        return;
 
928
 
 
929
flt2:   // binary
 
930
        if(nl->ullman >= nr->ullman) {
 
931
                cgen(nl, &f0);
 
932
                if(nr->addable)
 
933
                        gins(foptoas(n->op, n->type, 0), nr, &f0);
 
934
                else {
 
935
                        cgen(nr, &f0);
 
936
                        gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
 
937
                }
 
938
        } else {
 
939
                cgen(nr, &f0);
 
940
                if(nl->addable)
 
941
                        gins(foptoas(n->op, n->type, Frev), nl, &f0);
 
942
                else {
 
943
                        cgen(nl, &f0);
 
944
                        gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
 
945
                }
 
946
        }
 
947
        gmove(&f0, res);
 
948
        return;
 
949
 
 
950
}
 
951
 
 
952
static void
 
953
cgen_floatsse(Node *n, Node *res)
 
954
{
 
955
        Node *nl, *nr, *r;
 
956
        Node n1, n2, nt;
 
957
        int a;
 
958
 
 
959
        nl = n->left;
 
960
        nr = n->right;
 
961
        switch(n->op) {
 
962
        default:
 
963
                dump("cgen_floatsse", n);
 
964
                fatal("cgen_floatsse %O", n->op);
 
965
                return;
 
966
 
 
967
        case OMINUS:
 
968
        case OCOM:
 
969
                nr = nodintconst(-1);
 
970
                convlit(&nr, n->type);
 
971
                a = foptoas(OMUL, nl->type, 0);
 
972
                goto sbop;
 
973
 
 
974
        // symmetric binary
 
975
        case OADD:
 
976
        case OMUL:
 
977
                a = foptoas(n->op, nl->type, 0);
 
978
                goto sbop;
 
979
 
 
980
        // asymmetric binary
 
981
        case OSUB:
 
982
        case OMOD:
 
983
        case ODIV:
 
984
                a = foptoas(n->op, nl->type, 0);
 
985
                goto abop;
 
986
        }
 
987
 
 
988
sbop:   // symmetric binary
 
989
        if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
 
990
                r = nl;
864
991
                nl = nr;
865
 
                nr = c;
866
 
        }
867
 
        
868
 
        // Arguments are known not to be 64-bit,
869
 
        // but they might be smaller than 32 bits.
870
 
        // Check if we need to use a temporary.
871
 
        // At least one of the arguments is 32 bits
872
 
        // (the len or cap) so one temporary suffices.
873
 
        n1.op = OXXX;
874
 
        t = types[TUINT32];
875
 
        if(nl->type->width != t->width) {
876
 
                regalloc(&n1, t, nl);
877
 
                gmove(nl, &n1);
 
992
                nr = r;
 
993
        }
 
994
 
 
995
abop:   // asymmetric binary
 
996
        if(nl->ullman >= nr->ullman) {
 
997
                tempname(&nt, nl->type);
 
998
                cgen(nl, &nt);
 
999
                mgen(nr, &n2, N);
 
1000
                regalloc(&n1, nl->type, res);
 
1001
                gmove(&nt, &n1);
 
1002
                gins(a, &n2, &n1);
 
1003
                gmove(&n1, res);
 
1004
                regfree(&n1);
 
1005
                mfree(&n2);
 
1006
        } else {
 
1007
                regalloc(&n2, nr->type, res);
 
1008
                cgen(nr, &n2);
 
1009
                regalloc(&n1, nl->type, N);
 
1010
                cgen(nl, &n1);
 
1011
                gins(a, &n2, &n1);
 
1012
                regfree(&n2);
 
1013
                gmove(&n1, res);
 
1014
                regfree(&n1);
 
1015
        }
 
1016
        return;
 
1017
}
 
1018
 
 
1019
void
 
1020
bgen_float(Node *n, int true, int likely, Prog *to)
 
1021
{
 
1022
        int et, a;
 
1023
        Node *nl, *nr, *r;
 
1024
        Node n1, n2, n3, tmp, t1, t2, ax;
 
1025
        Prog *p1, *p2;
 
1026
 
 
1027
        nl = n->left;
 
1028
        nr = n->right;
 
1029
        a = n->op;
 
1030
        if(!true) {
 
1031
                // brcom is not valid on floats when NaN is involved.
 
1032
                p1 = gbranch(AJMP, T, 0);
 
1033
                p2 = gbranch(AJMP, T, 0);
 
1034
                patch(p1, pc);
 
1035
                // No need to avoid re-genning ninit.
 
1036
                bgen_float(n, 1, -likely, p2);
 
1037
                patch(gbranch(AJMP, T, 0), to);
 
1038
                patch(p2, pc);
 
1039
                return;
 
1040
        }
 
1041
 
 
1042
        if(use_sse)
 
1043
                goto sse;
 
1044
        else
 
1045
                goto x87;
 
1046
 
 
1047
x87:
 
1048
        a = brrev(a);   // because the args are stacked
 
1049
        if(a == OGE || a == OGT) {
 
1050
                // only < and <= work right with NaN; reverse if needed
 
1051
                r = nr;
 
1052
                nr = nl;
 
1053
                nl = r;
 
1054
                a = brrev(a);
 
1055
        }
 
1056
 
 
1057
        nodreg(&tmp, nr->type, D_F0);
 
1058
        nodreg(&n2, nr->type, D_F0 + 1);
 
1059
        nodreg(&ax, types[TUINT16], D_AX);
 
1060
        et = simsimtype(nr->type);
 
1061
        if(et == TFLOAT64) {
 
1062
                if(nl->ullman > nr->ullman) {
 
1063
                        cgen(nl, &tmp);
 
1064
                        cgen(nr, &tmp);
 
1065
                        gins(AFXCHD, &tmp, &n2);
 
1066
                } else {
 
1067
                        cgen(nr, &tmp);
 
1068
                        cgen(nl, &tmp);
 
1069
                }
 
1070
                gins(AFUCOMIP, &tmp, &n2);
 
1071
                gins(AFMOVDP, &tmp, &tmp);      // annoying pop but still better than STSW+SAHF
 
1072
        } else {
 
1073
                // TODO(rsc): The moves back and forth to memory
 
1074
                // here are for truncating the value to 32 bits.
 
1075
                // This handles 32-bit comparison but presumably
 
1076
                // all the other ops have the same problem.
 
1077
                // We need to figure out what the right general
 
1078
                // solution is, besides telling people to use float64.
 
1079
                tempname(&t1, types[TFLOAT32]);
 
1080
                tempname(&t2, types[TFLOAT32]);
 
1081
                cgen(nr, &t1);
 
1082
                cgen(nl, &t2);
 
1083
                gmove(&t2, &tmp);
 
1084
                gins(AFCOMFP, &t1, &tmp);
 
1085
                gins(AFSTSW, N, &ax);
 
1086
                gins(ASAHF, N, N);
 
1087
        }
 
1088
 
 
1089
        goto ret;
 
1090
 
 
1091
sse:
 
1092
        if(!nl->addable) {
 
1093
                tempname(&n1, nl->type);
 
1094
                cgen(nl, &n1);
878
1095
                nl = &n1;
879
 
        } else if(nr->type->width != t->width) {
880
 
                regalloc(&n1, t, nr);
881
 
                gmove(nr, &n1);
882
 
                nr = &n1;
883
 
        }
884
 
        gins(optoas(OCMP, t), nl, nr);
885
 
        if(n1.op != OXXX)
886
 
                regfree(&n1);
887
 
        if(throwpc == nil) {
888
 
                p1 = gbranch(optoas(op, t), T);
889
 
                throwpc = pc;
890
 
                ginscall(panicslice, 0);
 
1096
        }
 
1097
        if(!nr->addable) {
 
1098
                tempname(&tmp, nr->type);
 
1099
                cgen(nr, &tmp);
 
1100
                nr = &tmp;
 
1101
        }
 
1102
        regalloc(&n2, nr->type, N);
 
1103
        gmove(nr, &n2);
 
1104
        nr = &n2;
 
1105
 
 
1106
        if(nl->op != OREGISTER) {
 
1107
                regalloc(&n3, nl->type, N);
 
1108
                gmove(nl, &n3);
 
1109
                nl = &n3;
 
1110
        }
 
1111
 
 
1112
        if(a == OGE || a == OGT) {
 
1113
                // only < and <= work right with NaN; reverse if needed
 
1114
                r = nr;
 
1115
                nr = nl;
 
1116
                nl = r;
 
1117
                a = brrev(a);
 
1118
        }
 
1119
 
 
1120
        gins(foptoas(OCMP, nr->type, 0), nl, nr);
 
1121
        if(nl->op == OREGISTER)
 
1122
                regfree(nl);
 
1123
        regfree(nr);
 
1124
 
 
1125
ret:
 
1126
        if(a == OEQ) {
 
1127
                // neither NE nor P
 
1128
                p1 = gbranch(AJNE, T, -likely);
 
1129
                p2 = gbranch(AJPS, T, -likely);
 
1130
                patch(gbranch(AJMP, T, 0), to);
891
1131
                patch(p1, pc);
892
 
        } else {
893
 
                op = brcom(op);
894
 
                p1 = gbranch(optoas(op, t), T);
895
 
                patch(p1, throwpc);
896
 
        }
897
 
}
898
 
 
899
 
int
900
 
sleasy(Node *n)
901
 
{
902
 
        if(n->op != ONAME)
903
 
                return 0;
904
 
        if(!n->addable)
905
 
                return 0;
906
 
        return 1;
907
 
}
908
 
 
909
 
// generate inline code for
910
 
//      slicearray
911
 
//      sliceslice
912
 
//      arraytoslice
913
 
int
914
 
cgen_inline(Node *n, Node *res)
915
 
{
916
 
        Node nodes[5];
917
 
        Node n1, n2, nres, ntemp;
918
 
        vlong v;
919
 
        int i, narg, nochk;
920
 
 
921
 
        if(n->op != OCALLFUNC)
922
 
                goto no;
923
 
        if(!n->left->addable)
924
 
                goto no;
925
 
        if(n->left->sym == S)
926
 
                goto no;
927
 
        if(n->left->sym->pkg != runtimepkg)
928
 
                goto no;
929
 
        if(strcmp(n->left->sym->name, "slicearray") == 0)
930
 
                goto slicearray;
931
 
        if(strcmp(n->left->sym->name, "sliceslice") == 0) {
932
 
                narg = 4;
933
 
                goto sliceslice;
934
 
        }
935
 
        if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
936
 
                narg = 3;
937
 
                goto sliceslice;
938
 
        }
939
 
        goto no;
940
 
 
941
 
slicearray:
942
 
        if(!sleasy(res))
943
 
                goto no;
944
 
        if(!fix64(n->list, 5))
945
 
                goto no;
946
 
        getargs(n->list, nodes, 5);
947
 
 
948
 
        // if(hb[3] > nel[1]) goto throw
949
 
        cmpandthrow(&nodes[3], &nodes[1]);
950
 
 
951
 
        // if(lb[2] > hb[3]) goto throw
952
 
        cmpandthrow(&nodes[2], &nodes[3]);
953
 
 
954
 
        // len = hb[3] - lb[2] (destroys hb)
955
 
        n2 = *res;
956
 
        n2.xoffset += Array_nel;
957
 
        n2.type = types[TUINT32];
958
 
 
959
 
        if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
960
 
                v = mpgetfix(nodes[3].val.u.xval) -
961
 
                        mpgetfix(nodes[2].val.u.xval);
962
 
                nodconst(&n1, types[TUINT32], v);
963
 
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
964
 
        } else {
965
 
                regalloc(&n1, types[TUINT32], &nodes[3]);
966
 
                gmove(&nodes[3], &n1);
967
 
                if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
968
 
                        gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
969
 
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
970
 
                regfree(&n1);
971
 
        }
972
 
 
973
 
        // cap = nel[1] - lb[2] (destroys nel)
974
 
        n2 = *res;
975
 
        n2.xoffset += Array_cap;
976
 
        n2.type = types[TUINT32];
977
 
 
978
 
        if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
979
 
                v = mpgetfix(nodes[1].val.u.xval) -
980
 
                        mpgetfix(nodes[2].val.u.xval);
981
 
                nodconst(&n1, types[TUINT32], v);
982
 
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
983
 
        } else {
984
 
                regalloc(&n1, types[TUINT32], &nodes[1]);
985
 
                gmove(&nodes[1], &n1);
986
 
                if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
987
 
                        gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
988
 
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
989
 
                regfree(&n1);
990
 
        }
991
 
 
992
 
        // if slice could be too big, dereference to
993
 
        // catch nil array pointer.
994
 
        if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
995
 
                n2 = nodes[0];
996
 
                n2.xoffset = 0;
997
 
                n2.op = OINDREG;
998
 
                n2.type = types[TUINT8];
999
 
                gins(ATESTB, nodintconst(0), &n2);
1000
 
        }
1001
 
 
1002
 
        // ary = old[0] + (lb[2] * width[4]) (destroys old)
1003
 
        n2 = *res;
1004
 
        n2.xoffset += Array_array;
1005
 
        n2.type = types[tptr];
1006
 
 
1007
 
        if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
1008
 
                v = mpgetfix(nodes[2].val.u.xval) *
1009
 
                        mpgetfix(nodes[4].val.u.xval);
1010
 
                if(v != 0) {
1011
 
                        nodconst(&n1, types[tptr], v);
1012
 
                        gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
1013
 
                }
1014
 
        } else {
1015
 
                regalloc(&n1, types[tptr], &nodes[2]);
1016
 
                gmove(&nodes[2], &n1);
1017
 
                if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1)
1018
 
                        gins(optoas(OMUL, types[tptr]), &nodes[4], &n1);
1019
 
                gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
1020
 
                regfree(&n1);
1021
 
        }
1022
 
        gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
1023
 
 
1024
 
        for(i=0; i<5; i++) {
1025
 
                if(nodes[i].op == OREGISTER)
1026
 
                        regfree(&nodes[i]);
1027
 
        }
1028
 
        return 1;
1029
 
 
1030
 
sliceslice:
1031
 
        if(!fix64(n->list, narg))
1032
 
                goto no;
1033
 
        nochk = n->etype;  // skip bounds checking
1034
 
        ntemp.op = OXXX;
1035
 
        if(!sleasy(n->list->n->right)) {
1036
 
                Node *n0;
1037
 
                
1038
 
                n0 = n->list->n->right;
1039
 
                tempname(&ntemp, res->type);
1040
 
                cgen(n0, &ntemp);
1041
 
                n->list->n->right = &ntemp;
1042
 
                getargs(n->list, nodes, narg);
1043
 
                n->list->n->right = n0;
 
1132
                patch(p2, pc);
 
1133
        } else if(a == ONE) {
 
1134
                // either NE or P
 
1135
                patch(gbranch(AJNE, T, likely), to);
 
1136
                patch(gbranch(AJPS, T, likely), to);
1044
1137
        } else
1045
 
                getargs(n->list, nodes, narg);
1046
 
 
1047
 
        nres = *res;            // result
1048
 
        if(!sleasy(res)) {
1049
 
                if(ntemp.op == OXXX)
1050
 
                        tempname(&ntemp, res->type);
1051
 
                nres = ntemp;
1052
 
        }
1053
 
 
1054
 
        if(narg == 3) { // old[lb:]
1055
 
                // move width to where it would be for old[lb:hb]
1056
 
                nodes[3] = nodes[2];
1057
 
                nodes[2].op = OXXX;
1058
 
                
1059
 
                // if(lb[1] > old.nel[0]) goto throw;
1060
 
                n2 = nodes[0];
1061
 
                n2.xoffset += Array_nel;
1062
 
                n2.type = types[TUINT32];
1063
 
                if(!nochk)
1064
 
                        cmpandthrow(&nodes[1], &n2);
1065
 
 
1066
 
                // ret.nel = old.nel[0]-lb[1];
1067
 
                n2 = nodes[0];
1068
 
                n2.xoffset += Array_nel;
1069
 
                n2.type = types[TUINT32];
1070
 
        
1071
 
                regalloc(&n1, types[TUINT32], N);
1072
 
                gins(optoas(OAS, types[TUINT32]), &n2, &n1);
1073
 
                if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
1074
 
                        gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
1075
 
        
1076
 
                n2 = nres;
1077
 
                n2.xoffset += Array_nel;
1078
 
                n2.type = types[TUINT32];
1079
 
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
1080
 
                regfree(&n1);
1081
 
        } else {        // old[lb:hb]
1082
 
                n2 = nodes[0];
1083
 
                n2.xoffset += Array_cap;
1084
 
                n2.type = types[TUINT32];
1085
 
                if (!nochk) {
1086
 
                        // if(hb[2] > old.cap[0]) goto throw;
1087
 
                        cmpandthrow(&nodes[2], &n2);
1088
 
                        // if(lb[1] > hb[2]) goto throw;
1089
 
                        cmpandthrow(&nodes[1], &nodes[2]);
1090
 
                }
1091
 
 
1092
 
                // ret.len = hb[2]-lb[1]; (destroys hb[2])
1093
 
                n2 = nres;
1094
 
                n2.xoffset += Array_nel;
1095
 
                n2.type = types[TUINT32];
1096
 
 
1097
 
                if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
1098
 
                        v = mpgetfix(nodes[2].val.u.xval) -
1099
 
                                mpgetfix(nodes[1].val.u.xval);
1100
 
                        nodconst(&n1, types[TUINT32], v);
1101
 
                        gins(optoas(OAS, types[TUINT32]), &n1, &n2);
1102
 
                } else {
1103
 
                        regalloc(&n1, types[TUINT32], &nodes[2]);
1104
 
                        gmove(&nodes[2], &n1);
1105
 
                        if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
1106
 
                                gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
1107
 
                        gins(optoas(OAS, types[TUINT32]), &n1, &n2);
1108
 
                        regfree(&n1);
1109
 
                }
1110
 
        }
1111
 
 
1112
 
        // ret.cap = old.cap[0]-lb[1]; (uses hb[2])
1113
 
        n2 = nodes[0];
1114
 
        n2.xoffset += Array_cap;
1115
 
        n2.type = types[TUINT32];
1116
 
 
1117
 
        regalloc(&n1, types[TUINT32], &nodes[2]);
1118
 
        gins(optoas(OAS, types[TUINT32]), &n2, &n1);
1119
 
        if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
1120
 
                gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
1121
 
 
1122
 
        n2 = nres;
1123
 
        n2.xoffset += Array_cap;
1124
 
        n2.type = types[TUINT32];
1125
 
        gins(optoas(OAS, types[TUINT32]), &n1, &n2);
1126
 
        regfree(&n1);
1127
 
 
1128
 
        // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
1129
 
        n2 = nodes[0];
1130
 
        n2.xoffset += Array_array;
1131
 
        n2.type = types[tptr];
1132
 
 
1133
 
        regalloc(&n1, types[tptr], &nodes[1]);
1134
 
        if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
1135
 
                gins(optoas(OAS, types[tptr]), &n2, &n1);
1136
 
                v = mpgetfix(nodes[1].val.u.xval) *
1137
 
                        mpgetfix(nodes[3].val.u.xval);
1138
 
                if(v != 0) {
1139
 
                        nodconst(&n2, types[tptr], v);
1140
 
                        gins(optoas(OADD, types[tptr]), &n2, &n1);
1141
 
                }
1142
 
        } else {
1143
 
                gmove(&nodes[1], &n1);
1144
 
                if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1)
1145
 
                        gins(optoas(OMUL, types[tptr]), &nodes[3], &n1);
1146
 
                gins(optoas(OADD, types[tptr]), &n2, &n1);
1147
 
        }
1148
 
 
1149
 
        n2 = nres;
1150
 
        n2.xoffset += Array_array;
1151
 
        n2.type = types[tptr];
1152
 
        gins(optoas(OAS, types[tptr]), &n1, &n2);
1153
 
        regfree(&n1);
1154
 
 
1155
 
        for(i=0; i<4; i++) {
1156
 
                if(nodes[i].op == OREGISTER)
1157
 
                        regfree(&nodes[i]);
1158
 
        }
1159
 
 
1160
 
        if(!sleasy(res)) {
1161
 
                cgen(&nres, res);
1162
 
        }
1163
 
        return 1;
1164
 
 
1165
 
no:
1166
 
        return 0;
 
1138
                patch(gbranch(optoas(a, nr->type), T, likely), to);
 
1139
 
1167
1140
}