summaryrefslogtreecommitdiff
path: root/src/cmd/5g/cgen64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/cgen64.c')
-rw-r--r--src/cmd/5g/cgen64.c716
1 files changed, 0 insertions, 716 deletions
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c
deleted file mode 100644
index 4da8db2ae..000000000
--- a/src/cmd/5g/cgen64.c
+++ /dev/null
@@ -1,716 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "gg.h"
-
-/*
- * attempt to generate 64-bit
- * res = n
- * return 1 on success, 0 if op not handled.
- */
-void
-cgen64(Node *n, Node *res)
-{
- Node t1, t2, *l, *r;
- Node lo1, lo2, hi1, hi2;
- Node al, ah, bl, bh, cl, ch, s, n1, creg;
- Prog *p1, *p2, *p3, *p4, *p5, *p6;
-
- uint64 v;
-
- if(res->op != OINDREG && res->op != ONAME) {
- dump("n", n);
- dump("res", res);
- fatal("cgen64 %O of %O", n->op, res->op);
- }
-
- l = n->left;
- if(!l->addable) {
- tempname(&t1, l->type);
- cgen(l, &t1);
- l = &t1;
- }
-
- split64(l, &lo1, &hi1);
- switch(n->op) {
- default:
- fatal("cgen64 %O", n->op);
-
- case OMINUS:
- split64(res, &lo2, &hi2);
-
- regalloc(&t1, lo1.type, N);
- regalloc(&al, lo1.type, N);
- regalloc(&ah, hi1.type, N);
-
- gins(AMOVW, &lo1, &al);
- gins(AMOVW, &hi1, &ah);
-
- gmove(ncon(0), &t1);
- p1 = gins(ASUB, &al, &t1);
- p1->scond |= C_SBIT;
- gins(AMOVW, &t1, &lo2);
-
- gmove(ncon(0), &t1);
- gins(ASBC, &ah, &t1);
- gins(AMOVW, &t1, &hi2);
-
- regfree(&t1);
- regfree(&al);
- regfree(&ah);
- splitclean();
- splitclean();
- return;
-
- case OCOM:
- regalloc(&t1, lo1.type, N);
- gmove(ncon(-1), &t1);
-
- split64(res, &lo2, &hi2);
- regalloc(&n1, lo1.type, N);
-
- gins(AMOVW, &lo1, &n1);
- gins(AEOR, &t1, &n1);
- gins(AMOVW, &n1, &lo2);
-
- gins(AMOVW, &hi1, &n1);
- gins(AEOR, &t1, &n1);
- gins(AMOVW, &n1, &hi2);
-
- regfree(&t1);
- regfree(&n1);
- splitclean();
- splitclean();
- return;
-
- case OADD:
- case OSUB:
- case OMUL:
- case OLSH:
- case ORSH:
- case OAND:
- case OOR:
- case OXOR:
- // binary operators.
- // common setup below.
- break;
- }
-
- // setup for binary operators
- r = n->right;
- if(r != N && !r->addable) {
- tempname(&t2, r->type);
- cgen(r, &t2);
- r = &t2;
- }
- if(is64(r->type))
- split64(r, &lo2, &hi2);
-
- regalloc(&al, lo1.type, N);
- regalloc(&ah, hi1.type, N);
-
- // Do op. Leave result in ah:al.
- switch(n->op) {
- default:
- fatal("cgen64: not implemented: %N\n", n);
-
- case OADD:
- // TODO: Constants
- regalloc(&bl, types[TPTR32], N);
- regalloc(&bh, types[TPTR32], N);
- gins(AMOVW, &hi1, &ah);
- gins(AMOVW, &lo1, &al);
- gins(AMOVW, &hi2, &bh);
- gins(AMOVW, &lo2, &bl);
- p1 = gins(AADD, &bl, &al);
- p1->scond |= C_SBIT;
- gins(AADC, &bh, &ah);
- regfree(&bl);
- regfree(&bh);
- break;
-
- case OSUB:
- // TODO: Constants.
- regalloc(&bl, types[TPTR32], N);
- regalloc(&bh, types[TPTR32], N);
- gins(AMOVW, &lo1, &al);
- gins(AMOVW, &hi1, &ah);
- gins(AMOVW, &lo2, &bl);
- gins(AMOVW, &hi2, &bh);
- p1 = gins(ASUB, &bl, &al);
- p1->scond |= C_SBIT;
- gins(ASBC, &bh, &ah);
- regfree(&bl);
- regfree(&bh);
- break;
-
- case OMUL:
- // TODO(kaib): this can be done with 4 regs and does not need 6
- regalloc(&bl, types[TPTR32], N);
- regalloc(&bh, types[TPTR32], N);
- regalloc(&cl, types[TPTR32], N);
- regalloc(&ch, types[TPTR32], N);
-
- // load args into bh:bl and bh:bl.
- gins(AMOVW, &hi1, &bh);
- gins(AMOVW, &lo1, &bl);
- gins(AMOVW, &hi2, &ch);
- gins(AMOVW, &lo2, &cl);
-
- // bl * cl
- p1 = gins(AMULLU, N, N);
- p1->from.type = D_REG;
- p1->from.reg = bl.val.u.reg;
- p1->reg = cl.val.u.reg;
- p1->to.type = D_REGREG;
- p1->to.reg = ah.val.u.reg;
- p1->to.offset = al.val.u.reg;
-//print("%P\n", p1);
-
- // bl * ch
- p1 = gins(AMULA, N, N);
- p1->from.type = D_REG;
- p1->from.reg = bl.val.u.reg;
- p1->reg = ch.val.u.reg;
- p1->to.type = D_REGREG;
- p1->to.reg = ah.val.u.reg;
- p1->to.offset = ah.val.u.reg;
-//print("%P\n", p1);
-
- // bh * cl
- p1 = gins(AMULA, N, N);
- p1->from.type = D_REG;
- p1->from.reg = bh.val.u.reg;
- p1->reg = cl.val.u.reg;
- p1->to.type = D_REGREG;
- p1->to.reg = ah.val.u.reg;
- p1->to.offset = ah.val.u.reg;
-//print("%P\n", p1);
-
- regfree(&bh);
- regfree(&bl);
- regfree(&ch);
- regfree(&cl);
-
- break;
-
- case OLSH:
- regalloc(&bl, lo1.type, N);
- regalloc(&bh, hi1.type, N);
- gins(AMOVW, &hi1, &bh);
- gins(AMOVW, &lo1, &bl);
-
- if(r->op == OLITERAL) {
- v = mpgetfix(r->val.u.xval);
- if(v >= 64) {
- // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
- // here and below (verify it optimizes to EOR)
- gins(AEOR, &al, &al);
- gins(AEOR, &ah, &ah);
- } else
- if(v > 32) {
- gins(AEOR, &al, &al);
- // MOVW bl<<(v-32), ah
- gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
- } else
- if(v == 32) {
- gins(AEOR, &al, &al);
- gins(AMOVW, &bl, &ah);
- } else
- if(v > 0) {
- // MOVW bl<<v, al
- gshift(AMOVW, &bl, SHIFT_LL, v, &al);
-
- // MOVW bh<<v, ah
- gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
-
- // OR bl>>(32-v), ah
- gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
- } else {
- gins(AMOVW, &bl, &al);
- gins(AMOVW, &bh, &ah);
- }
- goto olsh_break;
- }
-
- regalloc(&s, types[TUINT32], N);
- regalloc(&creg, types[TUINT32], N);
- if (is64(r->type)) {
- // shift is >= 1<<32
- split64(r, &cl, &ch);
- gmove(&ch, &s);
- p1 = gins(ATST, &s, N);
- p6 = gbranch(ABNE, T);
- gmove(&cl, &s);
- splitclean();
- } else {
- gmove(r, &s);
- p6 = P;
- }
- p1 = gins(ATST, &s, N);
-
- // shift == 0
- p1 = gins(AMOVW, &bl, &al);
- p1->scond = C_SCOND_EQ;
- p1 = gins(AMOVW, &bh, &ah);
- p1->scond = C_SCOND_EQ;
- p2 = gbranch(ABEQ, T);
-
- // shift is < 32
- nodconst(&n1, types[TUINT32], 32);
- gmove(&n1, &creg);
- gcmp(ACMP, &s, &creg);
-
- // MOVW.LO bl<<s, al
- p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
- p1->scond = C_SCOND_LO;
-
- // MOVW.LO bh<<s, ah
- p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
- p1->scond = C_SCOND_LO;
-
- // SUB.LO s, creg
- p1 = gins(ASUB, &s, &creg);
- p1->scond = C_SCOND_LO;
-
- // OR.LO bl>>creg, ah
- p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
- p1->scond = C_SCOND_LO;
-
- // BLO end
- p3 = gbranch(ABLO, T);
-
- // shift == 32
- p1 = gins(AEOR, &al, &al);
- p1->scond = C_SCOND_EQ;
- p1 = gins(AMOVW, &bl, &ah);
- p1->scond = C_SCOND_EQ;
- p4 = gbranch(ABEQ, T);
-
- // shift is < 64
- nodconst(&n1, types[TUINT32], 64);
- gmove(&n1, &creg);
- gcmp(ACMP, &s, &creg);
-
- // EOR.LO al, al
- p1 = gins(AEOR, &al, &al);
- p1->scond = C_SCOND_LO;
-
- // MOVW.LO creg>>1, creg
- p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
- p1->scond = C_SCOND_LO;
-
- // SUB.LO creg, s
- p1 = gins(ASUB, &creg, &s);
- p1->scond = C_SCOND_LO;
-
- // MOVW bl<<s, ah
- p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
- p1->scond = C_SCOND_LO;
-
- p5 = gbranch(ABLO, T);
-
- // shift >= 64
- if (p6 != P) patch(p6, pc);
- gins(AEOR, &al, &al);
- gins(AEOR, &ah, &ah);
-
- patch(p2, pc);
- patch(p3, pc);
- patch(p4, pc);
- patch(p5, pc);
- regfree(&s);
- regfree(&creg);
-
-olsh_break:
- regfree(&bl);
- regfree(&bh);
- break;
-
-
- case ORSH:
- regalloc(&bl, lo1.type, N);
- regalloc(&bh, hi1.type, N);
- gins(AMOVW, &hi1, &bh);
- gins(AMOVW, &lo1, &bl);
-
- if(r->op == OLITERAL) {
- v = mpgetfix(r->val.u.xval);
- if(v >= 64) {
- if(bh.type->etype == TINT32) {
- // MOVW bh->31, al
- gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
-
- // MOVW bh->31, ah
- gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
- } else {
- gins(AEOR, &al, &al);
- gins(AEOR, &ah, &ah);
- }
- } else
- if(v > 32) {
- if(bh.type->etype == TINT32) {
- // MOVW bh->(v-32), al
- gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
-
- // MOVW bh->31, ah
- gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
- } else {
- // MOVW bh>>(v-32), al
- gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
- gins(AEOR, &ah, &ah);
- }
- } else
- if(v == 32) {
- gins(AMOVW, &bh, &al);
- if(bh.type->etype == TINT32) {
- // MOVW bh->31, ah
- gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
- } else {
- gins(AEOR, &ah, &ah);
- }
- } else
- if( v > 0) {
- // MOVW bl>>v, al
- gshift(AMOVW, &bl, SHIFT_LR, v, &al);
-
- // OR bh<<(32-v), al
- gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
-
- if(bh.type->etype == TINT32) {
- // MOVW bh->v, ah
- gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
- } else {
- // MOVW bh>>v, ah
- gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
- }
- } else {
- gins(AMOVW, &bl, &al);
- gins(AMOVW, &bh, &ah);
- }
- goto orsh_break;
- }
-
- regalloc(&s, types[TUINT32], N);
- regalloc(&creg, types[TUINT32], N);
- if(is64(r->type)) {
- // shift is >= 1<<32
- split64(r, &cl, &ch);
- gmove(&ch, &s);
- gins(ATST, &s, N);
- if(bh.type->etype == TINT32)
- p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
- else
- p1 = gins(AEOR, &ah, &ah);
- p1->scond = C_SCOND_NE;
- p6 = gbranch(ABNE, T);
- gmove(&cl, &s);
- splitclean();
- } else {
- gmove(r, &s);
- p6 = P;
- }
- p1 = gins(ATST, &s, N);
-
- // shift == 0
- p1 = gins(AMOVW, &bl, &al);
- p1->scond = C_SCOND_EQ;
- p1 = gins(AMOVW, &bh, &ah);
- p1->scond = C_SCOND_EQ;
- p2 = gbranch(ABEQ, T);
-
- // check if shift is < 32
- nodconst(&n1, types[TUINT32], 32);
- gmove(&n1, &creg);
- gcmp(ACMP, &s, &creg);
-
- // MOVW.LO bl>>s, al
- p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
- p1->scond = C_SCOND_LO;
-
- // SUB.LO s,creg
- p1 = gins(ASUB, &s, &creg);
- p1->scond = C_SCOND_LO;
-
- // OR.LO bh<<(32-s), al
- p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
- p1->scond = C_SCOND_LO;
-
- if(bh.type->etype == TINT32) {
- // MOVW bh->s, ah
- p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
- } else {
- // MOVW bh>>s, ah
- p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
- }
- p1->scond = C_SCOND_LO;
-
- // BLO end
- p3 = gbranch(ABLO, T);
-
- // shift == 32
- p1 = gins(AMOVW, &bh, &al);
- p1->scond = C_SCOND_EQ;
- if(bh.type->etype == TINT32)
- p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
- else
- p1 = gins(AEOR, &ah, &ah);
- p4 = gbranch(ABEQ, T);
-
- // check if shift is < 64
- nodconst(&n1, types[TUINT32], 64);
- gmove(&n1, &creg);
- gcmp(ACMP, &s, &creg);
-
- // MOVW.LO creg>>1, creg
- p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
- p1->scond = C_SCOND_LO;
-
- // SUB.LO creg, s
- p1 = gins(ASUB, &creg, &s);
- p1->scond = C_SCOND_LO;
-
- if(bh.type->etype == TINT32) {
- // MOVW bh->(s-32), al
- p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
- p1->scond = C_SCOND_LO;
- } else {
- // MOVW bh>>(v-32), al
- p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
- p1->scond = C_SCOND_LO;
- }
-
- // BLO end
- p5 = gbranch(ABLO, T);
-
- // s >= 64
- if(p6 != P)
- patch(p6, pc);
- if(bh.type->etype == TINT32) {
- // MOVW bh->31, al
- gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
- } else {
- gins(AEOR, &al, &al);
- }
-
- patch(p2, pc);
- patch(p3, pc);
- patch(p4, pc);
- patch(p5, pc);
- regfree(&s);
- regfree(&creg);
-
-
-orsh_break:
- regfree(&bl);
- regfree(&bh);
- break;
-
- case OXOR:
- case OAND:
- case OOR:
- // TODO(kaib): literal optimizations
- // make constant the right side (it usually is anyway).
-// if(lo1.op == OLITERAL) {
-// nswap(&lo1, &lo2);
-// nswap(&hi1, &hi2);
-// }
-// if(lo2.op == OLITERAL) {
-// // special cases for constants.
-// lv = mpgetfix(lo2.val.u.xval);
-// hv = mpgetfix(hi2.val.u.xval);
-// splitclean(); // right side
-// split64(res, &lo2, &hi2);
-// switch(n->op) {
-// case OXOR:
-// gmove(&lo1, &lo2);
-// gmove(&hi1, &hi2);
-// switch(lv) {
-// case 0:
-// break;
-// case 0xffffffffu:
-// gins(ANOTL, N, &lo2);
-// break;
-// default:
-// gins(AXORL, ncon(lv), &lo2);
-// break;
-// }
-// switch(hv) {
-// case 0:
-// break;
-// case 0xffffffffu:
-// gins(ANOTL, N, &hi2);
-// break;
-// default:
-// gins(AXORL, ncon(hv), &hi2);
-// break;
-// }
-// break;
-
-// case OAND:
-// switch(lv) {
-// case 0:
-// gins(AMOVL, ncon(0), &lo2);
-// break;
-// default:
-// gmove(&lo1, &lo2);
-// if(lv != 0xffffffffu)
-// gins(AANDL, ncon(lv), &lo2);
-// break;
-// }
-// switch(hv) {
-// case 0:
-// gins(AMOVL, ncon(0), &hi2);
-// break;
-// default:
-// gmove(&hi1, &hi2);
-// if(hv != 0xffffffffu)
-// gins(AANDL, ncon(hv), &hi2);
-// break;
-// }
-// break;
-
-// case OOR:
-// switch(lv) {
-// case 0:
-// gmove(&lo1, &lo2);
-// break;
-// case 0xffffffffu:
-// gins(AMOVL, ncon(0xffffffffu), &lo2);
-// break;
-// default:
-// gmove(&lo1, &lo2);
-// gins(AORL, ncon(lv), &lo2);
-// break;
-// }
-// switch(hv) {
-// case 0:
-// gmove(&hi1, &hi2);
-// break;
-// case 0xffffffffu:
-// gins(AMOVL, ncon(0xffffffffu), &hi2);
-// break;
-// default:
-// gmove(&hi1, &hi2);
-// gins(AORL, ncon(hv), &hi2);
-// break;
-// }
-// break;
-// }
-// splitclean();
-// splitclean();
-// goto out;
-// }
- regalloc(&n1, lo1.type, N);
- gins(AMOVW, &lo1, &al);
- gins(AMOVW, &hi1, &ah);
- gins(AMOVW, &lo2, &n1);
- gins(optoas(n->op, lo1.type), &n1, &al);
- gins(AMOVW, &hi2, &n1);
- gins(optoas(n->op, lo1.type), &n1, &ah);
- regfree(&n1);
- break;
- }
- if(is64(r->type))
- splitclean();
- splitclean();
-
- split64(res, &lo1, &hi1);
- gins(AMOVW, &al, &lo1);
- gins(AMOVW, &ah, &hi1);
- splitclean();
-
-//out:
- regfree(&al);
- regfree(&ah);
-}
-
-/*
- * generate comparison of nl, nr, both 64-bit.
- * nl is memory; nr is constant or memory.
- */
-void
-cmp64(Node *nl, Node *nr, int op, Prog *to)
-{
- Node lo1, hi1, lo2, hi2, r1, r2;
- Prog *br;
- Type *t;
-
- split64(nl, &lo1, &hi1);
- split64(nr, &lo2, &hi2);
-
- // compare most significant word;
- // if they differ, we're done.
- t = hi1.type;
- regalloc(&r1, types[TINT32], N);
- regalloc(&r2, types[TINT32], N);
- gins(AMOVW, &hi1, &r1);
- gins(AMOVW, &hi2, &r2);
- gcmp(ACMP, &r1, &r2);
- regfree(&r1);
- regfree(&r2);
-
- br = P;
- switch(op) {
- default:
- fatal("cmp64 %O %T", op, t);
- case OEQ:
- // cmp hi
- // bne L
- // cmp lo
- // beq to
- // L:
- br = gbranch(ABNE, T);
- break;
- case ONE:
- // cmp hi
- // bne to
- // cmp lo
- // bne to
- patch(gbranch(ABNE, T), to);
- break;
- case OGE:
- case OGT:
- // cmp hi
- // bgt to
- // blt L
- // cmp lo
- // bge to (or bgt to)
- // L:
- patch(gbranch(optoas(OGT, t), T), to);
- br = gbranch(optoas(OLT, t), T);
- break;
- case OLE:
- case OLT:
- // cmp hi
- // blt to
- // bgt L
- // cmp lo
- // ble to (or jlt to)
- // L:
- patch(gbranch(optoas(OLT, t), T), to);
- br = gbranch(optoas(OGT, t), T);
- break;
- }
-
- // compare least significant word
- t = lo1.type;
- regalloc(&r1, types[TINT32], N);
- regalloc(&r2, types[TINT32], N);
- gins(AMOVW, &lo1, &r1);
- gins(AMOVW, &lo2, &r2);
- gcmp(ACMP, &r1, &r2);
- regfree(&r1);
- regfree(&r2);
-
- // jump again
- patch(gbranch(optoas(op, t), T), to);
-
- // point first branch down here if appropriate
- if(br != P)
- patch(br, pc);
-
- splitclean();
- splitclean();
-}