2009-05-01 14:21:53 -06:00
|
|
|
// 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"
|
|
|
|
|
2009-08-21 17:29:19 -06:00
|
|
|
void
|
|
|
|
mgen(Node *n, Node *n1, Node *rg)
|
|
|
|
{
|
|
|
|
n1->ostk = 0;
|
|
|
|
n1->op = OEMPTY;
|
|
|
|
|
|
|
|
if(n->addable) {
|
|
|
|
*n1 = *n;
|
|
|
|
n1->ostk = 0;
|
|
|
|
if(n1->op == OREGISTER || n1->op == OINDREG)
|
|
|
|
reg[n->val.u.reg]++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(n->type->width > widthptr)
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(n1, n->type);
|
2009-08-21 17:29:19 -06:00
|
|
|
else
|
|
|
|
regalloc(n1, n->type, rg);
|
|
|
|
cgen(n, n1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mfree(Node *n)
|
|
|
|
{
|
2009-10-19 23:47:25 -06:00
|
|
|
if(n->op == OREGISTER)
|
2009-08-21 17:29:19 -06:00
|
|
|
regfree(n);
|
|
|
|
}
|
|
|
|
|
2009-05-01 14:21:53 -06:00
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* res = n;
|
|
|
|
* simplifies and calls gmove.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
cgen(Node *n, Node *res)
|
|
|
|
{
|
2009-05-28 15:25:54 -06:00
|
|
|
Node *nl, *nr, *r;
|
2009-10-09 08:37:49 -06:00
|
|
|
Node n1, n2, n3, f0, f1;
|
2009-08-18 20:20:33 -06:00
|
|
|
int a, w;
|
2009-05-28 15:25:54 -06:00
|
|
|
Prog *p1, *p2, *p3;
|
|
|
|
Addr addr;
|
|
|
|
|
|
|
|
if(debug['g']) {
|
|
|
|
dump("\ncgen-n", n);
|
|
|
|
dump("cgen-res", res);
|
|
|
|
}
|
|
|
|
if(n == N || n->type == T)
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
if(res == N || res->type == T)
|
|
|
|
fatal("cgen: res nil");
|
|
|
|
|
2009-06-23 16:30:59 -06:00
|
|
|
while(n->op == OCONVNOP)
|
|
|
|
n = n->left;
|
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
if(n->ullman >= UINF) {
|
|
|
|
if(n->op == OINDREG)
|
|
|
|
fatal("cgen: this is going to misscompile");
|
|
|
|
if(res->ullman >= UINF) {
|
|
|
|
tempname(&n1, n->type);
|
|
|
|
cgen(n, &n1);
|
|
|
|
cgen(&n1, res);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
}
|
2009-05-01 14:21:53 -06:00
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
if(isfat(n->type)) {
|
|
|
|
sgen(n, res, n->type->width);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2009-07-27 16:55:27 -06:00
|
|
|
// update addressability for string, slice
|
|
|
|
// can't do in walk because n->left->addable
|
|
|
|
// changes if n->left is an escaping local variable.
|
|
|
|
switch(n->op) {
|
|
|
|
case OLEN:
|
|
|
|
if(isslice(n->left->type) || istype(n->left->type, TSTRING))
|
|
|
|
n->addable = n->left->addable;
|
|
|
|
break;
|
|
|
|
case OCAP:
|
|
|
|
if(isslice(n->left->type))
|
|
|
|
n->addable = n->left->addable;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-10-06 15:48:39 -06:00
|
|
|
// if both are addressable, move
|
|
|
|
if(n->addable && res->addable) {
|
|
|
|
if (is64(n->type) || is64(res->type) || n->op == OREGISTER || res->op == OREGISTER) {
|
2009-09-18 00:07:52 -06:00
|
|
|
gmove(n, res);
|
|
|
|
} else {
|
|
|
|
regalloc(&n1, n->type, N);
|
|
|
|
gmove(n, &n1);
|
|
|
|
cgen(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2009-10-06 15:48:39 -06:00
|
|
|
// if both are not addressable, use a temporary.
|
|
|
|
if(!n->addable && !res->addable) {
|
|
|
|
// could use regalloc here sometimes,
|
|
|
|
// but have to check for ullman >= UINF.
|
|
|
|
tempname(&n1, n->type);
|
|
|
|
cgen(n, &n1);
|
|
|
|
cgen(&n1, res);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if result is not addressable directly but n is,
|
|
|
|
// compute its address and then store via the address.
|
|
|
|
if(!res->addable) {
|
|
|
|
igen(res, &n1, N);
|
|
|
|
cgen(n, &n1);
|
|
|
|
regfree(&n1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if n is sudoaddable generate addr and move
|
|
|
|
if (!is64(n->type) && !is64(res->type)) {
|
|
|
|
a = optoas(OAS, n->type);
|
|
|
|
if(sudoaddable(a, n, &addr, &w)) {
|
|
|
|
if (res->op != OREGISTER) {
|
|
|
|
regalloc(&n2, res->type, N);
|
|
|
|
p1 = gins(a, N, &n2);
|
|
|
|
p1->from = addr;
|
|
|
|
if(debug['g'])
|
|
|
|
print("%P [ignore previous line]\n", p1);
|
|
|
|
gmove(&n2, res);
|
|
|
|
regfree(&n2);
|
|
|
|
} else {
|
|
|
|
p1 = gins(a, N, res);
|
|
|
|
p1->from = addr;
|
|
|
|
if(debug['g'])
|
|
|
|
print("%P [ignore previous line]\n", p1);
|
|
|
|
}
|
|
|
|
sudoclean();
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, the result is addressable but n is not.
|
|
|
|
// let's do some computation.
|
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
nl = n->left;
|
|
|
|
nr = n->right;
|
|
|
|
|
|
|
|
if(nl != N && nl->ullman >= UINF)
|
|
|
|
if(nr != N && nr->ullman >= UINF) {
|
|
|
|
tempname(&n1, nl->type);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
n2 = *n;
|
|
|
|
n2.left = &n1;
|
|
|
|
cgen(&n2, res);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2009-08-21 17:29:19 -06:00
|
|
|
// 64-bit ops are hard on 32-bit machine.
|
|
|
|
if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
|
|
|
|
switch(n->op) {
|
|
|
|
// math goes to cgen64.
|
|
|
|
case OMINUS:
|
|
|
|
case OCOM:
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
case OAND:
|
|
|
|
case OOR:
|
|
|
|
case OXOR:
|
|
|
|
cgen64(n, res);
|
|
|
|
return;
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
}
|
|
|
|
|
2009-10-09 08:37:49 -06:00
|
|
|
if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
|
|
|
|
goto flt;
|
2009-05-28 15:25:54 -06:00
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
dump("cgen", n);
|
|
|
|
fatal("cgen: unknown op %N", n);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// these call bgen to get a bool value
|
|
|
|
case OOROR:
|
|
|
|
case OANDAND:
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OLT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
case OGT:
|
|
|
|
case ONOT:
|
|
|
|
p1 = gbranch(AB, T);
|
|
|
|
p2 = pc;
|
|
|
|
gmove(nodbool(1), res);
|
|
|
|
p3 = gbranch(AB, T);
|
|
|
|
patch(p1, pc);
|
|
|
|
bgen(n, 1, p2);
|
|
|
|
gmove(nodbool(0), res);
|
|
|
|
patch(p3, pc);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OPLUS:
|
|
|
|
cgen(nl, res);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
// unary
|
|
|
|
case OCOM:
|
|
|
|
a = optoas(OXOR, nl->type);
|
|
|
|
regalloc(&n1, nl->type, N);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
nodconst(&n2, nl->type, -1);
|
|
|
|
gins(a, &n2, &n1);
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OMINUS:
|
2009-10-23 11:58:29 -06:00
|
|
|
nodconst(&n3, nl->type, 0);
|
|
|
|
regalloc(&n2, nl->type, res);
|
|
|
|
regalloc(&n1, nl->type, N);
|
|
|
|
gmove(&n3, &n2);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
gins(optoas(OSUB, nl->type), &n1, &n2);
|
|
|
|
gmove(&n2, res);
|
|
|
|
regfree(&n1);
|
|
|
|
regfree(&n2);
|
|
|
|
goto ret;
|
2009-05-28 15:25:54 -06:00
|
|
|
|
|
|
|
// symmetric binary
|
|
|
|
case OAND:
|
|
|
|
case OOR:
|
|
|
|
case OXOR:
|
|
|
|
case OADD:
|
|
|
|
case OMUL:
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
a = optoas(n->op, nl->type);
|
|
|
|
goto sbop;
|
2009-05-28 15:25:54 -06:00
|
|
|
|
|
|
|
// asymmetric binary
|
|
|
|
case OSUB:
|
|
|
|
a = optoas(n->op, nl->type);
|
|
|
|
goto abop;
|
|
|
|
|
2009-10-27 23:38:45 -06:00
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
cgen_shift(n->op, nl, nr, res);
|
|
|
|
break;
|
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
case OCONV:
|
2009-08-21 17:29:19 -06:00
|
|
|
if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
|
|
|
|
cgen(nl, res);
|
|
|
|
break;
|
|
|
|
}
|
2009-10-11 21:01:11 -06:00
|
|
|
|
2009-08-21 17:29:19 -06:00
|
|
|
mgen(nl, &n1, res);
|
2009-05-28 15:25:54 -06:00
|
|
|
gmove(&n1, res);
|
2009-08-21 17:29:19 -06:00
|
|
|
mfree(&n1);
|
2009-05-28 15:25:54 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ODOT:
|
|
|
|
case ODOTPTR:
|
|
|
|
case OINDEX:
|
|
|
|
case OIND:
|
|
|
|
case ONAME: // PHEAP or PPARAMREF var
|
|
|
|
igen(n, &n1, res);
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLEN:
|
2009-10-23 21:31:03 -06:00
|
|
|
if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
|
2009-09-28 16:40:13 -06:00
|
|
|
// map has len in the first 32-bit word.
|
2009-05-28 15:25:54 -06:00
|
|
|
// a zero pointer means zero length
|
|
|
|
regalloc(&n1, types[tptr], res);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
|
|
|
|
nodconst(&n2, types[tptr], 0);
|
2009-09-18 00:07:52 -06:00
|
|
|
regalloc(&n3, n2.type, N);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n2, &n3);
|
|
|
|
gcmp(optoas(OCMP, types[tptr]), &n1, &n3);
|
2009-09-18 00:07:52 -06:00
|
|
|
regfree(&n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
p1 = gbranch(optoas(OEQ, types[tptr]), T);
|
|
|
|
|
|
|
|
n2 = n1;
|
|
|
|
n2.op = OINDREG;
|
|
|
|
n2.type = types[TINT32];
|
|
|
|
gmove(&n2, &n1);
|
|
|
|
|
|
|
|
patch(p1, pc);
|
|
|
|
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(istype(nl->type, TSTRING) || isslice(nl->type)) {
|
2009-09-28 16:40:13 -06:00
|
|
|
// both slice and string have len one pointer into the struct.
|
|
|
|
igen(nl, &n1, res);
|
|
|
|
n1.op = OREGISTER; // was OINDREG
|
|
|
|
regalloc(&n2, types[TUINT32], &n1);
|
2009-05-28 15:25:54 -06:00
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[TUINT32];
|
|
|
|
n1.xoffset = Array_nel;
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n1, &n2);
|
|
|
|
gmove(&n2, res);
|
2009-05-28 15:25:54 -06:00
|
|
|
regfree(&n1);
|
2009-09-28 16:40:13 -06:00
|
|
|
regfree(&n2);
|
2009-05-28 15:25:54 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fatal("cgen: OLEN: unknown type %lT", nl->type);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCAP:
|
2009-10-23 21:31:03 -06:00
|
|
|
if(istype(nl->type, TCHAN)) {
|
|
|
|
// chan has cap in the second 32-bit word.
|
|
|
|
// a zero pointer means zero length
|
|
|
|
regalloc(&n1, types[tptr], res);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
|
|
|
|
nodconst(&n2, types[tptr], 0);
|
|
|
|
regalloc(&n3, n2.type, N);
|
|
|
|
gmove(&n2, &n3);
|
|
|
|
gcmp(optoas(OCMP, types[tptr]), &n1, &n3);
|
|
|
|
regfree(&n3);
|
|
|
|
p1 = gbranch(optoas(OEQ, types[tptr]), T);
|
|
|
|
|
|
|
|
n2 = n1;
|
|
|
|
n2.op = OINDREG;
|
|
|
|
n2.xoffset = 4;
|
|
|
|
n2.type = types[TINT32];
|
|
|
|
gmove(&n2, &n1);
|
|
|
|
|
|
|
|
patch(p1, pc);
|
|
|
|
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
if(isslice(nl->type)) {
|
|
|
|
regalloc(&n1, types[tptr], res);
|
|
|
|
agen(nl, &n1);
|
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[TUINT32];
|
|
|
|
n1.xoffset = Array_cap;
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fatal("cgen: OCAP: unknown type %lT", nl->type);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OADDR:
|
|
|
|
agen(nl, res);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALLMETH:
|
|
|
|
cgen_callmeth(n, 0);
|
|
|
|
cgen_callret(n, res);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALLINTER:
|
|
|
|
cgen_callinter(n, res, 0);
|
|
|
|
cgen_callret(n, res);
|
|
|
|
break;
|
|
|
|
|
2009-07-30 17:53:08 -06:00
|
|
|
case OCALLFUNC:
|
2009-05-28 15:25:54 -06:00
|
|
|
cgen_call(n, 0);
|
|
|
|
cgen_callret(n, res);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMOD:
|
|
|
|
case ODIV:
|
2009-08-19 21:17:09 -06:00
|
|
|
a = optoas(n->op, nl->type);
|
|
|
|
goto abop;
|
2009-05-28 15:25:54 -06:00
|
|
|
}
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
sbop: // symmetric binary
|
|
|
|
if(nl->ullman < nr->ullman) {
|
|
|
|
r = nl;
|
|
|
|
nl = nr;
|
|
|
|
nr = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
abop: // asymmetric binary
|
2009-09-30 15:28:18 -06:00
|
|
|
// TODO(kaib): use fewer registers here.
|
2009-05-28 15:25:54 -06:00
|
|
|
if(nl->ullman >= nr->ullman) {
|
|
|
|
regalloc(&n1, nl->type, res);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
regalloc(&n2, nr->type, N);
|
|
|
|
cgen(nr, &n2);
|
|
|
|
} else {
|
|
|
|
regalloc(&n2, nr->type, N);
|
|
|
|
cgen(nr, &n2);
|
|
|
|
regalloc(&n1, nl->type, res);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
}
|
|
|
|
gins(a, &n2, &n1);
|
|
|
|
gmove(&n1, res);
|
|
|
|
regfree(&n1);
|
|
|
|
regfree(&n2);
|
|
|
|
goto ret;
|
|
|
|
|
2009-10-09 08:37:49 -06:00
|
|
|
flt: // floating-point.
|
|
|
|
regalloc(&f0, nl->type, res);
|
|
|
|
if(nr != N)
|
|
|
|
goto flt2;
|
|
|
|
|
|
|
|
if(n->op == OMINUS) {
|
|
|
|
nr = nodintconst(-1);
|
|
|
|
convlit(&nr, n->type);
|
|
|
|
n->op = OMUL;
|
|
|
|
goto flt2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// unary
|
|
|
|
cgen(nl, &f0);
|
|
|
|
if(n->op != OCONV && n->op != OPLUS)
|
|
|
|
gins(optoas(n->op, n->type), &f0, &f0);
|
|
|
|
gmove(&f0, res);
|
|
|
|
regfree(&f0);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
flt2: // binary
|
|
|
|
if(nl->ullman >= nr->ullman) {
|
|
|
|
cgen(nl, &f0);
|
|
|
|
regalloc(&f1, n->type, N);
|
|
|
|
gmove(&f0, &f1);
|
|
|
|
cgen(nr, &f0);
|
2009-10-24 23:47:25 -06:00
|
|
|
gins(optoas(n->op, n->type), &f0, &f1);
|
2009-10-09 08:37:49 -06:00
|
|
|
} else {
|
|
|
|
cgen(nr, &f0);
|
|
|
|
regalloc(&f1, n->type, N);
|
2009-11-06 14:51:17 -07:00
|
|
|
cgen(nl, &f1);
|
2009-10-24 23:47:25 -06:00
|
|
|
gins(optoas(n->op, n->type), &f0, &f1);
|
2009-10-09 08:37:49 -06:00
|
|
|
}
|
|
|
|
gmove(&f1, res);
|
|
|
|
regfree(&f0);
|
|
|
|
regfree(&f1);
|
|
|
|
goto ret;
|
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
ret:
|
2009-05-01 14:21:53 -06:00
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* res = &n;
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
agen(Node *n, Node *res)
|
|
|
|
{
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
Node *nl, *nr;
|
2009-09-30 19:56:37 -06:00
|
|
|
Node n1, n2, n3, n4, n5, tmp;
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
Prog *p1;
|
|
|
|
uint32 w;
|
|
|
|
uint64 v;
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
if(debug['g']) {
|
|
|
|
dump("\nagen-res", res);
|
|
|
|
dump("agen-r", n);
|
|
|
|
}
|
2009-08-21 17:29:19 -06:00
|
|
|
if(n == N || n->type == T || res == N || res->type == T)
|
|
|
|
fatal("agen");
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
|
|
|
while(n->op == OCONVNOP)
|
|
|
|
n = n->left;
|
|
|
|
|
|
|
|
if(n->addable) {
|
|
|
|
memset(&n1, 0, sizeof n1);
|
|
|
|
n1.op = OADDR;
|
|
|
|
n1.left = n;
|
|
|
|
regalloc(&n2, types[tptr], res);
|
|
|
|
gins(AMOVW, &n1, &n2);
|
|
|
|
gmove(&n2, res);
|
|
|
|
regfree(&n2);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
nl = n->left;
|
|
|
|
nr = n->right;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
fatal("agen: unknown op %N", n);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALLMETH:
|
|
|
|
cgen_callmeth(n, 0);
|
|
|
|
cgen_aret(n, res);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALLINTER:
|
|
|
|
cgen_callinter(n, res, 0);
|
|
|
|
cgen_aret(n, res);
|
|
|
|
break;
|
|
|
|
|
2009-07-30 17:53:08 -06:00
|
|
|
case OCALLFUNC:
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
cgen_call(n, 0);
|
|
|
|
cgen_aret(n, res);
|
|
|
|
break;
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
case OINDEX:
|
2009-09-28 16:40:13 -06:00
|
|
|
// TODO(rsc): uint64 indices
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
w = n->type->width;
|
2009-09-28 16:40:13 -06:00
|
|
|
if(nr->addable) {
|
|
|
|
agenr(nl, &n3, res);
|
|
|
|
if(!isconst(nr, CTINT)) {
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&tmp, types[TINT32]);
|
2009-09-28 16:40:13 -06:00
|
|
|
cgen(nr, &tmp);
|
|
|
|
regalloc(&n1, tmp.type, N);
|
|
|
|
gmove(&tmp, &n1);
|
|
|
|
}
|
|
|
|
} else if(nl->addable) {
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(!isconst(nr, CTINT)) {
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&tmp, types[TINT32]);
|
2009-09-28 16:40:13 -06:00
|
|
|
cgen(nr, &tmp);
|
|
|
|
regalloc(&n1, tmp.type, N);
|
|
|
|
gmove(&tmp, &n1);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
regalloc(&n3, types[tptr], res);
|
|
|
|
agen(nl, &n3);
|
2009-09-28 16:40:13 -06:00
|
|
|
} else {
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&tmp, types[TINT32]);
|
2009-09-28 16:40:13 -06:00
|
|
|
cgen(nr, &tmp);
|
|
|
|
nr = &tmp;
|
|
|
|
agenr(nl, &n3, res);
|
|
|
|
regalloc(&n1, tmp.type, N);
|
|
|
|
gins(optoas(OAS, tmp.type), &tmp, &n1);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// &a is in &n3 (allocated in res)
|
|
|
|
// i is in &n1 (if not constant)
|
|
|
|
// w is width
|
|
|
|
|
|
|
|
if(w == 0)
|
|
|
|
fatal("index is zero width");
|
|
|
|
|
|
|
|
// constant index
|
|
|
|
if(isconst(nr, CTINT)) {
|
|
|
|
v = mpgetfix(nr->val.u.xval);
|
|
|
|
if(isslice(nl->type)) {
|
|
|
|
|
|
|
|
if(!debug['B']) {
|
|
|
|
n1 = n3;
|
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[tptr];
|
|
|
|
n1.xoffset = Array_nel;
|
2009-09-30 19:56:37 -06:00
|
|
|
regalloc(&n4, n1.type, N);
|
|
|
|
cgen(&n1, &n4);
|
2009-08-18 20:20:33 -06:00
|
|
|
nodconst(&n2, types[TUINT32], v);
|
2009-09-30 19:56:37 -06:00
|
|
|
regalloc(&n5, n2.type, N);
|
|
|
|
gmove(&n2, &n5);
|
|
|
|
gcmp(optoas(OCMP, types[TUINT32]), &n4, &n5);
|
2009-09-18 00:07:52 -06:00
|
|
|
regfree(&n4);
|
2009-09-30 19:56:37 -06:00
|
|
|
regfree(&n5);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
|
|
|
|
ginscall(throwindex, 0);
|
|
|
|
patch(p1, pc);
|
|
|
|
}
|
|
|
|
|
|
|
|
n1 = n3;
|
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[tptr];
|
|
|
|
n1.xoffset = Array_array;
|
|
|
|
gmove(&n1, &n3);
|
|
|
|
} else
|
|
|
|
if(!debug['B']) {
|
|
|
|
if(v < 0)
|
|
|
|
yyerror("out of bounds on array");
|
|
|
|
else
|
|
|
|
if(v >= nl->type->bound)
|
|
|
|
yyerror("out of bounds on array");
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
nodconst(&n2, types[tptr], v*w);
|
2009-09-28 16:40:13 -06:00
|
|
|
regalloc(&n4, n2.type, N);
|
|
|
|
gmove(&n2, &n4);
|
2009-09-30 19:56:37 -06:00
|
|
|
gins(optoas(OADD, types[tptr]), &n4, &n3);
|
2009-09-28 16:40:13 -06:00
|
|
|
regfree(&n4);
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
gmove(&n3, res);
|
|
|
|
regfree(&n3);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
// type of the index
|
2009-08-18 20:20:33 -06:00
|
|
|
t = types[TUINT32];
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(issigned[n1.type->etype])
|
2009-08-18 20:20:33 -06:00
|
|
|
t = types[TINT32];
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
regalloc(&n2, t, &n1); // i
|
|
|
|
gmove(&n1, &n2);
|
|
|
|
regfree(&n1);
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(!debug['B']) {
|
|
|
|
// check bounds
|
2009-09-28 16:40:13 -06:00
|
|
|
regalloc(&n4, types[TUINT32], N);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(isslice(nl->type)) {
|
|
|
|
n1 = n3;
|
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[tptr];
|
|
|
|
n1.xoffset = Array_nel;
|
2009-09-28 16:40:13 -06:00
|
|
|
cgen(&n1, &n4);
|
2009-09-18 00:07:52 -06:00
|
|
|
} else {
|
2009-08-18 20:20:33 -06:00
|
|
|
nodconst(&n1, types[TUINT32], nl->type->bound);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n1, &n4);
|
2009-09-18 00:07:52 -06:00
|
|
|
}
|
2009-09-28 16:40:13 -06:00
|
|
|
gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
|
2009-09-18 00:07:52 -06:00
|
|
|
regfree(&n4);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
|
|
|
ginscall(throwindex, 0);
|
|
|
|
patch(p1, pc);
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(isslice(nl->type)) {
|
|
|
|
n1 = n3;
|
|
|
|
n1.op = OINDREG;
|
|
|
|
n1.type = types[tptr];
|
|
|
|
n1.xoffset = Array_array;
|
|
|
|
gmove(&n1, &n3);
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
if(w == 1 || w == 2 || w == 4 || w == 8) {
|
2009-09-28 16:40:13 -06:00
|
|
|
memset(&n4, 0, sizeof n4);
|
|
|
|
n4.op = OADDR;
|
|
|
|
n4.left = &n2;
|
|
|
|
cgen(&n4, &n3);
|
2009-10-15 23:16:31 -06:00
|
|
|
if (w == 1)
|
|
|
|
gins(AADD, &n2, &n3);
|
|
|
|
else if(w == 2)
|
|
|
|
gshift(AADD, &n2, SHIFT_LL, 1, &n3);
|
|
|
|
else if(w == 4)
|
|
|
|
gshift(AADD, &n2, SHIFT_LL, 2, &n3);
|
|
|
|
else if(w == 8)
|
|
|
|
gshift(AADD, &n2, SHIFT_LL, 3, &n3);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
} else {
|
2009-09-28 16:40:13 -06:00
|
|
|
regalloc(&n4, t, N);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
nodconst(&n1, t, w);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n1, &n4);
|
|
|
|
gins(optoas(OMUL, t), &n4, &n2);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
2009-09-28 16:40:13 -06:00
|
|
|
regfree(&n4);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
gmove(&n3, res);
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
gmove(&n3, res);
|
|
|
|
regfree(&n2);
|
|
|
|
regfree(&n3);
|
|
|
|
break;
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
case ONAME:
|
|
|
|
// should only get here with names in this func.
|
|
|
|
if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
|
|
|
|
dump("bad agen", n);
|
|
|
|
fatal("agen: bad ONAME funcdepth %d != %d",
|
|
|
|
n->funcdepth, funcdepth);
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
// should only get here for heap vars or paramref
|
|
|
|
if(!(n->class & PHEAP) && n->class != PPARAMREF) {
|
|
|
|
dump("bad agen", n);
|
|
|
|
fatal("agen: bad ONAME class %#x", n->class);
|
|
|
|
}
|
|
|
|
cgen(n->heapaddr, res);
|
|
|
|
if(n->xoffset != 0) {
|
2009-08-18 20:20:33 -06:00
|
|
|
nodconst(&n1, types[TINT32], n->xoffset);
|
2009-10-02 10:06:51 -06:00
|
|
|
regalloc(&n2, n1.type, N);
|
|
|
|
regalloc(&n3, types[TINT32], N);
|
|
|
|
gmove(&n1, &n2);
|
|
|
|
gmove(res, &n3);
|
|
|
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
|
|
|
gmove(&n3, res);
|
|
|
|
regfree(&n2);
|
|
|
|
regfree(&n3);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OIND:
|
|
|
|
cgen(nl, res);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ODOT:
|
|
|
|
agen(nl, res);
|
|
|
|
if(n->xoffset != 0) {
|
2009-08-18 20:20:33 -06:00
|
|
|
nodconst(&n1, types[TINT32], n->xoffset);
|
2009-10-02 10:06:51 -06:00
|
|
|
regalloc(&n2, n1.type, N);
|
|
|
|
regalloc(&n3, types[TINT32], N);
|
|
|
|
gmove(&n1, &n2);
|
|
|
|
gmove(res, &n3);
|
|
|
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
|
|
|
gmove(&n3, res);
|
|
|
|
regfree(&n2);
|
|
|
|
regfree(&n3);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ODOTPTR:
|
|
|
|
cgen(nl, res);
|
|
|
|
if(n->xoffset != 0) {
|
2009-10-26 22:49:32 -06:00
|
|
|
// explicit check for nil if struct is large enough
|
|
|
|
// that we might derive too big a pointer.
|
|
|
|
if(nl->type->type->width >= unmappedzero) {
|
|
|
|
regalloc(&n1, types[tptr], N);
|
|
|
|
gmove(res, &n1);
|
|
|
|
p1 = gins(AMOVW, &n1, &n1);
|
|
|
|
p1->from.type = D_OREG;
|
|
|
|
p1->from.offset = 0;
|
|
|
|
regfree(&n1);
|
|
|
|
}
|
2009-08-18 20:20:33 -06:00
|
|
|
nodconst(&n1, types[TINT32], n->xoffset);
|
2009-10-02 10:06:51 -06:00
|
|
|
regalloc(&n2, n1.type, N);
|
|
|
|
regalloc(&n3, types[tptr], N);
|
|
|
|
gmove(&n1, &n2);
|
|
|
|
gmove(res, &n3);
|
|
|
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
|
|
|
gmove(&n3, res);
|
|
|
|
regfree(&n2);
|
|
|
|
regfree(&n3);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-05-01 14:21:53 -06:00
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
ret:
|
|
|
|
;
|
2009-05-01 14:21:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* newreg = &n;
|
|
|
|
* res = newreg
|
|
|
|
*
|
|
|
|
* on exit, a has been changed to be *newreg.
|
|
|
|
* caller must regfree(a).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
igen(Node *n, Node *a, Node *res)
|
|
|
|
{
|
|
|
|
regalloc(a, types[tptr], res);
|
|
|
|
agen(n, a);
|
|
|
|
a->op = OINDREG;
|
|
|
|
a->type = n->type;
|
|
|
|
}
|
|
|
|
|
2009-09-28 16:40:13 -06:00
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* newreg = &n;
|
|
|
|
*
|
|
|
|
* caller must regfree(a).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
agenr(Node *n, Node *a, Node *res)
|
|
|
|
{
|
|
|
|
Node n1;
|
|
|
|
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&n1, types[tptr]);
|
2009-09-28 16:40:13 -06:00
|
|
|
agen(n, &n1);
|
|
|
|
regalloc(a, types[tptr], res);
|
|
|
|
gmove(&n1, a);
|
|
|
|
}
|
|
|
|
|
2009-05-01 14:21:53 -06:00
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* if(n == true) goto to;
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
bgen(Node *n, int true, Prog *to)
|
|
|
|
{
|
2009-05-28 15:25:54 -06:00
|
|
|
int et, a;
|
|
|
|
Node *nl, *nr, *r;
|
2009-09-30 19:56:37 -06:00
|
|
|
Node n1, n2, n3, n4, tmp;
|
2009-05-28 15:25:54 -06:00
|
|
|
Prog *p1, *p2;
|
2009-05-01 14:21:53 -06:00
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
if(debug['g']) {
|
|
|
|
dump("\nbgen", n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(n == N)
|
|
|
|
n = nodbool(1);
|
|
|
|
|
|
|
|
nl = n->left;
|
|
|
|
nr = n->right;
|
|
|
|
|
|
|
|
if(n->type == T) {
|
2009-07-28 18:02:05 -06:00
|
|
|
convlit(&n, types[TBOOL]);
|
2009-05-28 15:25:54 -06:00
|
|
|
if(n->type == T)
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
et = n->type->etype;
|
|
|
|
if(et != TBOOL) {
|
|
|
|
yyerror("cgen: bad type %T for %O", n->type, n->op);
|
|
|
|
patch(gins(AEND, N, N), to);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
nl = N;
|
|
|
|
nr = N;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
def:
|
|
|
|
regalloc(&n1, n->type, N);
|
|
|
|
cgen(n, &n1);
|
|
|
|
nodconst(&n2, n->type, 0);
|
2009-06-26 23:04:30 -06:00
|
|
|
regalloc(&n3, n->type, N);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n2, &n3);
|
|
|
|
gcmp(optoas(OCMP, n->type), &n1, &n3);
|
2009-06-26 23:04:30 -06:00
|
|
|
a = ABNE;
|
2009-05-28 15:25:54 -06:00
|
|
|
if(!true)
|
|
|
|
a = ABEQ;
|
|
|
|
patch(gbranch(a, n->type), to);
|
|
|
|
regfree(&n1);
|
2009-06-26 23:04:30 -06:00
|
|
|
regfree(&n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OLITERAL:
|
|
|
|
// need to ask if it is bool?
|
|
|
|
if(!true == !n->val.u.bval)
|
|
|
|
patch(gbranch(AB, T), to);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ONAME:
|
|
|
|
if(n->addable == 0)
|
|
|
|
goto def;
|
|
|
|
nodconst(&n1, n->type, 0);
|
2009-09-15 17:12:47 -06:00
|
|
|
regalloc(&n2, n->type, N);
|
|
|
|
regalloc(&n3, n->type, N);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&n1, &n2);
|
2009-09-15 17:12:47 -06:00
|
|
|
cgen(n, &n3);
|
2009-09-28 16:40:13 -06:00
|
|
|
gcmp(optoas(OCMP, n->type), &n2, &n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
a = ABNE;
|
|
|
|
if(!true)
|
|
|
|
a = ABEQ;
|
|
|
|
patch(gbranch(a, n->type), to);
|
2009-09-15 17:12:47 -06:00
|
|
|
regfree(&n2);
|
|
|
|
regfree(&n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OANDAND:
|
|
|
|
if(!true)
|
|
|
|
goto caseor;
|
|
|
|
|
|
|
|
caseand:
|
|
|
|
p1 = gbranch(AB, T);
|
|
|
|
p2 = gbranch(AB, T);
|
|
|
|
patch(p1, pc);
|
|
|
|
bgen(n->left, !true, p2);
|
|
|
|
bgen(n->right, !true, p2);
|
|
|
|
p1 = gbranch(AB, T);
|
|
|
|
patch(p1, to);
|
|
|
|
patch(p2, pc);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OOROR:
|
|
|
|
if(!true)
|
|
|
|
goto caseand;
|
|
|
|
|
|
|
|
caseor:
|
|
|
|
bgen(n->left, true, to);
|
|
|
|
bgen(n->right, true, to);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OLT:
|
|
|
|
case OGT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
nr = n->right;
|
|
|
|
if(nr == N || nr->type == T)
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ONOT: // unary
|
|
|
|
nl = n->left;
|
|
|
|
if(nl == N || nl->type == T)
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
|
|
|
|
case ONOT:
|
|
|
|
bgen(nl, !true, to);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OLT:
|
|
|
|
case OGT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
a = n->op;
|
|
|
|
if(!true)
|
|
|
|
a = brcom(a);
|
|
|
|
|
|
|
|
// make simplest on right
|
|
|
|
if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
|
|
|
|
a = brrev(a);
|
|
|
|
r = nl;
|
|
|
|
nl = nr;
|
|
|
|
nr = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isslice(nl->type)) {
|
|
|
|
// only valid to cmp darray to literal nil
|
|
|
|
if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
|
|
|
|
yyerror("illegal array comparison");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
a = optoas(a, types[tptr]);
|
|
|
|
regalloc(&n1, types[tptr], N);
|
2009-09-18 00:07:52 -06:00
|
|
|
regalloc(&n3, types[tptr], N);
|
2009-09-30 19:56:37 -06:00
|
|
|
regalloc(&n4, types[tptr], N);
|
2009-05-28 15:25:54 -06:00
|
|
|
agen(nl, &n1);
|
|
|
|
n2 = n1;
|
|
|
|
n2.op = OINDREG;
|
|
|
|
n2.xoffset = Array_array;
|
2009-09-30 19:56:37 -06:00
|
|
|
gmove(&n2, &n4);
|
2009-05-28 15:25:54 -06:00
|
|
|
nodconst(&tmp, types[tptr], 0);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&tmp, &n3);
|
2009-09-30 19:56:37 -06:00
|
|
|
gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
patch(gbranch(a, types[tptr]), to);
|
2009-09-30 19:56:37 -06:00
|
|
|
regfree(&n4);
|
2009-09-18 00:07:52 -06:00
|
|
|
regfree(&n3);
|
2009-05-28 15:25:54 -06:00
|
|
|
regfree(&n1);
|
|
|
|
break;
|
|
|
|
}
|
2009-10-11 21:01:11 -06:00
|
|
|
|
2009-08-24 16:20:37 -06:00
|
|
|
if(isinter(nl->type)) {
|
|
|
|
// front end shold only leave cmp to literal nil
|
|
|
|
if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
|
|
|
|
yyerror("illegal interface comparison");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
a = optoas(a, types[tptr]);
|
|
|
|
regalloc(&n1, types[tptr], N);
|
2009-09-18 00:07:52 -06:00
|
|
|
regalloc(&n3, types[tptr], N);
|
2009-09-30 19:56:37 -06:00
|
|
|
regalloc(&n4, types[tptr], N);
|
2009-08-24 16:20:37 -06:00
|
|
|
agen(nl, &n1);
|
|
|
|
n2 = n1;
|
|
|
|
n2.op = OINDREG;
|
|
|
|
n2.xoffset = 0;
|
2009-09-30 19:56:37 -06:00
|
|
|
gmove(&n2, &n4);
|
2009-08-24 16:20:37 -06:00
|
|
|
nodconst(&tmp, types[tptr], 0);
|
2009-09-28 16:40:13 -06:00
|
|
|
gmove(&tmp, &n3);
|
2009-09-30 19:56:37 -06:00
|
|
|
gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
|
2009-08-24 16:20:37 -06:00
|
|
|
patch(gbranch(a, types[tptr]), to);
|
|
|
|
regfree(&n1);
|
2009-09-18 00:07:52 -06:00
|
|
|
regfree(&n3);
|
2009-09-30 19:56:37 -06:00
|
|
|
regfree(&n4);
|
2009-08-24 16:20:37 -06:00
|
|
|
break;
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
2009-10-06 10:47:46 -06:00
|
|
|
if(is64(nr->type)) {
|
|
|
|
if(!nl->addable) {
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&n1, nl->type);
|
2009-10-06 10:47:46 -06:00
|
|
|
cgen(nl, &n1);
|
|
|
|
nl = &n1;
|
|
|
|
}
|
|
|
|
if(!nr->addable) {
|
2009-10-19 23:47:25 -06:00
|
|
|
tempname(&n2, nr->type);
|
2009-10-06 10:47:46 -06:00
|
|
|
cgen(nr, &n2);
|
|
|
|
nr = &n2;
|
|
|
|
}
|
|
|
|
cmp64(nl, nr, a, to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-05-28 15:25:54 -06:00
|
|
|
a = optoas(a, nr->type);
|
|
|
|
|
|
|
|
if(nr->ullman >= UINF) {
|
|
|
|
regalloc(&n1, nr->type, N);
|
|
|
|
cgen(nr, &n1);
|
|
|
|
|
|
|
|
tempname(&tmp, nr->type);
|
|
|
|
gmove(&n1, &tmp);
|
|
|
|
regfree(&n1);
|
|
|
|
|
|
|
|
regalloc(&n1, nl->type, N);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
|
2009-09-18 00:07:52 -06:00
|
|
|
regalloc(&n2, nr->type, N);
|
2009-05-28 15:25:54 -06:00
|
|
|
cgen(&tmp, &n2);
|
|
|
|
|
2009-09-28 16:40:13 -06:00
|
|
|
gcmp(optoas(OCMP, nr->type), &n1, &n2);
|
2009-05-28 15:25:54 -06:00
|
|
|
patch(gbranch(a, nr->type), to);
|
|
|
|
|
|
|
|
regfree(&n1);
|
|
|
|
regfree(&n2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
regalloc(&n1, nl->type, N);
|
|
|
|
cgen(nl, &n1);
|
|
|
|
|
|
|
|
regalloc(&n2, nr->type, N);
|
|
|
|
cgen(nr, &n2);
|
|
|
|
|
2009-09-28 16:40:13 -06:00
|
|
|
gcmp(optoas(OCMP, nr->type), &n1, &n2);
|
2009-05-28 15:25:54 -06:00
|
|
|
patch(gbranch(a, nr->type), to);
|
|
|
|
|
|
|
|
regfree(&n1);
|
|
|
|
regfree(&n2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
ret:
|
|
|
|
;
|
2009-05-01 14:21:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* n is on stack, either local variable
|
|
|
|
* or return value from function call.
|
|
|
|
* return n's offset from SP.
|
|
|
|
*/
|
|
|
|
int32
|
|
|
|
stkof(Node *n)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
Iter flist;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
case OINDREG:
|
|
|
|
return n->xoffset;
|
|
|
|
|
|
|
|
case OCALLMETH:
|
|
|
|
case OCALLINTER:
|
2009-07-30 17:53:08 -06:00
|
|
|
case OCALLFUNC:
|
2009-05-01 14:21:53 -06:00
|
|
|
t = n->left->type;
|
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
|
|
|
|
t = structfirst(&flist, getoutarg(t));
|
|
|
|
if(t != T)
|
|
|
|
return t->width;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// botch - probably failing to recognize address
|
|
|
|
// arithmetic on the above. eg INDEX and DOT
|
|
|
|
return -1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* block copy:
|
2009-07-07 00:04:56 -06:00
|
|
|
* memmove(&res, &n, w);
|
2009-10-11 21:01:11 -06:00
|
|
|
* NB: character copy assumed little endian architecture
|
2009-05-01 14:21:53 -06:00
|
|
|
*/
|
|
|
|
void
|
2009-07-07 00:04:56 -06:00
|
|
|
sgen(Node *n, Node *res, int32 w)
|
2009-05-01 14:21:53 -06:00
|
|
|
{
|
2009-07-13 23:04:24 -06:00
|
|
|
Node dst, src, tmp, nend;
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
int32 c, q, odst, osrc;
|
2009-08-21 17:29:19 -06:00
|
|
|
Prog *p, *ploop;
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
|
|
|
if(debug['g']) {
|
|
|
|
print("\nsgen w=%d\n", w);
|
|
|
|
dump("r", n);
|
2009-07-07 00:04:56 -06:00
|
|
|
dump("res", res);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
if(w == 0)
|
|
|
|
return;
|
2009-07-07 00:04:56 -06:00
|
|
|
if(n->ullman >= UINF && res->ullman >= UINF) {
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
fatal("sgen UINF");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(w < 0)
|
|
|
|
fatal("sgen copy %d", w);
|
|
|
|
|
|
|
|
// offset on the stack
|
|
|
|
osrc = stkof(n);
|
2009-07-07 00:04:56 -06:00
|
|
|
odst = stkof(res);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
2009-08-21 17:29:19 -06:00
|
|
|
if(osrc % 4 != 0 || odst %4 != 0)
|
|
|
|
fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
|
|
|
|
|
2009-10-06 10:47:46 -06:00
|
|
|
regalloc(&dst, types[tptr], res);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
2009-07-07 00:04:56 -06:00
|
|
|
if(n->ullman >= res->ullman) {
|
2009-10-30 10:38:30 -06:00
|
|
|
agen(n, &dst); // temporarily use dst
|
2009-10-06 10:47:46 -06:00
|
|
|
regalloc(&src, types[tptr], N);
|
|
|
|
gins(AMOVW, &dst, &src);
|
2009-07-13 23:04:24 -06:00
|
|
|
agen(res, &dst);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
} else {
|
2009-07-13 23:04:24 -06:00
|
|
|
agen(res, &dst);
|
2009-10-06 10:47:46 -06:00
|
|
|
regalloc(&src, types[tptr], N);
|
2009-07-13 23:04:24 -06:00
|
|
|
agen(n, &src);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
|
|
|
|
2009-10-06 10:47:46 -06:00
|
|
|
regalloc(&tmp, types[TUINT32], N);
|
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
c = w % 4; // bytes
|
|
|
|
q = w / 4; // quads
|
|
|
|
|
|
|
|
// if we are copying forward on the stack and
|
|
|
|
// the src and dst overlap, then reverse direction
|
|
|
|
if(osrc < odst && odst < osrc+w) {
|
2009-08-21 17:29:19 -06:00
|
|
|
if(c != 0)
|
|
|
|
fatal("sgen: reverse character copy not implemented");
|
|
|
|
if(q >= 4) {
|
|
|
|
regalloc(&nend, types[TUINT32], N);
|
|
|
|
// set up end marker to 4 bytes before source
|
|
|
|
p = gins(AMOVW, &src, &nend);
|
|
|
|
p->from.type = D_CONST;
|
|
|
|
p->from.offset = -4;
|
|
|
|
|
|
|
|
// move src and dest to the end of block
|
|
|
|
p = gins(AMOVW, &src, &src);
|
|
|
|
p->from.type = D_CONST;
|
|
|
|
p->from.offset = (q-1)*4;
|
|
|
|
|
|
|
|
p = gins(AMOVW, &dst, &dst);
|
|
|
|
p->from.type = D_CONST;
|
|
|
|
p->from.offset = (q-1)*4;
|
|
|
|
|
|
|
|
p = gins(AMOVW, &src, &tmp);
|
|
|
|
p->from.type = D_OREG;
|
|
|
|
p->from.offset = -4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
ploop = p;
|
|
|
|
|
|
|
|
p = gins(AMOVW, &tmp, &dst);
|
|
|
|
p->to.type = D_OREG;
|
|
|
|
p->to.offset = -4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
2009-09-18 00:07:52 -06:00
|
|
|
p = gins(ACMP, &src, N);
|
|
|
|
raddr(&nend, p);
|
2009-08-21 17:29:19 -06:00
|
|
|
|
|
|
|
patch(gbranch(ABNE, T), ploop);
|
|
|
|
|
|
|
|
regfree(&nend);
|
2009-10-30 10:38:30 -06:00
|
|
|
} else {
|
|
|
|
// move src and dest to the end of block
|
|
|
|
p = gins(AMOVW, &src, &src);
|
|
|
|
p->from.type = D_CONST;
|
|
|
|
p->from.offset = (q-1)*4;
|
|
|
|
|
|
|
|
p = gins(AMOVW, &dst, &dst);
|
|
|
|
p->from.type = D_CONST;
|
|
|
|
p->from.offset = (q-1)*4;
|
|
|
|
|
|
|
|
while(q > 0) {
|
|
|
|
p = gins(AMOVW, &src, &tmp);
|
|
|
|
p->from.type = D_OREG;
|
|
|
|
p->from.offset = -4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
|
|
|
p = gins(AMOVW, &tmp, &dst);
|
|
|
|
p->to.type = D_OREG;
|
|
|
|
p->to.offset = -4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
|
|
|
q--;
|
|
|
|
}
|
2009-08-21 17:29:19 -06:00
|
|
|
}
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
} else {
|
|
|
|
// normal direction
|
|
|
|
if(q >= 4) {
|
|
|
|
regalloc(&nend, types[TUINT32], N);
|
2009-07-13 23:04:24 -06:00
|
|
|
p = gins(AMOVW, &src, &nend);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p->from.type = D_CONST;
|
2009-08-21 17:29:19 -06:00
|
|
|
p->from.offset = q*4;
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
2009-07-13 23:04:24 -06:00
|
|
|
p = gins(AMOVW, &src, &tmp);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p->from.type = D_OREG;
|
|
|
|
p->from.offset = 4;
|
|
|
|
p->scond |= C_PBIT;
|
2009-08-21 17:29:19 -06:00
|
|
|
ploop = p;
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
|
2009-07-13 23:04:24 -06:00
|
|
|
p = gins(AMOVW, &tmp, &dst);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p->to.type = D_OREG;
|
|
|
|
p->to.offset = 4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
2009-09-18 00:07:52 -06:00
|
|
|
p = gins(ACMP, &src, N);
|
|
|
|
raddr(&nend, p);
|
2009-08-21 17:29:19 -06:00
|
|
|
|
|
|
|
patch(gbranch(ABNE, T), ploop);
|
|
|
|
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
regfree(&nend);
|
|
|
|
} else
|
|
|
|
while(q > 0) {
|
2009-07-13 23:04:24 -06:00
|
|
|
p = gins(AMOVW, &src, &tmp);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p->from.type = D_OREG;
|
|
|
|
p->from.offset = 4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
2009-07-13 23:04:24 -06:00
|
|
|
p = gins(AMOVW, &tmp, &dst);
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
p->to.type = D_OREG;
|
|
|
|
p->to.offset = 4;
|
|
|
|
p->scond |= C_PBIT;
|
|
|
|
|
|
|
|
q--;
|
|
|
|
}
|
2009-05-28 15:25:54 -06:00
|
|
|
|
2009-10-11 21:01:11 -06:00
|
|
|
if (c != 0) {
|
|
|
|
// MOVW (src), tmp
|
|
|
|
p = gins(AMOVW, &src, &tmp);
|
|
|
|
p->from.type = D_OREG;
|
|
|
|
|
2009-10-24 23:47:25 -06:00
|
|
|
// MOVW tmp<<((4-c)*8),src
|
|
|
|
gshift(AMOVW, &tmp, SHIFT_LL, ((4-c)*8), &src);
|
2009-10-11 21:01:11 -06:00
|
|
|
|
2009-10-24 23:47:25 -06:00
|
|
|
// MOVW src>>((4-c)*8),src
|
|
|
|
gshift(AMOVW, &src, SHIFT_LR, ((4-c)*8), &src);
|
2009-10-11 21:01:11 -06:00
|
|
|
|
|
|
|
// MOVW (dst), tmp
|
|
|
|
p = gins(AMOVW, &dst, &tmp);
|
|
|
|
p->from.type = D_OREG;
|
|
|
|
|
|
|
|
// MOVW tmp>>(c*8),tmp
|
2009-10-24 23:47:25 -06:00
|
|
|
gshift(AMOVW, &tmp, SHIFT_LR, (c*8), &tmp);
|
|
|
|
|
|
|
|
// MOVW tmp<<(c*8),tmp
|
|
|
|
gshift(AMOVW, &tmp, SHIFT_LL, c*8, &tmp);
|
2009-10-11 21:01:11 -06:00
|
|
|
|
|
|
|
// ORR src, tmp
|
|
|
|
gins(AORR, &src, &tmp);
|
|
|
|
|
|
|
|
// MOVW tmp, (dst)
|
|
|
|
p = gins(AMOVW, &tmp, &dst);
|
|
|
|
p->to.type = D_OREG;
|
|
|
|
}
|
agen, sgen, cgen_callret, cgen_asop, D_ADDR handling, gmove
8bit and 16bit, some optoas, replaced Addr.index with
Addr.name
empty function compiles, mutex compiles
R=rsc
APPROVED=rsc
DELTA=908 (83 added, 41 deleted, 784 changed)
OCL=31127
CL=31188
2009-07-06 07:42:37 -06:00
|
|
|
}
|
2009-07-13 23:04:24 -06:00
|
|
|
regfree(&dst);
|
|
|
|
regfree(&src);
|
|
|
|
regfree(&tmp);
|
2009-05-01 14:21:53 -06:00
|
|
|
}
|