summaryrefslogtreecommitdiff
path: root/src/cmd/8c/cgen64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8c/cgen64.c')
-rw-r--r--src/cmd/8c/cgen64.c2657
1 files changed, 0 insertions, 2657 deletions
diff --git a/src/cmd/8c/cgen64.c b/src/cmd/8c/cgen64.c
deleted file mode 100644
index 3424f762c..000000000
--- a/src/cmd/8c/cgen64.c
+++ /dev/null
@@ -1,2657 +0,0 @@
-// Inferno utils/8c/cgen64.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen64.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-zeroregm(Node *n)
-{
- gins(AMOVL, nodconst(0), n);
-}
-
-/* do we need to load the address of a vlong? */
-int
-vaddr(Node *n, int a)
-{
- switch(n->op) {
- case ONAME:
- if(a)
- return 1;
- return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
-
- case OCONST:
- case OREGISTER:
- case OINDREG:
- return 1;
- }
- return 0;
-}
-
-int32
-hi64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)(n->vconst) & ~0L;
- else
- return (int32)((uvlong)n->vconst>>32) & ~0L;
-}
-
-int32
-lo64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)((uvlong)n->vconst>>32) & ~0L;
- else
- return (int32)(n->vconst) & ~0L;
-}
-
-Node *
-hi64(Node *n)
-{
- return nodconst(hi64v(n));
-}
-
-Node *
-lo64(Node *n)
-{
- return nodconst(lo64v(n));
-}
-
-static Node *
-anonreg(void)
-{
- Node *n;
-
- n = new(OREGISTER, Z, Z);
- n->reg = D_NONE;
- n->type = types[TLONG];
- return n;
-}
-
-static Node *
-regpair(Node *n, Node *t)
-{
- Node *r;
-
- if(n != Z && n->op == OREGPAIR)
- return n;
- r = new(OREGPAIR, anonreg(), anonreg());
- if(n != Z)
- r->type = n->type;
- else
- r->type = t->type;
- return r;
-}
-
-static void
-evacaxdx(Node *r)
-{
- Node nod1, nod2;
-
- if(r->reg == D_AX || r->reg == D_DX) {
- reg[D_AX]++;
- reg[D_DX]++;
- /*
- * this is just an optim that should
- * check for spill
- */
- r->type = types[TULONG];
- regalloc(&nod1, r, Z);
- nodreg(&nod2, Z, r->reg);
- gins(AMOVL, &nod2, &nod1);
- regfree(r);
- r->reg = nod1.reg;
- reg[D_AX]--;
- reg[D_DX]--;
- }
-}
-
-/* lazy instantiation of register pair */
-static int
-instpair(Node *n, Node *l)
-{
- int r;
-
- r = 0;
- if(n->left->reg == D_NONE) {
- if(l != Z) {
- n->left->reg = l->reg;
- r = 1;
- }
- else
- regalloc(n->left, n->left, Z);
- }
- if(n->right->reg == D_NONE)
- regalloc(n->right, n->right, Z);
- return r;
-}
-
-static void
-zapreg(Node *n)
-{
- if(n->reg != D_NONE) {
- regfree(n);
- n->reg = D_NONE;
- }
-}
-
-static void
-freepair(Node *n)
-{
- regfree(n->left);
- regfree(n->right);
-}
-
-/* n is not OREGPAIR, nn is */
-void
-loadpair(Node *n, Node *nn)
-{
- Node nod;
-
- instpair(nn, Z);
- if(n->op == OCONST) {
- gins(AMOVL, lo64(n), nn->left);
- n->xoffset += SZ_LONG;
- gins(AMOVL, hi64(n), nn->right);
- n->xoffset -= SZ_LONG;
- return;
- }
- if(!vaddr(n, 0)) {
- /* steal the right register for the laddr */
- nod = regnode;
- nod.reg = nn->right->reg;
- lcgen(n, &nod);
- n = &nod;
- regind(n, n);
- n->xoffset = 0;
- }
- gins(AMOVL, n, nn->left);
- n->xoffset += SZ_LONG;
- gins(AMOVL, n, nn->right);
- n->xoffset -= SZ_LONG;
-}
-
-/* n is OREGPAIR, nn is not */
-static void
-storepair(Node *n, Node *nn, int f)
-{
- Node nod;
-
- if(!vaddr(nn, 0)) {
- reglcgen(&nod, nn, Z);
- nn = &nod;
- }
- gins(AMOVL, n->left, nn);
- nn->xoffset += SZ_LONG;
- gins(AMOVL, n->right, nn);
- nn->xoffset -= SZ_LONG;
- if(nn == &nod)
- regfree(&nod);
- if(f)
- freepair(n);
-}
-
-enum
-{
-/* 4 only, see WW */
- WNONE = 0,
- WCONST,
- WADDR,
- WHARD,
-};
-
-static int
-whatof(Node *n, int a)
-{
- if(n->op == OCONST)
- return WCONST;
- return !vaddr(n, a) ? WHARD : WADDR;
-}
-
-/* can upgrade an extern to addr for AND */
-static int
-reduxv(Node *n)
-{
- return lo64v(n) == 0 || hi64v(n) == 0;
-}
-
-int
-cond(int op)
-{
- switch(op) {
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
-
-/*
- * for a func operand call it and then return
- * the safe node
- */
-static Node *
-vfunc(Node *n, Node *nn)
-{
- Node *t;
-
- if(n->op != OFUNC)
- return n;
- t = new(0, Z, Z);
- if(nn == Z || nn == nodret)
- nn = n;
- regsalloc(t, nn);
- sugen(n, t, 8);
- return t;
-}
-
-/* try to steal a reg */
-static int
-getreg(Node **np, Node *t, int r)
-{
- Node *n, *p;
-
- n = *np;
- if(n->reg == r) {
- p = new(0, Z, Z);
- regalloc(p, n, Z);
- gins(AMOVL, n, p);
- *t = *n;
- *np = p;
- return 1;
- }
- return 0;
-}
-
-static Node *
-snarfreg(Node *n, Node *t, int r, Node *d, Node *c)
-{
- if(n == Z || n->op != OREGPAIR || (!getreg(&n->left, t, r) && !getreg(&n->right, t, r))) {
- if(nodreg(t, Z, r)) {
- regalloc(c, d, Z);
- gins(AMOVL, t, c);
- reg[r]++;
- return c;
- }
- reg[r]++;
- }
- return Z;
-}
-
-enum
-{
- Vstart = OEND,
-
- Vgo,
- Vamv,
- Vmv,
- Vzero,
- Vop,
- Vopx,
- Vins,
- Vins0,
- Vinsl,
- Vinsr,
- Vinsla,
- Vinsra,
- Vinsx,
- Vmul,
- Vshll,
- VT,
- VF,
- V_l_lo_f,
- V_l_hi_f,
- V_l_lo_t,
- V_l_hi_t,
- V_l_lo_u,
- V_l_hi_u,
- V_r_lo_f,
- V_r_hi_f,
- V_r_lo_t,
- V_r_hi_t,
- V_r_lo_u,
- V_r_hi_u,
- Vspazz,
- Vend,
-
- V_T0,
- V_T1,
- V_F0,
- V_F1,
-
- V_a0,
- V_a1,
- V_f0,
- V_f1,
-
- V_p0,
- V_p1,
- V_p2,
- V_p3,
- V_p4,
-
- V_s0,
- V_s1,
- V_s2,
- V_s3,
- V_s4,
-
- C00,
- C01,
- C31,
- C32,
-
- O_l_lo,
- O_l_hi,
- O_r_lo,
- O_r_hi,
- O_t_lo,
- O_t_hi,
- O_l,
- O_r,
- O_l_rp,
- O_r_rp,
- O_t_rp,
- O_r0,
- O_r1,
- O_Zop,
-
- O_a0,
- O_a1,
-
- V_C0,
- V_C1,
-
- V_S0,
- V_S1,
-
- VOPS = 5,
- VLEN = 5,
- VARGS = 2,
-
- S00 = 0,
- Sc0,
- Sc1,
- Sc2,
- Sac3,
- Sac4,
- S10,
-
- SAgen = 0,
- SAclo,
- SAc32,
- SAchi,
- SAdgen,
- SAdclo,
- SAdc32,
- SAdchi,
-
- B0c = 0,
- Bca,
- Bac,
-
- T0i = 0,
- Tii,
-
- Bop0 = 0,
- Bop1,
-};
-
-/*
- * _testv:
- * CMPL lo,$0
- * JNE true
- * CMPL hi,$0
- * JNE true
- * GOTO false
- * false:
- * GOTO code
- * true:
- * GOTO patchme
- * code:
- */
-
-static uchar testi[][VLEN] =
-{
- {Vop, ONE, O_l_lo, C00},
- {V_s0, Vop, ONE, O_l_hi, C00},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {Vend},
-};
-
-/* shift left general case */
-static uchar shll00[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vinsl, ASHLL, O_r, O_l_rp},
- {Vins, ASHLL, O_r, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, ASHLL, O_r, O_l_lo},
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, V_p0, Vend},
-};
-
-/* shift left rp, const < 32 */
-static uchar shllc0[][VLEN] =
-{
- {Vinsl, ASHLL, O_r, O_l_rp},
- {Vshll, O_r, O_l_lo, Vend},
-};
-
-/* shift left rp, const == 32 */
-static uchar shllc1[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, Vend},
-};
-
-/* shift left rp, const > 32 */
-static uchar shllc2[][VLEN] =
-{
- {Vshll, O_r, O_l_lo},
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, Vend},
-};
-
-/* shift left addr, const == 32 */
-static uchar shllac3[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo, Vend},
-};
-
-/* shift left addr, const > 32 */
-static uchar shllac4[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vshll, O_r, O_t_hi},
- {Vzero, O_t_lo, Vend},
-};
-
-/* shift left of constant */
-static uchar shll10[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vins, ASHLL, O_r, O_t_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {V_l_lo_t, Vins, ASHLL, O_r, O_t_hi},
- {Vzero, O_t_lo, V_p0, Vend},
-};
-
-static uchar (*shlltab[])[VLEN] =
-{
- shll00,
- shllc0,
- shllc1,
- shllc2,
- shllac3,
- shllac4,
- shll10,
-};
-
-/* shift right general case */
-static uchar shrl00[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vinsr, ASHRL, O_r, O_l_rp},
- {Vins, O_a0, O_r, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, O_a0, O_r, O_l_hi},
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {V_p0, Vend},
-};
-
-/* shift right rp, const < 32 */
-static uchar shrlc0[][VLEN] =
-{
- {Vinsr, ASHRL, O_r, O_l_rp},
- {Vins, O_a0, O_r, O_l_hi, Vend},
-};
-
-/* shift right rp, const == 32 */
-static uchar shrlc1[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {Vend},
-};
-
-/* shift right rp, const > 32 */
-static uchar shrlc2[][VLEN] =
-{
- {Vins, O_a0, O_r, O_l_hi},
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {Vend},
-};
-
-/* shift right addr, const == 32 */
-static uchar shrlac3[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-/* shift right addr, const > 32 */
-static uchar shrlac4[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {Vins, O_a0, O_r, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-/* shift right of constant */
-static uchar shrl10[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vins, O_a0, O_r, O_t_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_l_hi_t, Vins, O_a0, O_r, O_t_lo},
- {V_l_hi_u, V_S1},
- {V_T1, Vzero, O_t_hi, V_p0},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-static uchar (*shrltab[])[VLEN] =
-{
- shrl00,
- shrlc0,
- shrlc1,
- shrlc2,
- shrlac3,
- shrlac4,
- shrl10,
-};
-
-/* shift asop left general case */
-static uchar asshllgen[][VLEN] =
-{
- {V_a0, V_a1},
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsla, ASHLL, O_r, O_r0},
- {Vins, ASHLL, O_r, O_r0},
- {Vins, AMOVL, O_r1, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vins, ASHLL, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_hi, V_p0},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const < 32 */
-static uchar asshllclo[][VLEN] =
-{
- {V_a0, V_a1},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsla, ASHLL, O_r, O_r0},
- {Vshll, O_r, O_r0},
- {Vins, AMOVL, O_r1, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const == 32 */
-static uchar asshllc32[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop left, const > 32 */
-static uchar asshllchi[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vshll, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop dest left general case */
-static uchar asdshllgen[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vins, ASHLL, O_r, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_l_lo},
- {Vins, ASHLL, O_r, O_t_hi},
- {Vzero, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
- {Vend},
-};
-
-/* shift asop dest left, const < 32 */
-static uchar asdshllclo[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vshll, O_r, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vend},
-};
-
-/* shift asop dest left, const == 32 */
-static uchar asdshllc32[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar asdshllchi[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo},
- {Vshll, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-static uchar (*asshlltab[])[VLEN] =
-{
- asshllgen,
- asshllclo,
- asshllc32,
- asshllchi,
- asdshllgen,
- asdshllclo,
- asdshllc32,
- asdshllchi,
-};
-
-/* shift asop right general case */
-static uchar asshrlgen[][VLEN] =
-{
- {V_a0, V_a1},
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsra, ASHRL, O_r, O_r0},
- {Vinsx, Bop0, O_r, O_r1},
- {Vins, AMOVL, O_r0, O_l_lo},
- {Vins, AMOVL, O_r1, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {Vinsx, Bop0, O_r, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_p0, V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const < 32 */
-static uchar asshrlclo[][VLEN] =
-{
- {V_a0, V_a1},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsra, ASHRL, O_r, O_r0},
- {Vinsx, Bop0, O_r, O_r1},
- {Vins, AMOVL, O_r0, O_l_lo},
- {Vins, AMOVL, O_r1, O_l_hi},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const == 32 */
-static uchar asshrlc32[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop right, const > 32 */
-static uchar asshrlchi[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vinsx, Bop0, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop dest right general case */
-static uchar asdshrlgen[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vinsx, Bop0, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {Vinsx, Bop0, O_r, O_t_lo},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
- {Vend},
-};
-
-/* shift asop dest right, const < 32 */
-static uchar asdshrlclo[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vinsx, Bop0, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-/* shift asop dest right, const == 32 */
-static uchar asdshrlc32[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar asdshrlchi[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {Vinsx, Bop0, O_r, O_t_lo},
- {V_T1, Vins, AMOVL, O_t_hi, O_l_hi},
- {V_T1, Vins, AMOVL, O_t_lo, O_l_lo},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_l_lo},
- {V_F1, Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-static uchar (*asshrltab[])[VLEN] =
-{
- asshrlgen,
- asshrlclo,
- asshrlc32,
- asshrlchi,
- asdshrlgen,
- asdshrlclo,
- asdshrlc32,
- asdshrlchi,
-};
-
-static uchar shrlargs[] = { ASHRL, 1 };
-static uchar sarlargs[] = { ASARL, 0 };
-
-/* ++ -- */
-static uchar incdec[][VLEN] =
-{
- {Vinsx, Bop0, C01, O_l_lo},
- {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* ++ -- *p */
-static uchar incdecpre[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, C01, O_t_lo},
- {Vinsx, Bop1, C00, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, Vend},
-};
-
-/* *p ++ -- */
-static uchar incdecpost[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, C01, O_l_lo},
- {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* binop rp, rp */
-static uchar binop00[][VLEN] =
-{
- {Vinsx, Bop0, O_r_lo, O_l_lo},
- {Vinsx, Bop1, O_r_hi, O_l_hi, Vend},
- {Vend},
-};
-
-/* binop rp, addr */
-static uchar binoptmp[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_lo, O_r0},
- {Vinsx, Bop0, O_r0, O_l_lo},
- {Vins, AMOVL, O_r_hi, O_r0},
- {Vinsx, Bop1, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* binop t = *a op *b */
-static uchar binop11[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop1, O_r_hi, O_t_hi, Vend},
-};
-
-/* binop t = rp +- c */
-static uchar add0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_lo_f, Vamv, Bop0, Bop1},
- {Vinsx, Bop1, O_r_hi, O_l_hi},
- {Vend},
-};
-
-/* binop t = rp & c */
-static uchar and0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_lo_f, Vins, AMOVL, C00, O_l_lo},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
- {V_r_hi_f, Vins, AMOVL, C00, O_l_hi},
- {Vend},
-};
-
-/* binop t = rp | c */
-static uchar or0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
- {Vend},
-};
-
-/* binop t = c - rp */
-static uchar sub10[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_lo, O_r0},
- {Vinsx, Bop0, O_r_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r_lo},
- {Vinsx, Bop1, O_r_hi, O_r_lo},
- {Vspazz, V_f0, Vend},
-};
-
-/* binop t = c + *b */
-static uchar addca[][VLEN] =
-{
- {Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {V_l_lo_f, Vamv, Bop0, Bop1},
- {Vins, AMOVL, O_r_hi, O_t_hi},
- {Vinsx, Bop1, O_l_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = c & *b */
-static uchar andca[][VLEN] =
-{
- {V_l_lo_t, Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {V_l_lo_f, Vzero, O_t_lo},
- {V_l_hi_t, Vins, AMOVL, O_r_hi, O_t_hi},
- {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
- {V_l_hi_f, Vzero, O_t_hi},
- {Vend},
-};
-
-/* binop t = c | *b */
-static uchar orca[][VLEN] =
-{
- {Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_r_hi, O_t_hi},
- {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = c - *b */
-static uchar subca[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a +- c */
-static uchar addac[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {V_r_lo_f, Vamv, Bop0, Bop1},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a | c */
-static uchar orac[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a & c */
-static uchar andac[][VLEN] =
-{
- {V_r_lo_t, Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {V_r_lo_f, Vzero, O_t_lo},
- {V_r_hi_t, Vins, AMOVL, O_l_hi, O_t_hi},
- {V_r_hi_t, Vinsx, Bop0, O_r_hi, O_t_hi},
- {V_r_hi_f, Vzero, O_t_hi},
- {Vend},
-};
-
-static uchar ADDargs[] = { AADDL, AADCL };
-static uchar ANDargs[] = { AANDL, AANDL };
-static uchar ORargs[] = { AORL, AORL };
-static uchar SUBargs[] = { ASUBL, ASBBL };
-static uchar XORargs[] = { AXORL, AXORL };
-
-static uchar (*ADDtab[])[VLEN] =
-{
- add0c, addca, addac,
-};
-
-static uchar (*ANDtab[])[VLEN] =
-{
- and0c, andca, andac,
-};
-
-static uchar (*ORtab[])[VLEN] =
-{
- or0c, orca, orac,
-};
-
-static uchar (*SUBtab[])[VLEN] =
-{
- add0c, subca, addac,
-};
-
-/* mul of const32 */
-static uchar mulc32[][VLEN] =
-{
- {V_a0, Vop, ONE, O_l_hi, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {Vmul, O_r_lo, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* mul of const64 */
-static uchar mulc64[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_hi, O_r0},
- {Vop, OOR, O_l_hi, O_r0},
- {Vop, ONE, O_r0, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vmul, O_r_lo, O_l_hi},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vmul, O_r_hi, O_r0},
- {Vins, AADDL, O_l_hi, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* mul general */
-static uchar mull[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_hi, O_r0},
- {Vop, OOR, O_l_hi, O_r0},
- {Vop, ONE, O_r0, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vins, AIMULL, O_r_lo, O_l_hi},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AIMULL, O_r_hi, O_r0},
- {Vins, AADDL, O_l_hi, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* cast rp l to rp t */
-static uchar castrp[][VLEN] =
-{
- {Vmv, O_l, O_t_lo},
- {VT, Vins, AMOVL, O_t_lo, O_t_hi},
- {VT, Vins, ASARL, C31, O_t_hi},
- {VF, Vzero, O_t_hi},
- {Vend},
-};
-
-/* cast rp l to addr t */
-static uchar castrpa[][VLEN] =
-{
- {VT, V_a0, Vmv, O_l, O_r0},
- {VT, Vins, AMOVL, O_r0, O_t_lo},
- {VT, Vins, ASARL, C31, O_r0},
- {VT, Vins, AMOVL, O_r0, O_t_hi},
- {VT, V_f0},
- {VF, Vmv, O_l, O_t_lo},
- {VF, Vzero, O_t_hi},
- {Vend},
-};
-
-static uchar netab0i[][VLEN] =
-{
- {Vop, ONE, O_l_lo, O_r_lo},
- {V_s0, Vop, ONE, O_l_hi, O_r_hi},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {Vend},
-};
-
-static uchar netabii[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_lo, O_r0},
- {Vop, ONE, O_r0, O_r_lo},
- {V_s0, Vins, AMOVL, O_l_hi, O_r0},
- {Vop, ONE, O_r0, O_r_hi},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {V_f0, Vend},
-};
-
-static uchar cmptab0i[][VLEN] =
-{
- {Vopx, Bop0, O_l_hi, O_r_hi},
- {V_s0, Vins0, AJNE},
- {V_s1, Vopx, Bop1, O_l_lo, O_r_lo},
- {V_s2, Vgo, V_s3, Vgo, V_s4},
- {VT, V_p1, V_p3},
- {VF, V_p0, V_p2},
- {Vgo, V_p4},
- {VT, V_p0, V_p2},
- {VF, V_p1, V_p3},
- {Vend},
-};
-
-static uchar cmptabii[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_hi, O_r0},
- {Vopx, Bop0, O_r0, O_r_hi},
- {V_s0, Vins0, AJNE},
- {V_s1, Vins, AMOVL, O_l_lo, O_r0},
- {Vopx, Bop1, O_r0, O_r_lo},
- {V_s2, Vgo, V_s3, Vgo, V_s4},
- {VT, V_p1, V_p3},
- {VF, V_p0, V_p2},
- {Vgo, V_p4},
- {VT, V_p0, V_p2},
- {VF, V_p1, V_p3},
- {V_f0, Vend},
-};
-
-static uchar (*NEtab[])[VLEN] =
-{
- netab0i, netabii,
-};
-
-static uchar (*cmptab[])[VLEN] =
-{
- cmptab0i, cmptabii,
-};
-
-static uchar GEargs[] = { OGT, OHS };
-static uchar GTargs[] = { OGT, OHI };
-static uchar HIargs[] = { OHI, OHI };
-static uchar HSargs[] = { OHI, OHS };
-
-/* Big Generator */
-static void
-biggen(Node *l, Node *r, Node *t, int true, uchar code[][VLEN], uchar *a)
-{
- int i, j, g, oc, op, lo, ro, to, xo, *xp;
- Type *lt;
- Prog *pr[VOPS];
- Node *ot, *tl, *tr, tmps[2];
- uchar *c, (*cp)[VLEN], args[VARGS];
-
- if(a != nil)
- memmove(args, a, VARGS);
-//print("biggen %d %d %d\n", args[0], args[1], args[2]);
-//if(l) prtree(l, "l");
-//if(r) prtree(r, "r");
-//if(t) prtree(t, "t");
- lo = ro = to = 0;
- cp = code;
-
- for (;;) {
- c = *cp++;
- g = 1;
- i = 0;
-//print("code %d %d %d %d %d\n", c[0], c[1], c[2], c[3], c[4]);
- for(;;) {
- switch(op = c[i]) {
- case Vgo:
- if(g)
- gbranch(OGOTO);
- i++;
- break;
-
- case Vamv:
- i += 3;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- if(g)
- args[c[i - 1]] = args[c[i - 2]];
- break;
-
- case Vzero:
- i += 2;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 1;
- goto op;
-
- case Vspazz: // nasty hack to save a reg in SUB
-//print("spazz\n");
- if(g) {
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
- ot = r->right;
- r->right = r->left;
- tl = new(0, Z, Z);
- *tl = tmps[0];
- r->left = tl;
- tmps[0] = *ot;
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
- }
- i++;
- break;
-
- case Vmv:
- case Vmul:
- case Vshll:
- i += 3;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 2;
- goto op;
-
- case Vins0:
- i += 2;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- gins(c[i - 1], Z, Z);
- break;
-
- case Vop:
- case Vopx:
- case Vins:
- case Vinsl:
- case Vinsr:
- case Vinsla:
- case Vinsra:
- case Vinsx:
- i += 4;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 2;
- goto op;
-
- op:
- if(!g)
- break;
- tl = Z;
- tr = Z;
- for(; j < i; j++) {
- switch(c[j]) {
- case C00:
- ot = nodconst(0);
- break;
- case C01:
- ot = nodconst(1);
- break;
- case C31:
- ot = nodconst(31);
- break;
- case C32:
- ot = nodconst(32);
- break;
-
- case O_l:
- case O_l_lo:
- ot = l; xp = &lo; xo = 0;
- goto op0;
- case O_l_hi:
- ot = l; xp = &lo; xo = SZ_LONG;
- goto op0;
- case O_r:
- case O_r_lo:
- ot = r; xp = &ro; xo = 0;
- goto op0;
- case O_r_hi:
- ot = r; xp = &ro; xo = SZ_LONG;
- goto op0;
- case O_t_lo:
- ot = t; xp = &to; xo = 0;
- goto op0;
- case O_t_hi:
- ot = t; xp = &to; xo = SZ_LONG;
- goto op0;
- case O_l_rp:
- ot = l;
- break;
- case O_r_rp:
- ot = r;
- break;
- case O_t_rp:
- ot = t;
- break;
- case O_r0:
- case O_r1:
- ot = &tmps[c[j] - O_r0];
- break;
- case O_Zop:
- ot = Z;
- break;
-
- op0:
- switch(ot->op) {
- case OCONST:
- if(xo)
- ot = hi64(ot);
- else
- ot = lo64(ot);
- break;
- case OREGPAIR:
- if(xo)
- ot = ot->right;
- else
- ot = ot->left;
- break;
- case OREGISTER:
- break;
- default:
- if(xo != *xp) {
- ot->xoffset += xo - *xp;
- *xp = xo;
- }
- }
- break;
-
- default:
- diag(l, "bad V_lop");
- return;
- }
- if(tl == nil)
- tl = ot;
- else
- tr = ot;
- }
- if(op == Vzero) {
- zeroregm(tl);
- break;
- }
- oc = c[i - 3];
- if(op == Vinsx || op == Vopx) {
-//print("%d -> %d\n", oc, args[oc]);
- oc = args[oc];
- }
- else {
- switch(oc) {
- case O_a0:
- case O_a1:
- oc = args[oc - O_a0];
- break;
- }
- }
- switch(op) {
- case Vmul:
- mulgen(tr->type, tl, tr);
- break;
- case Vmv:
- gmove(tl, tr);
- break;
- case Vshll:
- shiftit(tr->type, tl, tr);
- break;
- case Vop:
- case Vopx:
- gopcode(oc, types[TULONG], tl, tr);
- break;
- case Vins:
- case Vinsx:
- gins(oc, tl, tr);
- break;
- case Vinsl:
- gins(oc, tl, tr->right);
- p->from.index = tr->left->reg;
- break;
- case Vinsr:
- gins(oc, tl, tr->left);
- p->from.index = tr->right->reg;
- break;
- case Vinsla:
- gins(oc, tl, tr + 1);
- p->from.index = tr->reg;
- break;
- case Vinsra:
- gins(oc, tl, tr);
- p->from.index = (tr + 1)->reg;
- break;
- }
- break;
-
- case VT:
- g = true;
- i++;
- break;
- case VF:
- g = !true;
- i++;
- break;
-
- case V_T0: case V_T1:
- g = args[op - V_T0];
- i++;
- break;
-
- case V_F0: case V_F1:
- g = !args[op - V_F0];
- i++;
- break;
-
- case V_C0: case V_C1:
- if(g)
- args[op - V_C0] = 0;
- i++;
- break;
-
- case V_S0: case V_S1:
- if(g)
- args[op - V_S0] = 1;
- i++;
- break;
-
- case V_l_lo_f:
- g = lo64v(l) == 0;
- i++;
- break;
- case V_l_hi_f:
- g = hi64v(l) == 0;
- i++;
- break;
- case V_l_lo_t:
- g = lo64v(l) != 0;
- i++;
- break;
- case V_l_hi_t:
- g = hi64v(l) != 0;
- i++;
- break;
- case V_l_lo_u:
- g = lo64v(l) >= 0;
- i++;
- break;
- case V_l_hi_u:
- g = hi64v(l) >= 0;
- i++;
- break;
- case V_r_lo_f:
- g = lo64v(r) == 0;
- i++;
- break;
- case V_r_hi_f:
- g = hi64v(r) == 0;
- i++;
- break;
- case V_r_lo_t:
- g = lo64v(r) != 0;
- i++;
- break;
- case V_r_hi_t:
- g = hi64v(r) != 0;
- i++;
- break;
- case V_r_lo_u:
- g = lo64v(r) >= 0;
- i++;
- break;
- case V_r_hi_u:
- g = hi64v(r) >= 0;
- i++;
- break;
-
- case Vend:
- goto out;
-
- case V_a0: case V_a1:
- if(g) {
- lt = l->type;
- l->type = types[TULONG];
- regalloc(&tmps[op - V_a0], l, Z);
- l->type = lt;
- }
- i++;
- break;
-
- case V_f0: case V_f1:
- if(g)
- regfree(&tmps[op - V_f0]);
- i++;
- break;
-
- case V_p0: case V_p1: case V_p2: case V_p3: case V_p4:
- if(g)
- patch(pr[op - V_p0], pc);
- i++;
- break;
-
- case V_s0: case V_s1: case V_s2: case V_s3: case V_s4:
- if(g)
- pr[op - V_s0] = p;
- i++;
- break;
-
- default:
- diag(l, "bad biggen: %d", op);
- return;
- }
- if(i == VLEN || c[i] == 0)
- break;
- }
- }
-out:
- if(lo)
- l->xoffset -= lo;
- if(ro)
- r->xoffset -= ro;
- if(to)
- t->xoffset -= to;
-}
-
-int
-cgen64(Node *n, Node *nn)
-{
- Type *dt;
- uchar *args, (*cp)[VLEN], (**optab)[VLEN];
- int li, ri, lri, dr, si, m, op, sh, cmp, true;
- Node *c, *d, *l, *r, *t, *s, nod1, nod2, nod3, nod4, nod5;
-
- if(debug['g']) {
- prtree(nn, "cgen64 lhs");
- prtree(n, "cgen64");
- print("AX = %d\n", reg[D_AX]);
- }
- cmp = 0;
- sh = 0;
-
- switch(n->op) {
- case ONEG:
- d = regpair(nn, n);
- sugen(n->left, d, 8);
- gins(ANOTL, Z, d->right);
- gins(ANEGL, Z, d->left);
- gins(ASBBL, nodconst(-1), d->right);
- break;
-
- case OCOM:
- if(!vaddr(n->left, 0) || !vaddr(nn, 0))
- d = regpair(nn, n);
- else
- return 0;
- sugen(n->left, d, 8);
- gins(ANOTL, Z, d->left);
- gins(ANOTL, Z, d->right);
- break;
-
- case OADD:
- optab = ADDtab;
- args = ADDargs;
- goto twoop;
- case OAND:
- optab = ANDtab;
- args = ANDargs;
- goto twoop;
- case OOR:
- optab = ORtab;
- args = ORargs;
- goto twoop;
- case OSUB:
- optab = SUBtab;
- args = SUBargs;
- goto twoop;
- case OXOR:
- optab = ORtab;
- args = XORargs;
- goto twoop;
- case OASHL:
- sh = 1;
- args = nil;
- optab = shlltab;
- goto twoop;
- case OLSHR:
- sh = 1;
- args = shrlargs;
- optab = shrltab;
- goto twoop;
- case OASHR:
- sh = 1;
- args = sarlargs;
- optab = shrltab;
- goto twoop;
- case OEQ:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case ONE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLT:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OGE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OGT:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OHI:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OHS:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLO:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLS:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
-
-twoop:
- dr = nn != Z && nn->op == OREGPAIR;
- l = vfunc(n->left, nn);
- if(sh)
- r = n->right;
- else
- r = vfunc(n->right, nn);
-
- li = l->op == ONAME || l->op == OINDREG || l->op == OCONST;
- ri = r->op == ONAME || r->op == OINDREG || r->op == OCONST;
-
-#define IMM(l, r) ((l) | ((r) << 1))
-
- lri = IMM(li, ri);
-
- /* find out what is so easy about some operands */
- if(li)
- li = whatof(l, sh | cmp);
- if(ri)
- ri = whatof(r, cmp);
-
- if(sh)
- goto shift;
-
- if(cmp)
- goto cmp;
-
- /* evaluate hard subexps, stealing nn if possible. */
- switch(lri) {
- case IMM(0, 0):
- bin00:
- if(l->complex > r->complex) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- }
- else {
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(0, 1):
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 0):
- if(n->op == OSUB && l->op == OCONST && hi64v(l) == 0) {
- lri = IMM(0, 0);
- goto bin00;
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- break;
- case IMM(1, 1):
- break;
- }
-
-#define WW(l, r) ((l) | ((r) << 2))
- d = Z;
- dt = nn->type;
- nn->type = types[TLONG];
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, 0, binop00, args);
- break;
- case IMM(0, 1):
- switch(ri) {
- case WNONE:
- diag(r, "bad whatof\n");
- break;
- case WCONST:
- biggen(l, r, Z, 0, optab[B0c], args);
- break;
- case WHARD:
- reglcgen(&nod2, r, Z);
- r = &nod2;
- /* fall thru */
- case WADDR:
- biggen(l, r, Z, 0, binoptmp, args);
- if(ri == WHARD)
- regfree(r);
- break;
- }
- break;
- case IMM(1, 0):
- if(n->op == OSUB) {
- switch(li) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WHARD:
- reglcgen(&nod2, l, Z);
- l = &nod2;
- /* fall thru */
- case WADDR:
- case WCONST:
- biggen(l, r, Z, 0, sub10, args);
- break;
- }
- if(li == WHARD)
- regfree(l);
- }
- else {
- switch(li) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WCONST:
- biggen(r, l, Z, 0, optab[B0c], args);
- break;
- case WHARD:
- reglcgen(&nod2, l, Z);
- l = &nod2;
- /* fall thru */
- case WADDR:
- biggen(r, l, Z, 0, binoptmp, args);
- if(li == WHARD)
- regfree(l);
- break;
- }
- }
- break;
- case IMM(1, 1):
- switch(WW(li, ri)) {
- case WW(WCONST, WHARD):
- if(r->op == ONAME && n->op == OAND && reduxv(l))
- ri = WADDR;
- break;
- case WW(WHARD, WCONST):
- if(l->op == ONAME && n->op == OAND && reduxv(r))
- li = WADDR;
- break;
- }
- if(li == WHARD) {
- reglcgen(&nod3, l, Z);
- l = &nod3;
- }
- if(ri == WHARD) {
- reglcgen(&nod2, r, Z);
- r = &nod2;
- }
- d = regpair(nn, n);
- instpair(d, Z);
- switch(WW(li, ri)) {
- case WW(WCONST, WADDR):
- case WW(WCONST, WHARD):
- biggen(l, r, d, 0, optab[Bca], args);
- break;
-
- case WW(WADDR, WCONST):
- case WW(WHARD, WCONST):
- biggen(l, r, d, 0, optab[Bac], args);
- break;
-
- case WW(WADDR, WADDR):
- case WW(WADDR, WHARD):
- case WW(WHARD, WADDR):
- case WW(WHARD, WHARD):
- biggen(l, r, d, 0, binop11, args);
- break;
-
- default:
- diag(r, "bad whatof pair %d %d\n", li, ri);
- break;
- }
- if(li == WHARD)
- regfree(l);
- if(ri == WHARD)
- regfree(r);
- break;
- }
-
- nn->type = dt;
-
- if(d != Z)
- goto finished;
-
- switch(lri) {
- case IMM(0, 0):
- freepair(r);
- /* fall thru */;
- case IMM(0, 1):
- if(!dr)
- storepair(l, nn, 1);
- break;
- case IMM(1, 0):
- if(!dr)
- storepair(r, nn, 1);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- shift:
- c = Z;
-
- /* evaluate hard subexps, stealing nn if possible. */
- /* must also secure CX. not as many optims as binop. */
- switch(lri) {
- case IMM(0, 0):
- imm00:
- if(l->complex + 1 > r->complex) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- t = &nod1;
- c = snarfreg(l, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- }
- else {
- t = &nod1;
- c = snarfreg(nn, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- if(dr)
- t = nn;
- else
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(0, 1):
- imm01:
- if(ri != WCONST) {
- lri = IMM(0, 0);
- goto imm00;
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 0):
- imm10:
- if(li != WCONST) {
- lri = IMM(0, 0);
- goto imm00;
- }
- t = &nod1;
- c = snarfreg(nn, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- break;
- case IMM(1, 1):
- if(ri != WCONST) {
- lri = IMM(1, 0);
- goto imm10;
- }
- if(li == WHARD) {
- lri = IMM(0, 1);
- goto imm01;
- }
- break;
- }
-
- d = Z;
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, 0, optab[S00], args);
- break;
- case IMM(0, 1):
- switch(ri) {
- case WNONE:
- case WADDR:
- case WHARD:
- diag(r, "bad whatof\n");
- break;
- case WCONST:
- m = r->vconst & 63;
- s = nodconst(m);
- if(m < 32)
- cp = optab[Sc0];
- else if(m == 32)
- cp = optab[Sc1];
- else
- cp = optab[Sc2];
- biggen(l, s, Z, 0, cp, args);
- break;
- }
- break;
- case IMM(1, 0):
- /* left is const */
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, r, d, 0, optab[S10], args);
- regfree(r);
- break;
- case IMM(1, 1):
- d = regpair(nn, n);
- instpair(d, Z);
- switch(WW(li, ri)) {
- case WW(WADDR, WCONST):
- m = r->vconst & 63;
- s = nodconst(m);
- if(m < 32) {
- loadpair(l, d);
- l = d;
- cp = optab[Sc0];
- }
- else if(m == 32)
- cp = optab[Sac3];
- else
- cp = optab[Sac4];
- biggen(l, s, d, 0, cp, args);
- break;
-
- default:
- diag(r, "bad whatof pair %d %d\n", li, ri);
- break;
- }
- break;
- }
-
- if(c != Z) {
- gins(AMOVL, c, r);
- regfree(c);
- }
-
- if(d != Z)
- goto finished;
-
- switch(lri) {
- case IMM(0, 0):
- regfree(r);
- /* fall thru */
- case IMM(0, 1):
- if(!dr)
- storepair(l, nn, 1);
- break;
- case IMM(1, 0):
- regfree(r);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- cmp:
- op = n->op;
- /* evaluate hard subexps */
- switch(lri) {
- case IMM(0, 0):
- if(l->complex > r->complex) {
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- }
- else {
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(1, 0):
- t = r;
- r = l;
- l = t;
- ri = li;
- op = invrel[relindex(op)];
- /* fall thru */
- case IMM(0, 1):
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 1):
- break;
- }
-
- true = 1;
- optab = cmptab;
- switch(op) {
- case OEQ:
- optab = NEtab;
- true = 0;
- break;
- case ONE:
- optab = NEtab;
- break;
- case OLE:
- args = GTargs;
- true = 0;
- break;
- case OGT:
- args = GTargs;
- break;
- case OLS:
- args = HIargs;
- true = 0;
- break;
- case OHI:
- args = HIargs;
- break;
- case OLT:
- args = GEargs;
- true = 0;
- break;
- case OGE:
- args = GEargs;
- break;
- case OLO:
- args = HSargs;
- true = 0;
- break;
- case OHS:
- args = HSargs;
- break;
- default:
- diag(n, "bad cmp\n");
- SET(optab);
- }
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, true, optab[T0i], args);
- break;
- case IMM(0, 1):
- case IMM(1, 0):
- switch(ri) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WCONST:
- biggen(l, r, Z, true, optab[T0i], args);
- break;
- case WHARD:
- reglcgen(&nod2, r, Z);
- r = &nod2;
- /* fall thru */
- case WADDR:
- biggen(l, r, Z, true, optab[T0i], args);
- if(ri == WHARD)
- regfree(r);
- break;
- }
- break;
- case IMM(1, 1):
- if(li == WHARD) {
- reglcgen(&nod3, l, Z);
- l = &nod3;
- }
- if(ri == WHARD) {
- reglcgen(&nod2, r, Z);
- r = &nod2;
- }
- biggen(l, r, Z, true, optab[Tii], args);
- if(li == WHARD)
- regfree(l);
- if(ri == WHARD)
- regfree(r);
- break;
- }
-
- switch(lri) {
- case IMM(0, 0):
- freepair(r);
- /* fall thru */;
- case IMM(0, 1):
- case IMM(1, 0):
- freepair(l);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- case OASMUL:
- case OASLMUL:
- m = 0;
- goto mulop;
-
- case OMUL:
- case OLMUL:
- m = 1;
- goto mulop;
-
- mulop:
- dr = nn != Z && nn->op == OREGPAIR;
- l = vfunc(n->left, nn);
- r = vfunc(n->right, nn);
- if(r->op != OCONST) {
- if(l->complex > r->complex) {
- if(m) {
- t = l;
- l = r;
- r = t;
- }
- else if(!vaddr(l, 1)) {
- reglcgen(&nod5, l, Z);
- l = &nod5;
- evacaxdx(l);
- }
- }
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- evacaxdx(r->left);
- evacaxdx(r->right);
- if(l->complex <= r->complex && !m && !vaddr(l, 1)) {
- reglcgen(&nod5, l, Z);
- l = &nod5;
- evacaxdx(l);
- }
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- c = Z;
- d = Z;
- if(!nodreg(&nod1, t->left, D_AX)) {
- if(t->left->reg != D_AX){
- t->left->reg = D_AX;
- reg[D_AX]++;
- }else if(reg[D_AX] == 0)
- fatal(Z, "vlong mul AX botch");
- }
- if(!nodreg(&nod2, t->right, D_DX)) {
- if(t->right->reg != D_DX){
- t->right->reg = D_DX;
- reg[D_DX]++;
- }else if(reg[D_DX] == 0)
- fatal(Z, "vlong mul DX botch");
- }
- if(m)
- sugen(l, t, 8);
- else
- loadpair(l, t);
- if(t->left->reg != D_AX) {
- c = &nod3;
- regsalloc(c, t->left);
- gmove(&nod1, c);
- gmove(t->left, &nod1);
- zapreg(t->left);
- }
- if(t->right->reg != D_DX) {
- d = &nod4;
- regsalloc(d, t->right);
- gmove(&nod2, d);
- gmove(t->right, &nod2);
- zapreg(t->right);
- }
- if(c != Z || d != Z) {
- s = regpair(Z, n);
- s->left = &nod1;
- s->right = &nod2;
- }
- else
- s = t;
- if(r->op == OCONST) {
- if(hi64v(r) == 0)
- biggen(s, r, Z, 0, mulc32, nil);
- else
- biggen(s, r, Z, 0, mulc64, nil);
- }
- else
- biggen(s, r, Z, 0, mull, nil);
- instpair(t, Z);
- if(c != Z) {
- gmove(&nod1, t->left);
- gmove(&nod3, &nod1);
- }
- if(d != Z) {
- gmove(&nod2, t->right);
- gmove(&nod4, &nod2);
- }
- if(r->op == OREGPAIR)
- freepair(r);
- if(!m)
- storepair(t, l, 0);
- if(l == &nod5)
- regfree(l);
- if(!dr) {
- if(nn != Z)
- storepair(t, nn, 1);
- else
- freepair(t);
- }
- return 1;
-
- case OASADD:
- args = ADDargs;
- goto vasop;
- case OASAND:
- args = ANDargs;
- goto vasop;
- case OASOR:
- args = ORargs;
- goto vasop;
- case OASSUB:
- args = SUBargs;
- goto vasop;
- case OASXOR:
- args = XORargs;
- goto vasop;
-
- vasop:
- l = n->left;
- r = n->right;
- dr = nn != Z && nn->op == OREGPAIR;
- m = 0;
- if(l->complex > r->complex) {
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- m = 1;
- }
- }
- else {
- if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- m = 1;
- }
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- }
- if(nn != Z) {
- if(n->op == OASSUB)
- biggen(l, r, Z, 0, sub10, args);
- else
- biggen(r, l, Z, 0, binoptmp, args);
- storepair(r, l, 0);
- }
- else {
- if(m)
- biggen(l, r, Z, 0, binop00, args);
- else
- biggen(l, r, Z, 0, binoptmp, args);
- }
- if(l == &nod1)
- regfree(&nod1);
- if(m) {
- if(nn == Z)
- freepair(r);
- else if(!dr)
- storepair(r, nn, 1);
- }
- return 1;
-
- case OASASHL:
- args = nil;
- optab = asshlltab;
- goto assh;
- case OASLSHR:
- args = shrlargs;
- optab = asshrltab;
- goto assh;
- case OASASHR:
- args = sarlargs;
- optab = asshrltab;
- goto assh;
-
- assh:
- c = Z;
- l = n->left;
- r = n->right;
- if(r->op == OCONST) {
- m = r->vconst & 63;
- if(m < 32)
- m = SAclo;
- else if(m == 32)
- m = SAc32;
- else
- m = SAchi;
- }
- else
- m = SAgen;
- if(l->complex > r->complex) {
- if(!vaddr(l, 0)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- if(m == SAgen) {
- t = &nod2;
- if(l->reg == D_CX) {
- regalloc(t, r, Z);
- gmove(l, t);
- l->reg = t->reg;
- t->reg = D_CX;
- }
- else
- c = snarfreg(nn, t, D_CX, r, &nod3);
- cgen(r, t);
- r = t;
- }
- }
- else {
- if(m == SAgen) {
- t = &nod2;
- c = snarfreg(nn, t, D_CX, r, &nod3);
- cgen(r, t);
- r = t;
- }
- if(!vaddr(l, 0)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- }
-
- if(nn != Z) {
- m += SAdgen - SAgen;
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, r, d, 0, optab[m], args);
- if(l == &nod1) {
- regfree(&nod1);
- l = Z;
- }
- if(r == &nod2 && c == Z) {
- regfree(&nod2);
- r = Z;
- }
- if(d != nn)
- storepair(d, nn, 1);
- }
- else
- biggen(l, r, Z, 0, optab[m], args);
-
- if(c != Z) {
- gins(AMOVL, c, r);
- regfree(c);
- }
- if(l == &nod1)
- regfree(&nod1);
- if(r == &nod2)
- regfree(&nod2);
- return 1;
-
- case OPOSTINC:
- args = ADDargs;
- cp = incdecpost;
- goto vinc;
- case OPOSTDEC:
- args = SUBargs;
- cp = incdecpost;
- goto vinc;
- case OPREINC:
- args = ADDargs;
- cp = incdecpre;
- goto vinc;
- case OPREDEC:
- args = SUBargs;
- cp = incdecpre;
- goto vinc;
-
- vinc:
- l = n->left;
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
-
- if(nn != Z) {
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, Z, d, 0, cp, args);
- if(l == &nod1) {
- regfree(&nod1);
- l = Z;
- }
- if(d != nn)
- storepair(d, nn, 1);
- }
- else
- biggen(l, Z, Z, 0, incdec, args);
-
- if(l == &nod1)
- regfree(&nod1);
- return 1;
-
- case OCAST:
- l = n->left;
- if(typev[l->type->etype]) {
- if(!vaddr(l, 1)) {
- if(l->complex + 1 > nn->complex) {
- d = regpair(Z, l);
- sugen(l, d, 8);
- if(!vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
- }
- else {
- if(!vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
- d = regpair(Z, l);
- sugen(l, d, 8);
- }
-// d->left->type = r->type;
- d->left->type = types[TLONG];
- gmove(d->left, r);
- freepair(d);
- }
- else {
- if(nn->op != OREGISTER && !vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
-// l->type = r->type;
- l->type = types[TLONG];
- gmove(l, r);
- }
- if(r != nn)
- regfree(r);
- }
- else {
- if(typeu[l->type->etype] || cond(l->op))
- si = TUNSIGNED;
- else
- si = TSIGNED;
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- if(nn->op == OREGPAIR) {
- m = instpair(nn, &nod1);
- biggen(&nod1, Z, nn, si == TSIGNED, castrp, nil);
- }
- else {
- m = 0;
- if(!vaddr(nn, si != TSIGNED)) {
- dt = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod2, nn, Z);
- nn->type = dt;
- nn = &nod2;
- }
- dt = nn->type;
- nn->type = types[TLONG];
- biggen(&nod1, Z, nn, si == TSIGNED, castrpa, nil);
- nn->type = dt;
- if(nn == &nod2)
- regfree(&nod2);
- }
- if(!m)
- regfree(&nod1);
- }
- return 1;
-
- default:
- if(n->op == OREGPAIR) {
- storepair(n, nn, 1);
- return 1;
- }
- if(nn->op == OREGPAIR) {
- loadpair(n, nn);
- return 1;
- }
- return 0;
- }
-finished:
- if(d != nn)
- storepair(d, nn, 1);
- return 1;
-}
-
-void
-testv(Node *n, int true)
-{
- Type *t;
- Node *nn, nod;
-
- switch(n->op) {
- case OINDREG:
- case ONAME:
- biggen(n, Z, Z, true, testi, nil);
- break;
-
- default:
- n = vfunc(n, n);
- if(n->addable >= INDEXED) {
- t = n->type;
- n->type = types[TLONG];
- reglcgen(&nod, n, Z);
- n->type = t;
- n = &nod;
- biggen(n, Z, Z, true, testi, nil);
- if(n == &nod)
- regfree(n);
- }
- else {
- nn = regpair(Z, n);
- sugen(n, nn, 8);
- biggen(nn, Z, Z, true, testi, nil);
- freepair(nn);
- }
- }
-}