summaryrefslogtreecommitdiff
path: root/src/cmd/6c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6c')
-rw-r--r--src/cmd/6c/Makefile5
-rw-r--r--src/cmd/6c/cgen.c2046
-rw-r--r--src/cmd/6c/div.c236
-rw-r--r--src/cmd/6c/doc.go16
-rw-r--r--src/cmd/6c/gc.h359
-rw-r--r--src/cmd/6c/list.c38
-rw-r--r--src/cmd/6c/machcap.c107
-rw-r--r--src/cmd/6c/mul.c458
-rw-r--r--src/cmd/6c/peep.c902
-rw-r--r--src/cmd/6c/reg.c1523
-rw-r--r--src/cmd/6c/sgen.c483
-rw-r--r--src/cmd/6c/swt.c353
-rw-r--r--src/cmd/6c/txt.c1674
13 files changed, 0 insertions, 8200 deletions
diff --git a/src/cmd/6c/Makefile b/src/cmd/6c/Makefile
deleted file mode 100644
index 3f528d751..000000000
--- a/src/cmd/6c/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 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 ../../Make.dist
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
deleted file mode 100644
index 68dd7bb5f..000000000
--- a/src/cmd/6c/cgen.c
+++ /dev/null
@@ -1,2046 +0,0 @@
-// Inferno utils/6c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/cgen.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"
-#include "../../runtime/funcdata.h"
-
-/* ,x/^(print|prtree)\(/i/\/\/ */
-int castup(Type*, Type*);
-int vaddr(Node *n, int a);
-
-void
-cgen(Node *n, Node *nn)
-{
- Node *l, *r, *t;
- Prog *p1;
- Node nod, nod1, nod2, nod3, nod4;
- int o, hardleft;
- int32 v, curs;
- vlong c;
-
- if(debug['g']) {
- prtree(nn, "cgen lhs");
- prtree(n, "cgen");
- }
- if(n == Z || n->type == T)
- return;
- if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
- sugen(n, nn, n->type->width);
- return;
- }
- l = n->left;
- r = n->right;
- o = n->op;
-
- if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
- gmove(n, nn);
- return;
- }
-
- if(n->addable >= INDEXED) {
- if(nn == Z) {
- switch(o) {
- default:
- nullwarn(Z, Z);
- break;
- case OINDEX:
- nullwarn(l, r);
- break;
- }
- return;
- }
- gmove(n, nn);
- return;
- }
- curs = cursafe;
-
- if(l->complex >= FNX)
- if(r != Z && r->complex >= FNX)
- switch(o) {
- default:
- if(cond(o) && typesu[l->type->etype])
- break;
-
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
-
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
-
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
-
- cgen(&nod, nn);
- return;
-
- case OFUNC:
- case OCOMMA:
- case OANDAND:
- case OOROR:
- case OCOND:
- case ODOT:
- break;
- }
-
- hardleft = l->addable < INDEXED || l->complex >= FNX;
- switch(o) {
- default:
- diag(n, "unknown op in cgen: %O", o);
- break;
-
- case ONEG:
- case OCOM:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, Z, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OAS:
- if(l->op == OBIT)
- goto bitas;
- if(!hardleft) {
- if(nn != Z || r->addable < INDEXED || hardconst(r)) {
- if(r->complex >= FNX && nn == Z)
- regret(&nod, r, 0, 0);
- else
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gmove(&nod, l);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- } else
- gmove(r, l);
- break;
- }
- if(l->complex >= r->complex) {
- if(l->op == OINDEX && immconst(r)) {
- gmove(r, l);
- break;
- }
- reglcgen(&nod1, l, Z);
- if(r->addable >= INDEXED && !hardconst(r)) {
- gmove(r, &nod1);
- if(nn != Z)
- gmove(r, nn);
- regfree(&nod1);
- break;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- reglcgen(&nod1, l, Z);
- }
- gmove(&nod, &nod1);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- bitas:
- n = l->left;
- regalloc(&nod, r, nn);
- if(l->complex >= r->complex) {
- reglcgen(&nod1, n, Z);
- cgen(r, &nod);
- } else {
- cgen(r, &nod);
- reglcgen(&nod1, n, Z);
- }
- regalloc(&nod2, n, Z);
- gmove(&nod1, &nod2);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OBIT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- bitload(n, &nod, Z, Z, nn);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(r->op == OCONST) {
- if(r->vconst == 0) {
- cgen(l, nn);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(o == OASHL && r->vconst == 1)
- gopcode(OADD, n->type, &nod, &nod);
- else
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod); /* probably a bug */
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
- if(nn->op == OREGISTER && nn->reg == D_CX)
- regalloc(&nod1, l, Z);
- else
- regalloc(&nod1, l, nn);
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- cgen(l, &nod1);
- } else {
- cgen(l, &nod1);
- cgen(r, &nod);
- }
- gopcode(o, n->type, &nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OADD:
- case OSUB:
- case OOR:
- case OXOR:
- case OAND:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST) {
- if(r->vconst == 0 && o != OAND) {
- cgen(l, nn);
- break;
- }
- }
- if(n->op == OOR && l->op == OASHL && r->op == OLSHR
- && l->right->op == OCONST && r->right->op == OCONST
- && l->left->op == ONAME && r->left->op == ONAME
- && l->left->sym == r->left->sym
- && l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- gopcode(OROTL, n->type, l->right, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
- && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
- c = l->right->vconst;
- if(c > 0 && c <= 3) {
- if(l->left->complex >= r->complex) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- genmuladd(&nod, &nod, 1 << c, &nod1);
- regfree(&nod1);
- }
- else
- genmuladd(&nod, &nod, 1 << c, r);
- }
- else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- regalloc(&nod1, l->left, Z);
- cgen(l->left, &nod1);
- genmuladd(&nod, &nod1, 1 << c, &nod);
- regfree(&nod1);
- }
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- }
- if(r->addable >= INDEXED && !hardconst(r)) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, n->type, &nod1, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- regalloc(&nod, l, Z);
- cgen(l, &nod);
- gopcode(o, n->type, &nod1, &nod);
- }
- gmove(&nod, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */
- SET(v);
- switch(o) {
- case ODIV:
- case OMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OMUL:
- case OLMUL:
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- switch(o) {
- case OMUL:
- case OLMUL:
- mulgen(n->type, r, &nod);
- break;
- case ODIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- case OLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- }
- }
-
- if(o == OMUL || o == OLMUL) {
- if(l->addable >= INDEXED) {
- t = l;
- l = r;
- r = t;
- }
- reg[D_DX]++; // for gopcode case OMUL
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED || hardconst(r)) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(OMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }else
- gopcode(OMUL, n->type, r, &nod); /* addressible */
- gmove(&nod, nn);
- regfree(&nod);
- reg[D_DX]--;
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
-
- if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
- reg[D_DX]++;
- if(l->addable < INDEXED) {
- regalloc(&nod2, l, Z);
- cgen(l, &nod2);
- l = &nod2;
- }
- if(o == ODIV)
- sdivgen(l, r, &nod, &nod1);
- else
- udivgen(l, r, &nod, &nod1);
- gmove(&nod1, nn);
- if(l == &nod2)
- regfree(l);
- goto freeaxdx;
- }
-
- if(l->complex >= r->complex) {
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST) {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- gopcode(o, n->type, &nod3, Z);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- gopcode(o, n->type, &nod3, Z);
- }
- if(o == OMOD || o == OLMOD)
- gmove(&nod1, nn);
- else
- gmove(&nod, nn);
- freeaxdx:
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->op == OCONST)
- goto asand;
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype])
- goto asand; /* can this happen? */
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod);
- if(nn != Z)
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
-
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- } else {
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- cgen(r, &nod);
- }
-
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod);
- if(nn != Z)
- gmove(&nod1, nn);
- if(hardleft)
- regfree(&nod1);
- break;
-
- case OASAND:
- case OASADD:
- case OASSUB:
- case OASXOR:
- case OASOR:
- asand:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[l->type->etype] || typefd[r->type->etype])
- goto asfop;
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(!immconst(r)) {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, r, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- }
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- asfop:
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(r->addable < INDEXED){
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- }else
- nod1 = *r;
- regalloc(&nod2, r, Z);
- gmove(&nod, &nod2);
- gopcode(o, r->type, &nod1, &nod2);
- gmove(&nod2, &nod);
- regfree(&nod2);
- if(r->addable < INDEXED)
- regfree(&nod1);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(o != OASMUL && o != OASADD) {
- regalloc(&nod2, r, Z);
- gmove(&nod, &nod2);
- gopcode(o, r->type, &nod1, &nod2);
- regfree(&nod1);
- gmove(&nod2, &nod);
- regfree(&nod2);
- } else {
- gopcode(o, r->type, &nod, &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- }
- }
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype] || typefd[r->type->etype])
- goto asfop;
- if(r->op == OCONST && typechl[n->type->etype]) {
- SET(v);
- switch(o) {
- case OASDIV:
- case OASMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OASMUL:
- case OASLMUL:
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, l, nn);
- cgen(&nod2, &nod);
- switch(o) {
- case OASMUL:
- case OASLMUL:
- mulgen(n->type, r, &nod);
- break;
- case OASDIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OASMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- havev:
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- goto done;
- case OASLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod1, l, nn);
- cgen(&nod2, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- goto havev;
- }
- }
-
- if(o == OASMUL) {
- /* should favour AX */
- regalloc(&nod, l, nn);
- if(r->complex >= FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- r = &nod1;
- }
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->addable < INDEXED || hardconst(r)) {
- if(r->complex < FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- }
- gopcode(OASMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }
- else
- gopcode(OASMUL, n->type, r, &nod);
- if(r == &nod1)
- regfree(r);
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- if(hardleft)
- regfree(&nod2);
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
- reg[D_DX]++;
-
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->op == OCONST && typechl[r->type->etype]) {
- switch(o) {
- case OASDIV:
- sdivgen(&nod2, r, &nod, &nod1);
- goto divdone;
- case OASLDIV:
- udivgen(&nod2, r, &nod, &nod1);
- divdone:
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- goto freelxaxdx;
- }
- }
- if(o == OASDIV || o == OASMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST ||
- !typeil[r->type->etype]) {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(o == OASDIV || o == OASMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- }
- if(o == OASMOD || o == OASLMOD) {
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- } else {
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- }
- freelxaxdx:
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- fop:
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, n->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, n->type, r, &nod);
- } else {
- /* TO DO: could do better with r->addable >= INDEXED */
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, &nod1, &nod);
- regfree(&nod1);
- }
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- asbitop:
- regalloc(&nod4, n, nn);
- if(l->complex >= r->complex) {
- bitload(l, &nod, &nod1, &nod2, &nod4);
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- bitload(l, &nod, &nod1, &nod2, &nod4);
- }
- gmove(&nod, &nod4);
-
- { /* TO DO: check floating point source */
- Node onod;
-
- /* incredible grot ... */
- onod = nod3;
- onod.op = o;
- onod.complex = 2;
- onod.addable = 0;
- onod.type = tfield;
- onod.left = &nod4;
- onod.right = &nod3;
- cgen(&onod, Z);
- }
- regfree(&nod3);
- gmove(&nod4, &nod);
- regfree(&nod4);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OADDR:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- lcgen(l, nn);
- break;
-
- case OFUNC:
- if(l->complex >= FNX) {
- if(l->op != OIND)
- diag(n, "bad function call");
-
- regret(&nod, l->left, 0, 0);
- cgen(l->left, &nod);
- regsalloc(&nod1, l->left);
- gmove(&nod, &nod1);
- regfree(&nod);
-
- nod = *n;
- nod.left = &nod2;
- nod2 = *l;
- nod2.left = &nod1;
- nod2.complex = 1;
- cgen(&nod, nn);
-
- return;
- }
- gargs(r, &nod, &nod1);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, nn);
- nod.op = OREGISTER;
- gopcode(OFUNC, n->type, Z, &nod);
- regfree(&nod);
- } else
- gopcode(OFUNC, n->type, Z, l);
- if(REGARG >= 0 && reg[REGARG])
- reg[REGARG]--;
- regret(&nod, n, l->type, 1); // update maxarg if nothing else
- if(nn != Z)
- gmove(&nod, nn);
- if(nod.op == OREGISTER)
- regfree(&nod);
- break;
-
- case OIND:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regialloc(&nod, n, nn);
- r = l;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- cgen(l, &nod);
- nod.xoffset += v;
- r->vconst = v;
- } else
- cgen(l, &nod);
- regind(&nod, n);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHI:
- case OHS:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OANDAND:
- case OOROR:
- boolgen(n, 1, nn);
- if(nn == Z)
- patch(p, pc);
- break;
-
- case ONOT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OCOMMA:
- cgen(l, Z);
- cgen(r, nn);
- break;
-
- case OCAST:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- /*
- * convert from types l->n->nn
- */
- if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
- /* both null, gen l->nn */
- cgen(l, nn);
- break;
- }
- if(ewidth[n->type->etype] < ewidth[l->type->etype]){
- if(l->type->etype == TIND && typechlp[n->type->etype])
- warn(n, "conversion of pointer to shorter integer");
- }else if(0){
- if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
- if(typefd[l->type->etype] != typefd[nn->type->etype])
- regalloc(&nod, l, nn);
- else
- regalloc(&nod, nn, nn);
- cgen(l, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, n, &nod);
- gmove(&nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod1);
- regfree(&nod);
- break;
-
- case ODOT:
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod = *nodrat;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod.xoffset += (int32)r->vconst;
- nod.type = n->type;
- cgen(&nod, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- cgen(r->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- cgen(r->right, nn);
- patch(p1, pc);
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPOSTDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
- if(nn == Z)
- goto pre;
-
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
-
- gmove(&nod, nn);
- if(typefd[n->type->etype]) {
- regalloc(&nod1, l, Z);
- gmove(&nod, &nod1);
- if(v < 0)
- gopcode(OSUB, n->type, nodfconst(-v), &nod1);
- else
- gopcode(OADD, n->type, nodfconst(v), &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OPREINC:
- case OPREDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPREDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
-
- pre:
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(typefd[n->type->etype]) {
- regalloc(&nod1, l, Z);
- gmove(&nod, &nod1);
- if(v < 0)
- gopcode(OSUB, n->type, nodfconst(-v), &nod1);
- else
- gopcode(OADD, n->type, nodfconst(v), &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- bitinc:
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
- bitload(l, &nod, &nod1, &nod2, Z);
- gmove(&nod, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, Z);
- break;
- }
- bitload(l, &nod, &nod1, &nod2, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
- }
-done:
- cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
- Node *r;
- int32 v;
-
- regialloc(t, n, nn);
- if(n->op == OIND) {
- r = n->left;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- lcgen(n, t);
- t->xoffset += v;
- r->vconst = v;
- regind(t, n);
- return;
- }
- }
- lcgen(n, t);
- regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
- Prog *p1;
- Node nod;
-
- if(debug['g']) {
- prtree(nn, "lcgen lhs");
- prtree(n, "lcgen");
- }
- if(n == Z || n->type == T)
- return;
- if(nn == Z) {
- nn = &nod;
- regalloc(&nod, n, Z);
- }
- switch(n->op) {
- default:
- if(n->addable < INDEXED) {
- diag(n, "unknown op in lcgen: %O", n->op);
- break;
- }
- gopcode(OADDR, n->type, n, nn);
- break;
-
- case OCOMMA:
- cgen(n->left, n->left);
- lcgen(n->right, nn);
- break;
-
- case OIND:
- cgen(n->left, nn);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- lcgen(n->right->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- lcgen(n->right->right, nn);
- patch(p1, pc);
- break;
- }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
- if(n->type == T)
- gbranch(OGOTO);
- else
- boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
- int o;
- Prog *p1, *p2, *p3;
- Node *l, *r, nod, nod1;
- int32 curs;
-
- if(debug['g']) {
- print("boolgen %d\n", true);
- prtree(nn, "boolgen lhs");
- prtree(n, "boolgen");
- }
- curs = cursafe;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- default:
- o = ONE;
- if(true)
- o = OEQ;
- /* bad, 13 is address of external that becomes constant */
- if(n->addable >= INDEXED && n->addable != 13) {
- if(typefd[n->type->etype]) {
- regalloc(&nod1, n, Z);
- gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
- gopcode(o, n->type, n, &nod1);
- regfree(&nod1);
- } else
- gopcode(o, n->type, n, nodconst(0));
- goto com;
- }
- regalloc(&nod, n, nn);
- cgen(n, &nod);
- if(typefd[n->type->etype]) {
- regalloc(&nod1, n, Z);
- gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
- gopcode(o, n->type, &nod, &nod1);
- regfree(&nod1);
- } else
- gopcode(o, n->type, &nod, nodconst(0));
- regfree(&nod);
- goto com;
-
- case OCONST:
- o = vconst(n);
- if(!true)
- o = !o;
- gbranch(OGOTO);
- if(o) {
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- }
- goto com;
-
- case OCOMMA:
- cgen(l, Z);
- boolgen(r, true, nn);
- break;
-
- case ONOT:
- boolgen(l, !true, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- bcgen(r->left, true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- bcgen(r->right, !true);
- patch(p2, pc);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OANDAND:
- if(!true)
- goto caseor;
-
- caseand:
- bcgen(l, true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- patch(p1, pc);
- gbranch(OGOTO);
- patch(p2, pc);
- goto com;
-
- case OOROR:
- if(!true)
- goto caseand;
-
- caseor:
- bcgen(l, !true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- o = n->op;
- if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
- // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
- // Jump around instead.
- boolgen(n, 0, Z);
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- goto com;
- }
- if(true)
- o = comrel[relindex(o)];
- if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- boolgen(&nod, true, nn);
- break;
- }
- if(immconst(l)) {
- // NOTE: Reversing the comparison here is wrong
- // for floating point ordering comparisons involving NaN,
- // but we don't have any of those yet so we don't
- // bother worrying about it.
- o = invrel[relindex(o)];
- /* bad, 13 is address of external that becomes constant */
- if(r->addable < INDEXED || r->addable == 13) {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gopcode(o, l->type, &nod, l);
- regfree(&nod);
- } else
- gopcode(o, l->type, r, l);
- goto com;
- }
- if(typefd[l->type->etype])
- o = invrel[relindex(logrel[relindex(o)])];
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod1);
- } else {
- gopcode(o, l->type, &nod, r);
- }
- regfree(&nod);
- goto fixfloat;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) {
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT])
- gopcode(o, types[TINT], &nod1, &nod);
- else
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, l, &nod);
- regfree(&nod);
- fixfloat:
- if(typefd[l->type->etype]) {
- switch(o) {
- case OEQ:
- // Already emitted AJEQ; want AJEQ and AJPC.
- p1 = p;
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gins(AJPC, Z, Z);
- patch(p2, pc);
- break;
-
- case ONE:
- // Already emitted AJNE; want AJNE or AJPS.
- p1 = p;
- gins(AJPS, Z, Z);
- p2 = p;
- gbranch(OGOTO);
- p3 = p;
- patch(p1, pc);
- patch(p2, pc);
- gbranch(OGOTO);
- patch(p3, pc);
- break;
- }
- }
-
- com:
- if(nn != Z) {
- p1 = p;
- gmove(nodconst(1L), nn);
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gmove(nodconst(0L), nn);
- patch(p2, pc);
- }
- break;
- }
- cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
- Prog *p1;
- Node nod0, nod1, nod2, nod3, nod4, *l, *r;
- Type *t;
- int c, mt, mo;
- vlong o0, o1;
-
- if(n == Z || n->type == T)
- return;
- if(debug['g']) {
- prtree(nn, "sugen lhs");
- prtree(n, "sugen");
- }
- if(nn == nodrat)
- if(w > nrathole)
- nrathole = w;
- switch(n->op) {
- case OIND:
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- default:
- goto copy;
-
- case OCONST:
- goto copy;
-
- case ODOT:
- l = n->left;
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod1 = *nodrat;
- r = n->right;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod1.xoffset += (int32)r->vconst;
- nod1.type = n->type;
- sugen(&nod1, nn, w);
- break;
-
- case OSTRUCT:
- /*
- * rewrite so lhs has no fn call
- */
- if(nn != Z && side(nn)) {
- nod1 = *n;
- nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1, 0, 0);
- lcgen(nn, &nod2);
- regsalloc(&nod0, &nod1);
- cgen(&nod2, &nod0);
- regfree(&nod2);
-
- nod1 = *n;
- nod1.op = OIND;
- nod1.left = &nod0;
- nod1.right = Z;
- nod1.complex = 1;
-
- sugen(n, &nod1, w);
- return;
- }
-
- r = n->left;
- for(t = n->type->link; t != T; t = t->down) {
- l = r;
- if(r->op == OLIST) {
- l = r->left;
- r = r->right;
- }
- if(nn == Z) {
- cgen(l, nn);
- continue;
- }
- /*
- * hand craft *(&nn + o) = l
- */
- nod0 = znode;
- nod0.op = OAS;
- nod0.type = t;
- nod0.left = &nod1;
- nod0.right = nil;
-
- nod1 = znode;
- nod1.op = OIND;
- nod1.type = t;
- nod1.left = &nod2;
-
- nod2 = znode;
- nod2.op = OADD;
- nod2.type = typ(TIND, t);
- nod2.left = &nod3;
- nod2.right = &nod4;
-
- nod3 = znode;
- nod3.op = OADDR;
- nod3.type = nod2.type;
- nod3.left = nn;
-
- nod4 = znode;
- nod4.op = OCONST;
- nod4.type = nod2.type;
- nod4.vconst = t->offset;
-
- ccom(&nod0);
- acom(&nod0);
- xcom(&nod0);
- nod0.addable = 0;
- nod0.right = l;
-
- // prtree(&nod0, "hand craft");
- cgen(&nod0, Z);
- }
- break;
-
- case OAS:
- if(nn == Z) {
- if(n->addable < INDEXED)
- sugen(n->right, n->left, w);
- break;
- }
-
- sugen(n->right, nodrat, w);
- warn(n, "non-interruptable temporary");
- sugen(nodrat, n->left, w);
- sugen(nodrat, nn, w);
- break;
-
- case OFUNC:
- if(!hasdotdotdot(n->left->type)) {
- cgen(n, Z);
- if(nn != Z) {
- curarg -= n->type->width;
- regret(&nod1, n, n->left->type, 1);
- if(nn->complex >= FNX) {
- regsalloc(&nod2, n);
- cgen(&nod1, &nod2);
- nod1 = nod2;
- }
- cgen(&nod1, nn);
- }
- break;
- }
- if(nn == Z) {
- sugen(n, nodrat, w);
- break;
- }
- if(nn->op != OIND) {
- nn = new1(OADDR, nn, Z);
- nn->type = types[TIND];
- nn->addable = 0;
- } else
- nn = nn->left;
- n = new(OFUNC, n->left, new(OLIST, nn, n->right));
- n->type = types[TVOID];
- n->left->type = types[TVOID];
- cgen(n, Z);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- sugen(n->right->left, nn, w);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- sugen(n->right->right, nn, w);
- patch(p1, pc);
- break;
-
- case OCOMMA:
- cgen(n->left, Z);
- sugen(n->right, nn, w);
- break;
- }
- return;
-
-copy:
- if(nn == Z) {
- switch(n->op) {
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
-
- case OASMUL:
- case OASLMUL:
-
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- break;
-
- default:
- return;
- }
- }
-
- if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TIND];
- regialloc(&nod1, nn, Z);
- lcgen(nn, &nod1);
- regsalloc(&nod2, nn);
- nn->type = t;
-
- gins(AMOVQ, &nod1, &nod2);
- regfree(&nod1);
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- return;
- }
-
- if(w <= 32) {
- c = cursafe;
- if(n->left != Z && n->left->complex >= FNX
- && n->right != Z && n->right->complex >= FNX) {
- regsalloc(&nod1, n->right);
- cgen(n->right, &nod1);
- nod2 = *n;
- nod2.right = &nod1;
- cgen(&nod2, nn);
- cursafe = c;
- return;
- }
- if(w & 7) {
- mt = TLONG;
- mo = AMOVL;
- } else {
- mt = TVLONG;
- mo = AMOVQ;
- }
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[mt];
- regalloc(&nod0, n, Z);
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
-
- t = nn->type;
- nn->type = types[mt];
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
- } else {
- t = nn->type;
- nn->type = types[mt];
- regalloc(&nod0, nn, Z);
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
-
- t = n->type;
- n->type = types[mt];
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
- }
- o0 = n->xoffset;
- o1 = nn->xoffset;
- w /= ewidth[mt];
- while(--w >= 0) {
- gins(mo, n, &nod0);
- gins(mo, &nod0, nn);
- n->xoffset += ewidth[mt];
- nn->xoffset += ewidth[mt];
- }
- n->xoffset = o0;
- nn->xoffset = o1;
- if(nn == &nod2)
- regfree(&nod2);
- if(n == &nod1)
- regfree(&nod1);
- regfree(&nod0);
- return;
- }
-
- /* botch, need to save in .safe */
- c = 0;
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[TIND];
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHQ, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
-
- t = nn->type;
- nn->type = types[TIND];
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
-warn(Z, "DI botch");
- gins(APUSHQ, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
- } else {
- t = nn->type;
- nn->type = types[TIND];
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
-warn(Z, "DI botch");
- gins(APUSHQ, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
-
- t = n->type;
- n->type = types[TIND];
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHQ, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
- }
- nodreg(&nod3, n, D_CX);
- if(reg[D_CX]) {
- gins(APUSHQ, &nod3, Z);
- c |= 4;
- reg[D_CX]++;
- }
- gins(AMOVL, nodconst(w/SZ_INT), &nod3);
- gins(ACLD, Z, Z);
- gins(AREP, Z, Z);
- gins(AMOVSL, Z, Z);
- if(c & 4) {
- gins(APOPQ, Z, &nod3);
- reg[D_CX]--;
- }
- if(c & 2) {
- gins(APOPQ, Z, &nod2);
- reg[nod2.reg]--;
- }
- if(c & 1) {
- gins(APOPQ, Z, &nod1);
- reg[nod1.reg]--;
- }
-}
-
-/*
- * TO DO
- */
-void
-layout(Node *f, Node *t, int c, int cv, Node *cn)
-{
- Node t1, t2;
-
- while(c > 3) {
- layout(f, t, 2, 0, Z);
- c -= 2;
- }
-
- regalloc(&t1, &lregnode, Z);
- regalloc(&t2, &lregnode, Z);
- if(c > 0) {
- gmove(f, &t1);
- f->xoffset += SZ_INT;
- }
- if(cn != Z)
- gmove(nodconst(cv), cn);
- if(c > 1) {
- gmove(f, &t2);
- f->xoffset += SZ_INT;
- }
- if(c > 0) {
- gmove(&t1, t);
- t->xoffset += SZ_INT;
- }
- if(c > 2) {
- gmove(f, &t1);
- f->xoffset += SZ_INT;
- }
- if(c > 1) {
- gmove(&t2, t);
- t->xoffset += SZ_INT;
- }
- if(c > 2) {
- gmove(&t1, t);
- t->xoffset += SZ_INT;
- }
- regfree(&t1);
- regfree(&t2);
-}
-
-/*
- * constant is not vlong or fits as 32-bit signed immediate
- */
-int
-immconst(Node *n)
-{
- int32 v;
-
- if(n->op != OCONST || !typechlpv[n->type->etype])
- return 0;
- if(typechl[n->type->etype])
- return 1;
- v = n->vconst;
- return n->vconst == (vlong)v;
-}
-
-/*
- * if a constant and vlong, doesn't fit as 32-bit signed immediate
- */
-int
-hardconst(Node *n)
-{
- return n->op == OCONST && !immconst(n);
-}
-
-/*
- * casting up to t2 covers an intermediate cast to t1
- */
-int
-castup(Type *t1, Type *t2)
-{
- int ft;
-
- if(!nilcast(t1, t2))
- return 0;
- /* known to be small to large */
- ft = t1->etype;
- switch(t2->etype){
- case TINT:
- case TLONG:
- return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
- case TUINT:
- case TULONG:
- return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
- case TVLONG:
- return ft == TLONG || ft == TINT || ft == TSHORT;
- case TUVLONG:
- return ft == TULONG || ft == TUINT || ft == TUSHORT;
- }
- return 0;
-}
-
-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));
-}
-
-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;
-}
diff --git a/src/cmd/6c/div.c b/src/cmd/6c/div.c
deleted file mode 100644
index bad6c5e27..000000000
--- a/src/cmd/6c/div.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inferno utils/6c/div.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/div.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"
-
-/*
- * Based on: Granlund, T.; Montgomery, P.L.
- * "Division by Invariant Integers using Multiplication".
- * SIGPLAN Notices, Vol. 29, June 1994, page 61.
- */
-
-#define TN(n) ((uvlong)1 << (n))
-#define T31 TN(31)
-#define T32 TN(32)
-
-int
-multiplier(uint32 d, int p, uvlong *mp)
-{
- int l;
- uvlong mlo, mhi, tlo, thi;
-
- l = topbit(d - 1) + 1;
- mlo = (((TN(l) - d) << 32) / d) + T32;
- if(l + p == 64)
- mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
- else
- mhi = (TN(32 + l) + TN(32 + l - p)) / d;
- /*assert(mlo < mhi);*/
- while(l > 0) {
- tlo = mlo >> 1;
- thi = mhi >> 1;
- if(tlo == thi)
- break;
- mlo = tlo;
- mhi = thi;
- l--;
- }
- *mp = mhi;
- return l;
-}
-
-int
-sdiv(uint32 d, uint32 *mp, int *sp)
-{
- int s;
- uvlong m;
-
- s = multiplier(d, 32 - 1, &m);
- *mp = m;
- *sp = s;
- if(m >= T31)
- return 1;
- else
- return 0;
-}
-
-int
-udiv(uint32 d, uint32 *mp, int *sp, int *pp)
-{
- int p, s;
- uvlong m;
-
- s = multiplier(d, 32, &m);
- p = 0;
- if(m >= T32) {
- while((d & 1) == 0) {
- d >>= 1;
- p++;
- }
- s = multiplier(d, 32 - p, &m);
- }
- *mp = m;
- *pp = p;
- if(m >= T32) {
- /*assert(p == 0);*/
- *sp = s - 1;
- return 1;
- }
- else {
- *sp = s;
- return 0;
- }
-}
-
-void
-sdivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s;
- uint32 m;
- vlong c;
-
- c = r->vconst;
- if(c < 0)
- c = -c;
- a = sdiv(c, &m, &s);
-//print("a=%d i=%d s=%d m=%ux\n", a, (long)r->vconst, s, m);
- gins(AMOVL, nodconst(m), ax);
- gins(AIMULL, l, Z);
- gins(AMOVL, l, ax);
- if(a)
- gins(AADDL, ax, dx);
- gins(ASHRL, nodconst(31), ax);
- gins(ASARL, nodconst(s), dx);
- gins(AADDL, ax, dx);
- if(r->vconst < 0)
- gins(ANEGL, Z, dx);
-}
-
-void
-udivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s, t;
- uint32 m;
- Node nod;
-
- a = udiv(r->vconst, &m, &s, &t);
-//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (long)r->vconst, t, s, m);
- if(t != 0) {
- gins(AMOVL, l, ax);
- gins(ASHRL, nodconst(t), ax);
- gins(AMOVL, nodconst(m), dx);
- gins(AMULL, dx, Z);
- }
- else if(a) {
- if(l->op != OREGISTER) {
- regalloc(&nod, l, Z);
- gins(AMOVL, l, &nod);
- l = &nod;
- }
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- gins(AADDL, l, dx);
- gins(ARCRL, nodconst(1), dx);
- if(l == &nod)
- regfree(l);
- }
- else {
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- }
- if(s != 0)
- gins(ASHRL, nodconst(s), dx);
-}
-
-void
-sext(Node *d, Node *s, Node *l)
-{
- if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
- reg[D_DX]++;
- gins(ACDQ, Z, Z);
- }
- else {
- regalloc(d, l, Z);
- gins(AMOVL, s, d);
- gins(ASARL, nodconst(31), d);
- }
-}
-
-void
-sdiv2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(v > 0) {
- if(v > 1) {
- sext(&nod, n, l);
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- regfree(&nod);
- }
- else {
- gins(ACMPL, n, nodconst(0x80000000));
- gins(ASBBL, nodconst(-1), n);
- }
- gins(ASARL, nodconst(v), n);
- }
- if(c < 0)
- gins(ANEGL, Z, n);
-}
-
-void
-smod2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(c == 1) {
- zeroregm(n);
- return;
- }
-
- sext(&nod, n, l);
- if(v == 0) {
- zeroregm(n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- else if(v > 1) {
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- gins(AANDL, nodconst((1 << v) - 1), n);
- gins(ASUBL, &nod, n);
- }
- else {
- gins(AANDL, nodconst(1), n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- regfree(&nod);
-}
diff --git a/src/cmd/6c/doc.go b/src/cmd/6c/doc.go
deleted file mode 100644
index e0a22e78b..000000000
--- a/src/cmd/6c/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-6c is a version of the Plan 9 C compiler. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the x86-64, referred to by these tools as amd64.
-
-*/
-package main
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
deleted file mode 100644
index aa9d95d21..000000000
--- a/src/cmd/6c/gc.h
+++ /dev/null
@@ -1,359 +0,0 @@
-// Inferno utils/6c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
-//
-// 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 <u.h>
-#include "../cc/cc.h"
-#include "../6l/6.out.h"
-
-/*
- * 6c/amd64
- * Intel 386 with AMD64 extensions
- */
-#define SZ_CHAR 1
-#define SZ_SHORT 2
-#define SZ_INT 4
-#define SZ_LONG 4
-#define SZ_IND 8
-#define SZ_FLOAT 4
-#define SZ_VLONG 8
-#define SZ_DOUBLE 8
-#define FNX 100
-
-typedef struct Case Case;
-typedef struct C1 C1;
-typedef struct Reg Reg;
-typedef struct Rgn Rgn;
-typedef struct Renv Renv;
-
-EXTERN struct
-{
- Node* regtree;
- Node* basetree;
- short scale;
- short reg;
- short ptr;
-} idx;
-
-#define INDEXED 9
-
-#define A ((Addr*)0)
-#define P ((Prog*)0)
-
-struct Case
-{
- Case* link;
- vlong val;
- int32 label;
- char def;
- char isv;
-};
-#define C ((Case*)0)
-
-struct C1
-{
- vlong val;
- int32 label;
-};
-
-struct Reg
-{
- int32 pc;
- int32 rpo; /* reverse post ordering */
-
- Bits set;
- Bits use1;
- Bits use2;
-
- Bits refbehind;
- Bits refahead;
- Bits calbehind;
- Bits calahead;
- Bits regdiff;
- Bits act;
-
- int32 regu;
- int32 loop; /* could be shorter */
-
- Reg* log5;
- int32 active;
-
- Reg* p1;
- Reg* p2;
- Reg* p2link;
- Reg* s1;
- Reg* s2;
- Reg* link;
- Prog* prog;
-};
-#define R ((Reg*)0)
-
-struct Renv
-{
- int safe;
- Node base;
- Node* saved;
- Node* scope;
-};
-
-#define NRGN 600
-struct Rgn
-{
- Reg* enter;
- short cost;
- short varno;
- short regno;
-};
-
-EXTERN int32 breakpc;
-EXTERN int32 nbreak;
-EXTERN Case* cases;
-EXTERN Node constnode;
-EXTERN Node fconstnode;
-EXTERN Node vconstnode;
-EXTERN int32 continpc;
-EXTERN int32 curarg;
-EXTERN int32 cursafe;
-EXTERN Prog* lastp;
-EXTERN int32 maxargsafe;
-EXTERN int mnstring;
-EXTERN Node* nodrat;
-EXTERN Node* nodret;
-EXTERN Node* nodsafe;
-EXTERN int32 nrathole;
-EXTERN int32 nstring;
-EXTERN Prog* p;
-EXTERN int32 pc;
-EXTERN Node lregnode;
-EXTERN Node qregnode;
-EXTERN char string[NSNAME];
-EXTERN Sym* symrathole;
-EXTERN Node znode;
-EXTERN Prog zprog;
-EXTERN int reg[D_NONE];
-EXTERN int32 exregoffset;
-EXTERN int32 exfregoffset;
-EXTERN uchar typechlpv[NTYPE];
-
-#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
-#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
-#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
-#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define CLOAD 5
-#define CREF 5
-#define CINF 1000
-#define LOOP 3
-
-EXTERN Rgn region[NRGN];
-EXTERN Rgn* rgp;
-EXTERN int nregion;
-EXTERN int nvar;
-
-EXTERN Bits externs;
-EXTERN Bits params;
-EXTERN Bits consts;
-EXTERN Bits addrs;
-
-EXTERN int32 regbits;
-EXTERN int32 exregbits;
-
-EXTERN int change;
-EXTERN int suppress;
-
-EXTERN Reg* firstr;
-EXTERN Reg* lastr;
-EXTERN Reg zreg;
-EXTERN Reg* freer;
-EXTERN int32* idom;
-EXTERN Reg** rpo2r;
-EXTERN int32 maxnr;
-
-extern char* anames[];
-
-/*
- * sgen.c
- */
-void codgen(Node*, Node*);
-void gen(Node*);
-void noretval(int);
-void usedset(Node*, int);
-void xcom(Node*);
-void indx(Node*);
-int bcomplex(Node*, Node*);
-Prog* gtext(Sym*, int32);
-vlong argsize(int);
-
-/*
- * cgen.c
- */
-void zeroregm(Node*);
-void cgen(Node*, Node*);
-void reglcgen(Node*, Node*, Node*);
-void lcgen(Node*, Node*);
-void bcgen(Node*, int);
-void boolgen(Node*, int, Node*);
-void sugen(Node*, Node*, int32);
-int needreg(Node*, int);
-int hardconst(Node*);
-int immconst(Node*);
-
-/*
- * txt.c
- */
-void ginit(void);
-void gclean(void);
-void nextpc(void);
-void gargs(Node*, Node*, Node*);
-void garg1(Node*, Node*, Node*, int, Node**);
-Node* nodconst(int32);
-Node* nodfconst(double);
-Node* nodgconst(vlong, Type*);
-int nodreg(Node*, Node*, int);
-int isreg(Node*, int);
-void regret(Node*, Node*, Type*, int);
-void regalloc(Node*, Node*, Node*);
-void regfree(Node*);
-void regialloc(Node*, Node*, Node*);
-void regsalloc(Node*, Node*);
-void regaalloc1(Node*, Node*);
-void regaalloc(Node*, Node*);
-void regind(Node*, Node*);
-void gprep(Node*, Node*);
-void naddr(Node*, Addr*);
-void gcmp(int, Node*, vlong);
-void gmove(Node*, Node*);
-void gins(int a, Node*, Node*);
-void gopcode(int, Type*, Node*, Node*);
-int samaddr(Node*, Node*);
-void gbranch(int);
-void patch(Prog*, int32);
-int sconst(Node*);
-void gpseudo(int, Sym*, Node*);
-void gprefetch(Node*);
-void gpcdata(int, int);
-
-/*
- * swt.c
- */
-int swcmp(const void*, const void*);
-void doswit(Node*);
-void swit1(C1*, int, int32, Node*);
-void swit2(C1*, int, int32, Node*);
-void newcase(void);
-void bitload(Node*, Node*, Node*, Node*, Node*);
-void bitstore(Node*, Node*, Node*, Node*, Node*);
-int32 outstring(char*, int32);
-void nullwarn(Node*, Node*);
-void sextern(Sym*, Node*, int32, int32);
-void gextern(Sym*, Node*, int32, int32);
-void outcode(void);
-
-/*
- * list
- */
-void listinit(void);
-
-/*
- * reg.c
- */
-Reg* rega(void);
-int rcmp(const void*, const void*);
-void regopt(Prog*);
-void addmove(Reg*, int, int, int);
-Bits mkvar(Reg*, Addr*);
-void prop(Reg*, Bits, Bits);
-void loopit(Reg*, int32);
-void synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void paint3(Reg*, int, int32, int);
-void addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void peep(void);
-void excise(Reg*);
-Reg* uniqp(Reg*);
-Reg* uniqs(Reg*);
-int regtyp(Addr*);
-int anyvar(Addr*);
-int subprop(Reg*);
-int copyprop(Reg*);
-int copy1(Addr*, Addr*, Reg*, int);
-int copyu(Prog*, Addr*, Addr*);
-
-int copyas(Addr*, Addr*);
-int copyau(Addr*, Addr*);
-int copysub(Addr*, Addr*, Addr*, int);
-int copysub1(Prog*, Addr*, Addr*, int);
-
-int32 RtoB(int);
-int32 FtoB(int);
-int BtoR(int32);
-int BtoF(int32);
-
-#define D_HI D_NONE
-#define D_LO D_NONE
-
-/*
- * bound
- */
-void comtarg(void);
-
-/*
- * com64
- */
-int cond(int);
-int com64(Node*);
-void com64init(void);
-void bool64(Node*);
-int32 lo64v(Node*);
-int32 hi64v(Node*);
-Node* lo64(Node*);
-Node* hi64(Node*);
-
-/*
- * div/mul
- */
-void sdivgen(Node*, Node*, Node*, Node*);
-void udivgen(Node*, Node*, Node*, Node*);
-void sdiv2(int32, int, Node*, Node*);
-void smod2(int32, int, Node*, Node*);
-void mulgen(Type*, Node*, Node*);
-void genmuladd(Node*, Node*, int, Node*);
-void shiftit(Type*, Node*, Node*);
-
-#define D_X7 (D_X0+7)
-
-void fgopcode(int, Node*, Node*, int, int);
diff --git a/src/cmd/6c/list.c b/src/cmd/6c/list.c
deleted file mode 100644
index 28f5b8df7..000000000
--- a/src/cmd/6c/list.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// Inferno utils/6c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.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.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
- listinit6();
-}
diff --git a/src/cmd/6c/machcap.c b/src/cmd/6c/machcap.c
deleted file mode 100644
index 820d9a0aa..000000000
--- a/src/cmd/6c/machcap.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Inferno utils/6c/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/machcap.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"
-
-int
-machcap(Node *n)
-{
-
- if(n == Z)
- return 1; /* test */
-
- switch(n->op) {
- case OMUL:
- case OLMUL:
- case OASMUL:
- case OASLMUL:
- if(typechl[n->type->etype])
- return 1;
- if(typev[n->type->etype])
- return 1;
- break;
-
- case OCOM:
- case ONEG:
- case OADD:
- case OAND:
- case OOR:
- case OSUB:
- case OXOR:
- case OASHL:
- case OLSHR:
- case OASHR:
- if(typechlv[n->left->type->etype])
- return 1;
- break;
-
- case OCAST:
- return 1;
-
- case OCOND:
- case OCOMMA:
- case OLIST:
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
- return 1;
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- return 1;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OGT:
- case OLT:
- case OGE:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
diff --git a/src/cmd/6c/mul.c b/src/cmd/6c/mul.c
deleted file mode 100644
index 510edc05c..000000000
--- a/src/cmd/6c/mul.c
+++ /dev/null
@@ -1,458 +0,0 @@
-// Inferno utils/6c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/mul.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"
-
-typedef struct Malg Malg;
-typedef struct Mparam Mparam;
-
-struct Malg
-{
- schar vals[10];
-};
-
-struct Mparam
-{
- uint32 value;
- schar alg;
- char neg;
- char shift;
- char arg;
- schar off;
-};
-
-static Mparam multab[32];
-static int mulptr;
-
-static Malg malgs[] =
-{
- {0, 100},
- {-1, 1, 100},
- {-9, -5, -3, 3, 5, 9, 100},
- {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
- {-8, -4, -2, 2, 4, 8, 100},
-};
-
-/*
- * return position of lowest 1
- */
-int
-lowbit(uint32 v)
-{
- int s, i;
- uint32 m;
-
- s = 0;
- m = 0xFFFFFFFFUL;
- for(i = 16; i > 0; i >>= 1) {
- m >>= i;
- if((v & m) == 0) {
- v >>= i;
- s += i;
- }
- }
- return s;
-}
-
-void
-genmuladd(Node *d, Node *s, int m, Node *a)
-{
- Node nod;
-
- nod.op = OINDEX;
- nod.left = a;
- nod.right = s;
- nod.scale = m;
- nod.type = types[TIND];
- nod.xoffset = 0;
- xcom(&nod);
- gopcode(OADDR, d->type, &nod, d);
-}
-
-void
-mulparam(uint32 m, Mparam *mp)
-{
- int c, i, j, n, o, q, s;
- int bc, bi, bn, bo, bq, bs, bt;
- schar *p;
- int32 u;
- uint32 t;
-
- bc = bq = 10;
- bi = bn = bo = bs = bt = 0;
- for(i = 0; i < nelem(malgs); i++) {
- for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
- for(s = 0; s < 2; s++) {
- c = 10;
- q = 10;
- u = m - o;
- if(u == 0)
- continue;
- if(s) {
- o = -o;
- if(o > 0)
- continue;
- u = -u;
- }
- n = lowbit(u);
- t = (uint32)u >> n;
- switch(i) {
- case 0:
- if(t == 1) {
- c = s + 1;
- q = 0;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = s + 1;
- if(n)
- c++;
- q = 0;
- break;
- }
- if(s)
- break;
- switch(t) {
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- c = 2;
- if(n)
- c++;
- q = 1;
- break;
- }
- break;
- case 1:
- if(t == 1) {
- c = 3;
- q = 3;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = 3;
- q = 2;
- break;
- }
- break;
- case 2:
- if(t == 1) {
- c = 3;
- q = 2;
- break;
- }
- break;
- case 3:
- if(s)
- break;
- if(t == 1) {
- c = 3;
- q = 1;
- break;
- }
- break;
- case 4:
- if(t == 1) {
- c = 3;
- q = 0;
- break;
- }
- break;
- }
- if(c < bc || (c == bc && q > bq)) {
- bc = c;
- bi = i;
- bn = n;
- bo = o;
- bq = q;
- bs = s;
- bt = t;
- }
- }
- }
- mp->value = m;
- if(bc <= 3) {
- mp->alg = bi;
- mp->shift = bn;
- mp->off = bo;
- mp->neg = bs;
- mp->arg = bt;
- }
- else
- mp->alg = -1;
-}
-
-int
-m0(int a)
-{
- switch(a) {
- case -2:
- case 2:
- return 2;
- case -3:
- case 3:
- return 2;
- case -4:
- case 4:
- return 4;
- case -5:
- case 5:
- return 4;
- case 6:
- return 2;
- case -8:
- case 8:
- return 8;
- case -9:
- case 9:
- return 8;
- case 10:
- return 4;
- case 12:
- return 2;
- case 15:
- return 2;
- case 18:
- return 8;
- case 20:
- return 4;
- case 24:
- return 2;
- case 25:
- return 4;
- case 27:
- return 2;
- case 36:
- return 8;
- case 40:
- return 4;
- case 45:
- return 4;
- case 72:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m0");
- return 0;
-}
-
-int
-m1(int a)
-{
- switch(a) {
- case 15:
- return 4;
- case 25:
- return 4;
- case 27:
- return 8;
- case 45:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m1");
- return 0;
-}
-
-int
-m2(int a)
-{
- switch(a) {
- case 6:
- return 2;
- case 10:
- return 2;
- case 12:
- return 4;
- case 18:
- return 2;
- case 20:
- return 4;
- case 24:
- return 8;
- case 36:
- return 4;
- case 40:
- return 8;
- case 72:
- return 8;
- }
- diag(Z, "bad m2");
- return 0;
-}
-
-void
-shiftit(Type *t, Node *s, Node *d)
-{
- int32 c;
-
- c = (int32)s->vconst & 31;
- switch(c) {
- case 0:
- break;
- case 1:
- gopcode(OADD, t, d, d);
- break;
- default:
- gopcode(OASHL, t, s, d);
- }
-}
-
-static int
-mulgen1(uint32 v, Node *n)
-{
- int i, o;
- Mparam *p;
- Node nod, nods;
-
- for(i = 0; i < nelem(multab); i++) {
- p = &multab[i];
- if(p->value == v)
- goto found;
- }
-
- p = &multab[mulptr];
- if(++mulptr == nelem(multab))
- mulptr = 0;
-
- mulparam(v, p);
-
-found:
-// print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
- if(p->alg < 0)
- return 0;
-
- nods = *nodconst(p->shift);
-
- o = OADD;
- if(p->alg > 0) {
- regalloc(&nod, n, Z);
- if(p->off < 0)
- o = OSUB;
- }
-
- switch(p->alg) {
- case 0:
- switch(p->arg) {
- case 1:
- shiftit(n->type, &nods, n);
- break;
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- genmuladd(n, n, m1(p->arg), n);
- /* fall thru */
- case 3:
- case 5:
- case 9:
- genmuladd(n, n, m0(p->arg), n);
- shiftit(n->type, &nods, n);
- break;
- default:
- goto bad;
- }
- if(p->neg == 1)
- gins(ANEGL, Z, n);
- break;
- case 1:
- switch(p->arg) {
- case 1:
- gmove(n, &nod);
- shiftit(n->type, &nods, &nod);
- break;
- case 3:
- case 5:
- case 9:
- genmuladd(&nod, n, m0(p->arg), n);
- shiftit(n->type, &nods, &nod);
- break;
- default:
- goto bad;
- }
- if(p->neg)
- gopcode(o, n->type, &nod, n);
- else {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- break;
- case 2:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- goto comop;
- case 3:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- genmuladd(n, &nod, m2(p->off), n);
- break;
- case 4:
- genmuladd(&nod, n, m0(p->off), nodconst(0));
- shiftit(n->type, &nods, n);
- goto comop;
- default:
- diag(Z, "bad mul alg");
- break;
- comop:
- if(p->neg) {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- else
- gopcode(o, n->type, &nod, n);
- }
-
- if(p->alg > 0)
- regfree(&nod);
-
- return 1;
-
-bad:
- diag(Z, "mulgen botch");
- return 1;
-}
-
-void
-mulgen(Type *t, Node *r, Node *n)
-{
- if(!mulgen1(r->vconst, n))
- gopcode(OMUL, t, r, n);
-}
diff --git a/src/cmd/6c/peep.c b/src/cmd/6c/peep.c
deleted file mode 100644
index a11067c84..000000000
--- a/src/cmd/6c/peep.c
+++ /dev/null
@@ -1,902 +0,0 @@
-// Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.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"
-
-static int
-needc(Prog *p)
-{
- while(p != P) {
- switch(p->as) {
- case AADCL:
- case AADCQ:
- case ASBBL:
- case ASBBQ:
- case ARCRL:
- case ARCRQ:
- return 1;
- case AADDL:
- case AADDQ:
- case ASUBL:
- case ASUBQ:
- case AJMP:
- case ARET:
- case ACALL:
- return 0;
- default:
- if(p->to.type == D_BRANCH)
- return 0;
- }
- p = p->link;
- }
- return 0;
-}
-
-static Reg*
-rnops(Reg *r)
-{
- Prog *p;
- Reg *r1;
-
- if(r != R)
- for(;;){
- p = r->prog;
- if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
- break;
- r1 = uniqs(r);
- if(r1 == R)
- break;
- r = r1;
- }
- return r;
-}
-
-void
-peep(void)
-{
- Reg *r, *r1, *r2;
- Prog *p, *p1;
- int t;
-
- /*
- * complete R structure
- */
- t = 0;
- for(r=firstr; r!=R; r=r1) {
- r1 = r->link;
- if(r1 == R)
- break;
- p = r->prog->link;
- while(p != r1->prog)
- switch(p->as) {
- default:
- r2 = rega();
- r->link = r2;
- r2->link = r1;
-
- r2->prog = p;
- r2->p1 = r;
- r->s1 = r2;
- r2->s1 = r1;
- r1->p1 = r2;
-
- r = r2;
- t++;
-
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- p = p->link;
- }
- }
-
- pc = 0; /* speculating it won't kill */
-
-loop1:
-
- t = 0;
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- case AMOVL:
- case AMOVQ:
- case AMOVSS:
- case AMOVSD:
- if(regtyp(&p->to))
- if(regtyp(&p->from)) {
- if(copyprop(r)) {
- excise(r);
- t++;
- } else
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- break;
-
- case AMOVBLZX:
- case AMOVWLZX:
- case AMOVBLSX:
- case AMOVWLSX:
- if(regtyp(&p->to)) {
- r1 = rnops(uniqs(r));
- if(r1 != R) {
- p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
- p1->as = AMOVL;
- t++;
- }
- }
- }
- break;
-
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- if(regtyp(&p->to)) {
- r1 = rnops(uniqs(r));
- if(r1 != R) {
- p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
- p1->as = AMOVQ;
- t++;
- }
- }
- }
- break;
-
- case AADDL:
- case AADDQ:
- case AADDW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1){
- if(p->as == AADDQ)
- p->as = ADECQ;
- else if(p->as == AADDL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == AADDQ)
- p->as = AINCQ;
- else if(p->as == AADDL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- break;
-
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1) {
- if(p->as == ASUBQ)
- p->as = AINCQ;
- else if(p->as == ASUBL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == ASUBQ)
- p->as = ADECQ;
- else if(p->as == ASUBL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- break;
- }
- }
- if(t)
- goto loop1;
-}
-
-void
-excise(Reg *r)
-{
- Prog *p;
-
- p = r->prog;
- p->as = ANOP;
- p->from = zprog.from;
- p->to = zprog.to;
-}
-
-Reg*
-uniqp(Reg *r)
-{
- Reg *r1;
-
- r1 = r->p1;
- if(r1 == R) {
- r1 = r->p2;
- if(r1 == R || r1->p2link != R)
- return R;
- } else
- if(r->p2 != R)
- return R;
- return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
- Reg *r1;
-
- r1 = r->s1;
- if(r1 == R) {
- r1 = r->s2;
- if(r1 == R)
- return R;
- } else
- if(r->s2 != R)
- return R;
- return r1;
-}
-
-int
-regtyp(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t >= D_AX && t <= D_R15)
- return 1;
- if(t >= D_X0 && t <= D_X0+15)
- return 1;
- return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- * MOV a, R0
- * ADD b, R0 / no use of R1
- * MOV R0, R1
- * would be converted to
- * MOV a, R1
- * ADD b, R1
- * MOV R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
- int t;
-
- p = r0->prog;
- v1 = &p->from;
- if(!regtyp(v1))
- return 0;
- v2 = &p->to;
- if(!regtyp(v2))
- return 0;
- for(r=uniqp(r0); r!=R; r=uniqp(r)) {
- if(uniqs(r) == R)
- break;
- p = r->prog;
- switch(p->as) {
- case ACALL:
- return 0;
-
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
- goto giveup;
-
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- if(p->from.type == D_CONST)
- break;
- goto giveup;
-
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case AREP:
- case AREPN:
-
- case ACWD:
- case ACDQ:
- case ACQO:
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- case AMOVQL:
- giveup:
- return 0;
-
- case AMOVL:
- case AMOVQ:
- if(p->to.type == v1->type)
- goto gotit;
- break;
- }
- if(copyau(&p->from, v2) ||
- copyau(&p->to, v2))
- break;
- if(copysub(&p->from, v1, v2, 0) ||
- copysub(&p->to, v1, v2, 0))
- break;
- }
- return 0;
-
-gotit:
- copysub(&p->to, v1, v2, 1);
- if(debug['P']) {
- print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
- print(" excise");
- print("\n");
- }
- for(r=uniqs(r); r!=r0; r=uniqs(r)) {
- p = r->prog;
- copysub(&p->from, v1, v2, 1);
- copysub(&p->to, v1, v2, 1);
- if(debug['P'])
- print("%P\n", r->prog);
- }
- t = v1->type;
- v1->type = v2->type;
- v2->type = t;
- if(debug['P'])
- print("%P last\n", r->prog);
- return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * use v2 return fail
- * -----------------
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * set v2 return success
- */
-int
-copyprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
-
- p = r0->prog;
- v1 = &p->from;
- v2 = &p->to;
- if(copyas(v1, v2))
- return 1;
- for(r=firstr; r!=R; r=r->link)
- r->active = 0;
- return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
- int t;
- Prog *p;
-
- if(r->active) {
- if(debug['P'])
- print("act set; return 1\n");
- return 1;
- }
- r->active = 1;
- if(debug['P'])
- print("copy %D->%D f=%d\n", v1, v2, f);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['P'])
- print("%P", p);
- if(!f && uniqp(r) == R) {
- f = 1;
- if(debug['P'])
- print("; merge; f=%d", f);
- }
- t = copyu(p, v2, A);
- switch(t) {
- case 2: /* rar, can't split */
- if(debug['P'])
- print("; %D rar; return 0\n", v2);
- return 0;
-
- case 3: /* set */
- if(debug['P'])
- print("; %D set; return 1\n", v2);
- return 1;
-
- case 1: /* used, substitute */
- case 4: /* use and set */
- if(f) {
- if(!debug['P'])
- return 0;
- if(t == 4)
- print("; %D used+set and f=%d; return 0\n", v2, f);
- else
- print("; %D used and f=%d; return 0\n", v2, f);
- return 0;
- }
- if(copyu(p, v2, v1)) {
- if(debug['P'])
- print("; sub fail; return 0\n");
- return 0;
- }
- if(debug['P'])
- print("; sub %D/%D", v2, v1);
- if(t == 4) {
- if(debug['P'])
- print("; %D used+set; return 1\n", v2);
- return 1;
- }
- break;
- }
- if(!f) {
- t = copyu(p, v1, A);
- if(!f && (t == 2 || t == 3 || t == 4)) {
- f = 1;
- if(debug['P'])
- print("; %D set and !f; f=%d", v1, f);
- }
- }
- if(debug['P'])
- print("\n");
- if(r->s2)
- if(!copy1(v1, v2, r->s2, f))
- return 0;
- }
- return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
- switch(p->as) {
-
- default:
- if(debug['P'])
- print("unknown op %A\n", p->as);
- /* SBBL; ADCL; FLD1; SAHF */
- return 2;
-
-
- case ANEGB:
- case ANEGW:
- case ANEGL:
- case ANEGQ:
- case ANOTB:
- case ANOTW:
- case ANOTL:
- case ANOTQ:
- if(copyas(&p->to, v))
- return 2;
- break;
-
- case ALEAL: /* lhs addr, rhs store */
- case ALEAQ:
- if(copyas(&p->from, v))
- return 2;
-
-
- case ANOP: /* rhs store */
- case AMOVL:
- case AMOVQ:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- case AMOVWLSX:
- case AMOVWLZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVQL:
-
- case AMOVSS:
- case AMOVSD:
- case ACVTSD2SL:
- case ACVTSD2SQ:
- case ACVTSD2SS:
- case ACVTSL2SD:
- case ACVTSL2SS:
- case ACVTSQ2SD:
- case ACVTSQ2SS:
- case ACVTSS2SD:
- case ACVTSS2SL:
- case ACVTSS2SQ:
- case ACVTTSD2SL:
- case ACVTTSD2SQ:
- case ACVTTSS2SL:
- case ACVTTSS2SQ:
- if(copyas(&p->to, v)) {
- if(s != A)
- return copysub(&p->from, v, s, 1);
- if(copyau(&p->from, v))
- return 4;
- return 3;
- }
- goto caseread;
-
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- if(copyas(&p->to, v))
- return 2;
- if(copyas(&p->from, v))
- if(p->from.type == D_CX)
- return 2;
- goto caseread;
-
- case AADDB: /* rhs rar */
- case AADDL:
- case AADDQ:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDQ:
- case AANDW:
- case ADECL:
- case ADECQ:
- case ADECW:
- case AINCL:
- case AINCQ:
- case AINCW:
- case ASUBB:
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- case AORB:
- case AORL:
- case AORQ:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORQ:
- case AXORW:
- case AMOVB:
- case AMOVW:
-
- case AADDSD:
- case AADDSS:
- case ACMPSD:
- case ACMPSS:
- case ADIVSD:
- case ADIVSS:
- case AMAXSD:
- case AMAXSS:
- case AMINSD:
- case AMINSS:
- case AMULSD:
- case AMULSS:
- case ARCPSS:
- case ARSQRTSS:
- case ASQRTSD:
- case ASQRTSS:
- case ASUBSD:
- case ASUBSS:
- case AXORPD:
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
-
- case ACMPL: /* read only */
- case ACMPW:
- case ACMPB:
- case ACMPQ:
-
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
-
- case ACOMISD:
- case ACOMISS:
- case AUCOMISD:
- case AUCOMISS:
- caseread:
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- return copysub(&p->to, v, s, 1);
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- break;
-
- case AJGE: /* no reference */
- case AJNE:
- case AJLE:
- case AJEQ:
- case AJHI:
- case AJLS:
- case AJMI:
- case AJPL:
- case AJGT:
- case AJLT:
- case AJCC:
- case AJCS:
-
- case AADJSP:
- case AWAIT:
- case ACLD:
- break;
-
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE) {
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
- }
-
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- case ACQO:
- if(v->type == D_AX || v->type == D_DX)
- return 2;
- goto caseread;
-
- case AREP:
- case AREPN:
- if(v->type == D_CX)
- return 2;
- goto caseread;
-
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- if(v->type == D_DI || v->type == D_SI)
- return 2;
- goto caseread;
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- if(v->type == D_AX || v->type == D_DI)
- return 2;
- goto caseread;
-
- case AJMP: /* funny */
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARET: /* funny */
- if(v->type == REGRET || v->type == FREGRET)
- return 2;
- if(s != A)
- return 1;
- return 3;
-
- case ACALL: /* funny */
- if(REGARG >= 0 && v->type == (uchar)REGARG)
- return 2;
-
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 4;
- return 3;
-
- case ATEXT: /* funny */
- if(REGARG >= 0 && v->type == (uchar)REGARG)
- return 3;
- return 0;
- }
- return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
- if(a->type != v->type)
- return 0;
- if(regtyp(v))
- return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
- if(v->offset == a->offset)
- return 1;
- return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
- if(copyas(a, v))
- return 1;
- if(regtyp(v)) {
- if(a->type-D_INDIR == v->type)
- return 1;
- if(a->index == v->type)
- return 1;
- }
- return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
- int t;
-
- if(copyas(a, v)) {
- t = s->type;
- if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
- if(f)
- a->type = t;
- }
- return 0;
- }
- if(regtyp(v)) {
- t = v->type;
- if(a->type == t+D_INDIR) {
- if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
- return 1; /* can't use BP-base with index */
- if(f)
- a->type = s->type+D_INDIR;
-// return 0;
- }
- if(a->index == t) {
- if(f)
- a->index = s->type;
- return 0;
- }
- return 0;
- }
- return 0;
-}
diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c
deleted file mode 100644
index 6f8d3ce14..000000000
--- a/src/cmd/6c/reg.c
+++ /dev/null
@@ -1,1523 +0,0 @@
-// Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.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"
-
-static void fixjmp(Reg*);
-
-Reg*
-rega(void)
-{
- Reg *r;
-
- r = freer;
- if(r == R) {
- r = alloc(sizeof(*r));
- } else
- freer = r->link;
-
- *r = zreg;
- return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
- Rgn *p1, *p2;
- int c1, c2;
-
- p1 = (Rgn*)a1;
- p2 = (Rgn*)a2;
- c1 = p2->cost;
- c2 = p1->cost;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- int32 initpc, val, npc;
- uint32 vreg;
- Bits bit;
- struct
- {
- int32 m;
- int32 c;
- Reg* p;
- } log5[6], *lp;
-
- firstr = R;
- lastr = R;
- nvar = 0;
- regbits = RtoB(D_SP) | RtoB(D_AX) | RtoB(D_X0);
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- consts.b[z] = 0;
- addrs.b[z] = 0;
- }
-
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
- val = 5L * 5L * 5L * 5L * 5L;
- lp = log5;
- for(i=0; i<5; i++) {
- lp->m = val;
- lp->c = 0;
- lp->p = R;
- val /= 5L;
- lp++;
- }
- val = 0;
- for(; p != P; p = p->link) {
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- continue;
- }
- r = rega();
- if(firstr == R) {
- firstr = r;
- lastr = r;
- } else {
- lastr->link = r;
- r->p1 = lastr;
- lastr->s1 = r;
- lastr = r;
- }
- r->prog = p;
- r->pc = val;
- val++;
-
- lp = log5;
- for(i=0; i<5; i++) {
- lp->c--;
- if(lp->c <= 0) {
- lp->c = lp->m;
- if(lp->p != R)
- lp->p->log5 = r;
- lp->p = r;
- (lp+1)->c = 0;
- break;
- }
- lp++;
- }
-
- r1 = r->p1;
- if(r1 != R)
- switch(r1->prog->as) {
- case ARET:
- case AJMP:
- case AIRETL:
- case AIRETQ:
- r->p1 = R;
- r1->s1 = R;
- }
-
- bit = mkvar(r, &p->from);
- if(bany(&bit))
- switch(p->as) {
- /*
- * funny
- */
- case ALEAL:
- case ALEAQ:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
-
- /*
- * left side read
- */
- default:
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
- break;
- }
-
- bit = mkvar(r, &p->to);
- if(bany(&bit))
- switch(p->as) {
- default:
- diag(Z, "reg: unknown op: %A", p->as);
- break;
-
- /*
- * right side read
- */
- case ACMPB:
- case ACMPL:
- case ACMPQ:
- case ACMPW:
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
- case ACOMISS:
- case ACOMISD:
- case AUCOMISS:
- case AUCOMISD:
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- break;
-
- /*
- * right side write
- */
- case ANOP:
- case AMOVL:
- case AMOVQ:
- case AMOVB:
- case AMOVW:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- case AMOVWLSX:
- case AMOVWLZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVQL:
-
- case AMOVSS:
- case AMOVSD:
- case ACVTSD2SL:
- case ACVTSD2SQ:
- case ACVTSD2SS:
- case ACVTSL2SD:
- case ACVTSL2SS:
- case ACVTSQ2SD:
- case ACVTSQ2SS:
- case ACVTSS2SD:
- case ACVTSS2SL:
- case ACVTSS2SQ:
- case ACVTTSD2SL:
- case ACVTTSD2SQ:
- case ACVTTSS2SL:
- case ACVTTSS2SQ:
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- break;
-
- /*
- * right side read+write
- */
- case AADDB:
- case AADDL:
- case AADDQ:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDQ:
- case AANDW:
- case ASUBB:
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- case AORB:
- case AORL:
- case AORQ:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORQ:
- case AXORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- case ANEGL:
- case ANEGQ:
- case ANOTL:
- case ANOTQ:
- case AADCL:
- case AADCQ:
- case ASBBL:
- case ASBBQ:
-
- case AADDSD:
- case AADDSS:
- case ACMPSD:
- case ACMPSS:
- case ADIVSD:
- case ADIVSS:
- case AMAXSD:
- case AMAXSS:
- case AMINSD:
- case AMINSS:
- case AMULSD:
- case AMULSS:
- case ARCPSS:
- case ARSQRTSS:
- case ASQRTSD:
- case ASQRTSS:
- case ASUBSD:
- case ASUBSS:
- case AXORPD:
- for(z=0; z<BITS; z++) {
- r->set.b[z] |= bit.b[z];
- r->use2.b[z] |= bit.b[z];
- }
- break;
-
- /*
- * funny
- */
- case ACALL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
- }
-
- switch(p->as) {
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
-
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- case ACQO:
- r->regu |= RtoB(D_AX) | RtoB(D_DX);
- break;
-
- case AREP:
- case AREPN:
- case ALOOP:
- case ALOOPEQ:
- case ALOOPNE:
- r->regu |= RtoB(D_CX);
- break;
-
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- case AMOVSW:
- case ACMPSB:
- case ACMPSL:
- case ACMPSQ:
- case ACMPSW:
- r->regu |= RtoB(D_SI) | RtoB(D_DI);
- break;
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- case ASTOSW:
- case ASCASB:
- case ASCASL:
- case ASCASQ:
- case ASCASW:
- r->regu |= RtoB(D_AX) | RtoB(D_DI);
- break;
-
- case AINSB:
- case AINSL:
- case AINSW:
- case AOUTSB:
- case AOUTSL:
- case AOUTSW:
- r->regu |= RtoB(D_DI) | RtoB(D_DX);
- break;
- }
- }
- if(firstr == R)
- return;
- initpc = pc - val;
- npc = val;
-
- /*
- * pass 2
- * turn branch references to pointers
- * build back pointers
- */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- val = p->to.offset - initpc;
- r1 = firstr;
- while(r1 != R) {
- r2 = r1->log5;
- if(r2 != R && val >= r2->pc) {
- r1 = r2;
- continue;
- }
- if(r1->pc == val)
- break;
- r1 = r1->link;
- }
- if(r1 == R) {
- nearln = p->lineno;
- diag(Z, "ref not found\n%P", p);
- continue;
- }
- if(r1 == r) {
- nearln = p->lineno;
- diag(Z, "ref to self\n%P", p);
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R']) {
- p = firstr->prog;
- print("\n%L %D\n", p->lineno, &p->from);
- }
-
- /*
- * pass 2.1
- * fix jumps
- */
- fixjmp(firstr);
-
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- change = 0;
- loopit(firstr, npc);
- if(debug['R'] && debug['v']) {
- print("\nlooping structure:\n");
- for(r = firstr; r != R; r = r->link) {
- print("%d:%P", r->loop, r->prog);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->use1.b[z] |
- r->use2.b[z] |
- r->set.b[z];
- if(bany(&bit)) {
- print("\t");
- if(bany(&r->use1))
- print(" u1=%B", r->use1);
- if(bany(&r->use2))
- print(" u2=%B", r->use2);
- if(bany(&r->set))
- print(" st=%B", r->set);
- }
- print("\n");
- }
- }
-
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
-loop1:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARET)
- prop(r, zbits, zbits);
-loop11:
- /* pick up unreachable code */
- i = 0;
- for(r = firstr; r != R; r = r1) {
- r1 = r->link;
- if(r1 && r1->active && !r->active) {
- prop(r, zbits, zbits);
- i = 1;
- }
- }
- if(i)
- goto loop11;
- if(change)
- goto loop1;
-
-
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
-loop2:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(change)
- goto loop2;
-
-
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
- r = firstr;
- if(r) {
- for(z=0; z<BITS; z++)
- bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
- ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "used and not set: %B", bit);
- if(debug['R'] && !debug['w'])
- print("used and not set: %B\n", bit);
- }
- }
- if(debug['R'] && debug['v'])
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link)
- r->act = zbits;
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->link) {
- if(debug['R'] && debug['v']) {
- print("%P\t", r->prog);
- if(bany(&r->set))
- print("s:%B ", r->set);
- if(bany(&r->refahead))
- print("ra:%B ", r->refahead);
- if(bany(&r->calahead))
- print("ca:%B ", r->calahead);
- print("\n");
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] &
- ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set and not used: %B\n", bit);
- excise(r);
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- rgp->enter = r;
- rgp->varno = i;
- change = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(change <= 0) {
- if(debug['R'])
- print("%L$%d: %B\n",
- r->prog->lineno, change, blsh(i));
- continue;
- }
- rgp->cost = change;
- nregion++;
- if(nregion >= NRGN)
- fatal(Z, "too many regions");
- rgp++;
- }
- }
- qsort(region, nregion, sizeof(region[0]), rcmp);
-
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
- rgp = region;
- for(i=0; i<nregion; i++) {
- bit = blsh(rgp->varno);
- vreg = paint2(rgp->enter, rgp->varno);
- vreg = allreg(vreg, rgp);
- if(debug['R']) {
- print("%L$%d %R: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
- }
- if(rgp->regno != 0)
- paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
- rgp++;
- }
- /*
- * pass 7
- * peep-hole on basic block
- */
- if(!debug['R'] || debug['P'])
- peep();
-
- /*
- * pass 8
- * recalculate pc
- */
- val = initpc;
- for(r = firstr; r != R; r = r1) {
- r->pc = val;
- p = r->prog;
- p1 = P;
- r1 = r->link;
- if(r1 != R)
- p1 = r1->prog;
- for(; p != p1; p = p->link) {
- switch(p->as) {
- default:
- val++;
- break;
-
- case ANOP:
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- break;
- }
- }
- }
- pc = val;
-
- /*
- * fix up branches
- */
- if(debug['R'])
- if(bany(&addrs))
- print("addrs: %B\n", addrs);
-
- r1 = 0; /* set */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- }
- r1 = r;
- }
-
- /*
- * last pass
- * eliminate nops
- * free aux structures
- */
- for(p = firstr->prog; p != P; p = p->link){
- while(p->link && p->link->as == ANOP)
- p->link = p->link->link;
- }
- if(r1 != R) {
- r1->link = freer;
- freer = firstr;
- }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
- Prog *p, *p1;
- Addr *a;
- Var *v;
-
- p1 = alloc(sizeof(*p1));
- *p1 = zprog;
- p = r->prog;
-
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
-
- v = var + bn;
-
- a = &p1->to;
- a->sym = v->sym;
- a->offset = v->offset;
- a->etype = v->etype;
- a->type = v->name;
-
- p1->as = AMOVL;
- if(v->etype == TCHAR || v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TSHORT || v->etype == TUSHORT)
- p1->as = AMOVW;
- if(v->etype == TVLONG || v->etype == TUVLONG || (v->etype == TIND && ewidth[TIND] == 8))
- p1->as = AMOVQ;
- if(v->etype == TFLOAT)
- p1->as = AMOVSS;
- if(v->etype == TDOUBLE)
- p1->as = AMOVSD;
-
- p1->from.type = rn;
- if(!f) {
- p1->from = *a;
- *a = zprog.from;
- a->type = rn;
- if(v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TUSHORT)
- p1->as = AMOVW;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
-}
-
-uint32
-doregbits(int r)
-{
- uint32 b;
-
- b = 0;
- if(r >= D_INDIR)
- r -= D_INDIR;
- if(r >= D_AX && r <= D_R15)
- b |= RtoB(r);
- else
- if(r >= D_AL && r <= D_R15B)
- b |= RtoB(r-D_AL+D_AX);
- else
- if(r >= D_AH && r <= D_BH)
- b |= RtoB(r-D_AH+D_AX);
- else
- if(r >= D_X0 && r <= D_X0+15)
- b |= FtoB(r);
- return b;
-}
-
-Bits
-mkvar(Reg *r, Addr *a)
-{
- Var *v;
- int i, t, n, et, z;
- int32 o;
- Bits bit;
- LSym *s;
-
- /*
- * mark registers used
- */
- t = a->type;
- r->regu |= doregbits(t);
- r->regu |= doregbits(a->index);
-
- switch(t) {
- default:
- goto none;
- case D_ADDR:
- a->type = a->index;
- bit = mkvar(r, a);
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- a->type = t;
- goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_PARAM:
- case D_AUTO:
- n = t;
- break;
- }
- s = a->sym;
- if(s == nil)
- goto none;
- if(s->name[0] == '.')
- goto none;
- et = a->etype;
- o = a->offset;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(n == v->name)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(nvar >= NVAR)
- fatal(Z, "variable not optimized: %s", s->name);
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->name = n;
- v->etype = et;
- if(debug['R'])
- print("bit=%2d et=%2d %D\n", i, et, a);
-
-out:
- bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(v->etype != et || !(typechlpfd[et] || typev[et])) /* funny punning */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- return bit;
-
-none:
- return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
- Reg *r1, *r2;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- change++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- change++;
- }
- }
- switch(r1->prog->as) {
- case ACALL:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
-
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
-
- case ARET:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->p2link)
- prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
- Reg *r1;
-
- r->rpo = 1;
- r1 = r->s1;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- r1 = r->s2;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- rpo2r[n] = r;
- n++;
- return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
- int32 t;
-
- if(rpo1 == -1)
- return rpo2;
- while(rpo1 != rpo2){
- if(rpo1 > rpo2){
- t = rpo2;
- rpo2 = rpo1;
- rpo1 = t;
- }
- while(rpo1 < rpo2){
- t = idom[rpo2];
- if(t >= rpo2)
- fatal(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
- while(s > r)
- s = idom[s];
- return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
- int32 src;
-
- src = r->rpo;
- if(r->p1 != R && doms(idom, src, r->p1->rpo))
- return 1;
- for(r = r->p2; r != R; r = r->p2link)
- if(doms(idom, src, r->rpo))
- return 1;
- return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
- if(r->rpo < head || r->active == head)
- return;
- r->active = head;
- r->loop += LOOP;
- if(r->p1 != R)
- loopmark(rpo2r, head, r->p1);
- for(r = r->p2; r != R; r = r->p2link)
- loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
- Reg *r1;
- int32 i, d, me;
-
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(int32));
- maxnr = nr;
- }
-
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "too many reg nodes");
- nr = d;
- for(i = 0; i < nr / 2; i++){
- r1 = rpo2r[i];
- rpo2r[i] = rpo2r[nr - 1 - i];
- rpo2r[nr - 1 - i] = r1;
- }
- for(i = 0; i < nr; i++)
- rpo2r[i]->rpo = i;
-
- idom[0] = 0;
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- me = r1->rpo;
- d = -1;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(r1->rpo < me)
- d = rpolca(idom, d, r1->rpo);
- idom[i] = d;
- }
-
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- r1->loop++;
- if(r1->p2 != R && loophead(idom, r1))
- loopmark(rpo2r, i, r1);
- }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
- Reg *r1;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->s1) {
- for(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- change++;
- }
- }
- if(r1->active)
- break;
- r1->active = 1;
- for(z=0; z<BITS; z++)
- dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
- if(r1->s2 != R)
- synch(r1->s2, dif);
- }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
- Var *v;
- int i;
-
- v = var + r->varno;
- r->regno = 0;
- switch(v->etype) {
-
- default:
- diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
- break;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- case TARRAY:
- i = BtoR(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return RtoB(i);
- }
- break;
-
- case TDOUBLE:
- case TFLOAT:
- i = BtoF(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return FtoB(i);
- }
- break;
- }
- return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\td %B $%d\n", r->loop,
- r->prog, blsh(bn), change);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu1 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu2 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tst %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-uint32
-regset(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = b & 0xFFFF? BtoR(b): BtoF(b);
- if(v.type == 0)
- diag(Z, "zero v.type for %#ux", b);
- c = copyu(r->prog, &v, A);
- if(c == 3)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = b & 0xFFFF? BtoR(b): BtoF(b);
- c = copyu(r->prog, &v, A);
- if(c == 1 || c == 2 || c == 4)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
- Reg *r1;
- int z;
- uint32 bb, vreg, x;
-
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
-
- vreg |= r->regu;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-
- bb = vreg;
- for(; r; r=r->s1) {
- x = r->regu & ~bb;
- if(x) {
- vreg |= reguse(r, x);
- bb |= regset(r, x);
- }
- }
- return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
- a->sym = 0;
- a->offset = 0;
- a->type = rn;
-}
-
-int32
-RtoB(int r)
-{
-
- if(r < D_AX || r > D_R15)
- return 0;
- return 1L << (r-D_AX);
-}
-
-int
-BtoR(int32 b)
-{
-
- b &= 0xffffL;
- if(nacl)
- b &= ~((1<<(D_BP-D_AX)) | (1<<(D_R15-D_AX)));
- if(b == 0)
- return 0;
- return bitno(b) + D_AX;
-}
-
-/*
- * bit reg
- * 16 X5
- * 17 X6
- * 18 X7
- */
-int32
-FtoB(int f)
-{
- if(f < FREGMIN || f > FREGEXT)
- return 0;
- return 1L << (f - FREGMIN + 16);
-}
-
-int
-BtoF(int32 b)
-{
-
- b &= 0x70000L;
- if(b == 0)
- return 0;
- return bitno(b) - 16 + FREGMIN;
-}
-
-/* what instruction does a JMP to p eventually land on? */
-static Reg*
-chasejmp(Reg *r, int *jmploop)
-{
- int n;
-
- n = 0;
- for(; r; r=r->s2) {
- if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH)
- break;
- if(++n > 10) {
- *jmploop = 1;
- break;
- }
- }
- return r;
-}
-
-/* mark all code reachable from firstp as alive */
-static void
-mark(Reg *firstr)
-{
- Reg *r;
- Prog *p;
-
- for(r=firstr; r; r=r->link) {
- if(r->active)
- break;
- r->active = 1;
- p = r->prog;
- if(p->as != ACALL && p->to.type == D_BRANCH)
- mark(r->s2);
- if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
- break;
- }
-}
-
-/*
- * the code generator depends on being able to write out JMP
- * instructions that it can jump to now but fill in later.
- * the linker will resolve them nicely, but they make the code
- * longer and more difficult to follow during debugging.
- * remove them.
- */
-static void
-fixjmp(Reg *firstr)
-{
- int jmploop;
- Reg *r;
- Prog *p;
-
- if(debug['R'] && debug['v'])
- print("\nfixjmp\n");
-
- // pass 1: resolve jump to AJMP, mark all code as dead.
- jmploop = 0;
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(debug['R'] && debug['v'])
- print("%04d %P\n", (int)r->pc, p);
- if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
- r->s2 = chasejmp(r->s2, &jmploop);
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- if(debug['R'] && debug['v'])
- print("->%P\n", p);
- }
- r->active = 0;
- }
- if(debug['R'] && debug['v'])
- print("\n");
-
- // pass 2: mark all reachable code alive
- mark(firstr);
-
- // pass 3: delete dead code (mostly JMPs).
- for(r=firstr; r; r=r->link) {
- if(!r->active) {
- p = r->prog;
- if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) {
- // This is the final ARET, and the code so far doesn't have one.
- // Let it stay.
- } else {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // pass 4: elide JMP to next instruction.
- // only safe if there are no jumps to JMPs anymore.
- if(!jmploop) {
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // fix back pointers.
- for(r=firstr; r; r=r->link) {
- r->p2 = R;
- r->p2link = R;
- }
- for(r=firstr; r; r=r->link) {
- if(r->s2) {
- r->p2link = r->s2->p2;
- r->s2->p2 = r;
- }
- }
-
- if(debug['R'] && debug['v']) {
- print("\n");
- for(r=firstr; r; r=r->link)
- print("%04d %P\n", (int)r->pc, r->prog);
- print("\n");
- }
-}
-
diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c
deleted file mode 100644
index fceb332b2..000000000
--- a/src/cmd/6c/sgen.c
+++ /dev/null
@@ -1,483 +0,0 @@
-// Inferno utils/6c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.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"
-#include "../../runtime/funcdata.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
- vlong v;
-
- v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
- if((textflag & NOSPLIT) && stkoff >= 128)
- yyerror("stack frame too large for NOSPLIT function");
-
- gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
- return p;
-}
-
-void
-noretval(int n)
-{
-
- if(n & 1) {
- gins(ANOP, Z, Z);
- p->to.type = REGRET;
- }
- if(n & 2) {
- gins(ANOP, Z, Z);
- p->to.type = FREGRET;
- }
-}
-
-/* welcome to commute */
-static void
-commute(Node *n)
-{
- Node *l, *r;
-
- l = n->left;
- r = n->right;
- if(r->complex > l->complex) {
- n->left = r;
- n->right = l;
- }
-}
-
-void
-indexshift(Node *n)
-{
- int g;
-
- if(!typechlpv[n->type->etype])
- return;
- simplifyshift(n);
- if(n->op == OASHL && n->right->op == OCONST){
- g = vconst(n->right);
- if(g >= 0 && g <= 3)
- n->addable = 7;
- }
-}
-
-/*
- * calculate addressability as follows
- * NAME ==> 10/11 name+value(SB/SP)
- * REGISTER ==> 12 register
- * CONST ==> 20 $value
- * *(20) ==> 21 value
- * &(10) ==> 13 $name+value(SB)
- * &(11) ==> 1 $name+value(SP)
- * (13) + (20) ==> 13 fold constants
- * (1) + (20) ==> 1 fold constants
- * *(13) ==> 10 back to name
- * *(1) ==> 11 back to name
- *
- * (20) * (X) ==> 7 multiplier in indexing
- * (X,7) + (13,1) ==> 8 adder in indexing (addresses)
- * (8) ==> &9(OINDEX) index, almost addressable
- *
- * calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
- Node *l, *r;
- int g;
-
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- n->complex = 0;
- n->addable = 0;
- switch(n->op) {
- case OCONST:
- n->addable = 20;
- break;
-
- case ONAME:
- n->addable = 9;
- if(n->class == CPARAM || n->class == CAUTO)
- n->addable = 11;
- break;
-
- case OEXREG:
- n->addable = 0;
- break;
-
- case OREGISTER:
- n->addable = 12;
- break;
-
- case OINDREG:
- n->addable = 12;
- break;
-
- case OADDR:
- xcom(l);
- if(l->addable == 10)
- n->addable = 13;
- else
- if(l->addable == 11)
- n->addable = 1;
- break;
-
- case OADD:
- xcom(l);
- xcom(r);
- if(n->type->etype != TIND)
- break;
-
- switch(r->addable) {
- case 20:
- switch(l->addable) {
- case 1:
- case 13:
- commadd:
- l->type = n->type;
- *n = *l;
- l = new(0, Z, Z);
- *l = *(n->left);
- l->xoffset += r->vconst;
- n->left = l;
- r = n->right;
- goto brk;
- }
- break;
-
- case 1:
- case 13:
- case 10:
- case 11:
- /* l is the base, r is the index */
- if(l->addable != 20)
- n->addable = 8;
- break;
- }
- switch(l->addable) {
- case 20:
- switch(r->addable) {
- case 13:
- case 1:
- r = n->left;
- l = n->right;
- n->left = l;
- n->right = r;
- goto commadd;
- }
- break;
-
- case 13:
- case 1:
- case 10:
- case 11:
- /* r is the base, l is the index */
- if(r->addable != 20)
- n->addable = 8;
- break;
- }
- if(n->addable == 8 && !side(n) && !nacl) {
- indx(n);
- l = new1(OINDEX, idx.basetree, idx.regtree);
- l->scale = idx.scale;
- l->addable = 9;
- l->complex = l->right->complex;
- l->type = l->left->type;
- n->op = OADDR;
- n->left = l;
- n->right = Z;
- n->addable = 8;
- break;
- }
- break;
-
- case OINDEX:
- xcom(l);
- xcom(r);
- n->addable = 9;
- break;
-
- case OIND:
- xcom(l);
- if(l->op == OADDR) {
- l = l->left;
- l->type = n->type;
- *n = *l;
- return;
- }
- switch(l->addable) {
- case 20:
- n->addable = 21;
- break;
- case 1:
- n->addable = 11;
- break;
- case 13:
- n->addable = 10;
- break;
- }
- break;
-
- case OASHL:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- case OMUL:
- case OLMUL:
- xcom(l);
- xcom(r);
- g = vlog(l);
- if(g >= 0) {
- n->left = r;
- n->right = l;
- l = r;
- r = n->right;
- }
- g = vlog(r);
- if(g >= 0) {
- n->op = OASHL;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
- commute(n);
- break;
-
- case OASLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASLSHR;
- r->vconst = g;
- r->type = types[TINT];
- }
- break;
-
- case OLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OLSHR;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
- break;
-
- case OASLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASAND;
- r->vconst--;
- }
- break;
-
- case OLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OAND;
- r->vconst--;
- }
- break;
-
- case OASMUL:
- case OASLMUL:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASASHL;
- r->vconst = g;
- }
- break;
-
- case OLSHR:
- case OASHR:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- default:
- if(l != Z)
- xcom(l);
- if(r != Z)
- xcom(r);
- break;
- }
-brk:
- if(n->addable >= 10)
- return;
- if(l != Z)
- n->complex = l->complex;
- if(r != Z) {
- if(r->complex == n->complex)
- n->complex = r->complex+1;
- else
- if(r->complex > n->complex)
- n->complex = r->complex;
- }
- if(n->complex == 0)
- n->complex++;
-
- switch(n->op) {
-
- case OFUNC:
- n->complex = FNX;
- break;
-
- case OCAST:
- if(l->type->etype == TUVLONG && typefd[n->type->etype])
- n->complex += 2;
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 3;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 3;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 2;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 2;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OADD:
- case OXOR:
- case OAND:
- case OOR:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- }
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- /*
- * compare operators, make const on left
- */
- if(r->op == OCONST) {
- n->left = r;
- n->right = l;
- n->op = invrel[relindex(n->op)];
- }
- break;
- }
-}
-
-void
-indx(Node *n)
-{
- Node *l, *r;
-
- if(debug['x'])
- prtree(n, "indx");
-
- l = n->left;
- r = n->right;
- if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
- n->right = l;
- n->left = r;
- l = r;
- r = n->right;
- }
- if(l->addable != 7) {
- idx.regtree = l;
- idx.scale = 1;
- } else
- if(l->right->addable == 20) {
- idx.regtree = l->left;
- idx.scale = 1 << l->right->vconst;
- } else
- if(l->left->addable == 20) {
- idx.regtree = l->right;
- idx.scale = 1 << l->left->vconst;
- } else
- diag(n, "bad index");
-
- idx.basetree = r;
- if(debug['x']) {
- print("scale = %d\n", idx.scale);
- prtree(idx.regtree, "index");
- prtree(idx.basetree, "base");
- }
-}
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
deleted file mode 100644
index 6e918eb10..000000000
--- a/src/cmd/6c/swt.c
+++ /dev/null
@@ -1,353 +0,0 @@
-// Inferno utils/6c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.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
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
- Node nreg;
-
- regalloc(&nreg, n, Z);
- if(typev[n->type->etype])
- nreg.type = types[TVLONG];
- else
- nreg.type = types[TLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
- C1 *r;
- int i;
- Prog *sp;
-
- if(nc < 5) {
- for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8llux\n", q->val);
- gcmp(OEQ, n, q->val);
- patch(p, q->label);
- q++;
- }
- gbranch(OGOTO);
- patch(p, def);
- return;
- }
- i = nc / 2;
- r = q+i;
- if(debug['W'])
- print("case > %.8llux\n", r->val);
- gcmp(OGT, n, r->val);
- sp = p;
- gbranch(OGOTO);
- p->as = AJEQ;
- patch(p, r->label);
- swit2(q, i, def, n);
-
- if(debug['W'])
- print("case < %.8llux\n", r->val);
- patch(sp, pc);
- swit2(r+1, nc-i-1, def, n);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int sh;
- int32 v;
- Node *l;
-
- /*
- * n1 gets adjusted/masked value
- * n2 gets address of cell
- * n3 gets contents of cell
- */
- l = b->left;
- if(n2 != Z) {
- regalloc(n1, l, nn);
- reglcgen(n2, l, Z);
- regalloc(n3, l, Z);
- gmove(n2, n3);
- gmove(n3, n1);
- } else {
- regalloc(n1, l, nn);
- cgen(l, n1);
- }
- if(b->type->shift == 0 && typeu[b->type->etype]) {
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, tfield, nodconst(v), n1);
- } else {
- sh = 32 - b->type->shift - b->type->nbits;
- if(sh > 0)
- gopcode(OASHL, tfield, nodconst(sh), n1);
- sh += b->type->shift;
- if(sh > 0)
- if(typeu[b->type->etype])
- gopcode(OLSHR, tfield, nodconst(sh), n1);
- else
- gopcode(OASHR, tfield, nodconst(sh), n1);
- }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int32 v;
- Node nod;
- int sh;
-
- regalloc(&nod, b->left, Z);
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, types[TLONG], nodconst(v), n1);
- gmove(n1, &nod);
- if(nn != Z)
- gmove(n1, nn);
- sh = b->type->shift;
- if(sh > 0)
- gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
- v <<= sh;
- gopcode(OAND, types[TLONG], nodconst(~v), n3);
- gopcode(OOR, types[TLONG], n3, &nod);
- gmove(&nod, n2);
-
- regfree(&nod);
- regfree(n1);
- regfree(n2);
- regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
- int32 r;
-
- if(suppress)
- return nstring;
- r = nstring;
- while(n) {
- string[mnstring] = *s++;
- mnstring++;
- nstring++;
- if(mnstring >= NSNAME) {
- gpseudo(ADATA, symstring, nodconst(0L));
- p->from.offset += nstring - NSNAME;
- p->from.scale = NSNAME;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, string, NSNAME);
- mnstring = 0;
- }
- n--;
- }
- return r;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
- int32 e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0L));
- p->from.offset += o+e;
- p->from.scale = lw;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, a->cstring+e, lw);
- }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
- if(0 && a->op == OCONST && typev[a->type->etype]) {
- gpseudo(ADATA, s, lo64(a));
- p->from.offset += o;
- p->from.scale = 4;
- gpseudo(ADATA, s, hi64(a));
- p->from.offset += o + 4;
- p->from.scale = 4;
- return;
- }
- gpseudo(ADATA, s, a);
- p->from.offset += o;
- p->from.scale = w;
- switch(p->to.type) {
- default:
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
- case D_CONST:
- case D_FCONST:
- case D_ADDR:
- break;
- }
-}
-
-void
-outcode(void)
-{
- int f;
- Biobuf b;
-
- f = open(outfile, OWRITE);
- if(f < 0) {
- diag(Z, "cannot open %s", outfile);
- return;
- }
- Binit(&b, f, OWRITE);
-
- Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
- if(pragcgobuf.to > pragcgobuf.start) {
- Bprint(&b, "\n");
- Bprint(&b, "$$ // exports\n\n");
- Bprint(&b, "$$ // local types\n\n");
- Bprint(&b, "$$ // cgo\n");
- Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
- Bprint(&b, "\n$$\n\n");
- }
- Bprint(&b, "!\n");
-
- writeobj(ctxt, &b);
- Bterm(&b);
- close(f);
- lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
- int32 o;
- Type *v;
- int w, packw;
-
- o = i;
- w = 1;
- packw = 0;
- switch(op) {
- default:
- diag(Z, "unknown align opcode %d", op);
- break;
-
- case Asu2: /* padding at end of a struct */
- w = *maxalign;
- if(w < 1)
- w = 1;
- if(packflg)
- packw = packflg;
- break;
-
- case Ael1: /* initial align of struct element */
- for(v=t; v->etype==TARRAY; v=v->link)
- ;
- if(v->etype == TSTRUCT || v->etype == TUNION)
- w = v->align;
- else
- w = ewidth[v->etype];
- if(w < 1 || w > SZ_VLONG)
- fatal(Z, "align");
- if(packflg)
- packw = packflg;
- break;
-
- case Ael2: /* width of a struct element */
- o += t->width;
- break;
-
- case Aarg0: /* initial passbyptr argument in arg list */
- if(typesu[t->etype]) {
- o = align(o, types[TIND], Aarg1, nil);
- o = align(o, types[TIND], Aarg2, nil);
- }
- break;
-
- case Aarg1: /* initial align of parameter */
- if(ewidth[TIND] == 4) {
- if(typesu[t->etype]) {
- for(v = t->link; v != T; v = v->down)
- o = align(o, v, Aarg1, maxalign);
- goto out;
- }
- w = ewidth[t->etype];
- if(typev[t->etype] || t->etype == TDOUBLE)
- w = 8;
- else if(w <= 0 || w >= 4)
- w = 4;
- else
- w = 1;
- break;
- }
- w = ewidth[t->etype];
- if(w <= 0 || w >= SZ_VLONG) {
- w = SZ_VLONG;
- break;
- }
- w = 1; /* little endian no adjustment */
- break;
-
- case Aarg2: /* width of a parameter */
- o += t->width;
- if(ewidth[TIND] == 4) {
- o = align(o, t, Aarg1, maxalign);
- goto out;
- }
- w = t->width;
- if(w > SZ_VLONG)
- w = SZ_VLONG;
- break;
-
- case Aaut3: /* total align of automatic */
- o = align(o, t, Ael1, nil);
- o = align(o, t, Ael2, nil);
- break;
- }
- if(packw != 0 && xround(o, w) != xround(o, packw))
- diag(Z, "#pragma pack changes offset of %T", t);
- o = xround(o, w);
- if(maxalign && *maxalign < w)
- *maxalign = w;
-out:
- if(debug['A'])
- print("align %s %d %T = %d\n", bnames[op], i, t, o);
- return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
- v = xround(v, SZ_VLONG);
- if(v > max)
- return v;
- return max;
-}
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
deleted file mode 100644
index 3bdbf410e..000000000
--- a/src/cmd/6c/txt.c
+++ /dev/null
@@ -1,1674 +0,0 @@
-// Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.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"
-
-int thechar = '6';
-char *thestring = "amd64";
-
-LinkArch *thelinkarch = &linkamd64;
-
-void
-linkarchinit(void)
-{
- if(strcmp(getgoarch(), "amd64p32") == 0)
- thelinkarch = &linkamd64p32;
-}
-
-void
-ginit(void)
-{
- int i;
- Type *t;
-
- dodefine("_64BITREG");
- if(ewidth[TIND] == 8)
- dodefine("_64BIT");
- listinit();
- nstring = 0;
- mnstring = 0;
- nrathole = 0;
- pc = 0;
- breakpc = -1;
- continpc = -1;
- cases = C;
- lastp = P;
- tfield = types[TINT];
-
- typeword = typechlvp;
- typecmplx = typesu;
-
- /* TO DO */
- memmove(typechlpv, typechlp, sizeof(typechlpv));
- typechlpv[TVLONG] = 1;
- typechlpv[TUVLONG] = 1;
-
- zprog.link = P;
- zprog.as = AGOK;
- zprog.from.type = D_NONE;
- zprog.from.index = D_NONE;
- zprog.from.scale = 0;
- zprog.to = zprog.from;
-
- lregnode.op = OREGISTER;
- lregnode.class = CEXREG;
- lregnode.reg = REGTMP;
- lregnode.complex = 0;
- lregnode.addable = 11;
- lregnode.type = types[TLONG];
-
- qregnode = lregnode;
- qregnode.type = types[TVLONG];
-
- constnode.op = OCONST;
- constnode.class = CXXX;
- constnode.complex = 0;
- constnode.addable = 20;
- constnode.type = types[TLONG];
-
- vconstnode = constnode;
- vconstnode.type = types[TVLONG];
-
- fconstnode.op = OCONST;
- fconstnode.class = CXXX;
- fconstnode.complex = 0;
- fconstnode.addable = 20;
- fconstnode.type = types[TDOUBLE];
-
- nodsafe = new(ONAME, Z, Z);
- nodsafe->sym = slookup(".safe");
- nodsafe->type = types[TINT];
- nodsafe->etype = types[TINT]->etype;
- nodsafe->class = CAUTO;
- complex(nodsafe);
-
- t = typ(TARRAY, types[TCHAR]);
- symrathole = slookup(".rathole");
- symrathole->class = CGLOBL;
- symrathole->type = t;
-
- nodrat = new(ONAME, Z, Z);
- nodrat->sym = symrathole;
- nodrat->type = types[TIND];
- nodrat->etype = TVOID;
- nodrat->class = CGLOBL;
- complex(nodrat);
- nodrat->type = t;
-
- nodret = new(ONAME, Z, Z);
- nodret->sym = slookup(".ret");
- nodret->type = types[TIND];
- nodret->etype = TIND;
- nodret->class = CPARAM;
- nodret = new(OIND, nodret, Z);
- complex(nodret);
-
- if(0)
- com64init();
-
- for(i=0; i<nelem(reg); i++) {
- reg[i] = 1;
- if(i >= D_AX && i <= D_R15 && i != D_SP)
- reg[i] = 0;
- if(i >= D_X0 && i <= D_X7)
- reg[i] = 0;
- }
- if(nacl) {
- reg[D_BP] = 1;
- reg[D_R15] = 1;
- }
-}
-
-void
-gclean(void)
-{
- int i;
- Sym *s;
-
- reg[D_SP]--;
- if(nacl) {
- reg[D_BP]--;
- reg[D_R15]--;
- }
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i])
- diag(Z, "reg %R left allocated", i);
- for(i=D_X0; i<=D_X7; i++)
- if(reg[i])
- diag(Z, "reg %R left allocated", i);
- while(mnstring)
- outstring("", 1L);
- symstring->type->width = nstring;
- symrathole->type->width = nrathole;
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->link) {
- if(s->type == T)
- continue;
- if(s->type->width == 0)
- continue;
- if(s->class != CGLOBL && s->class != CSTATIC)
- continue;
- if(s->type == types[TENUM])
- continue;
- gpseudo(AGLOBL, s, nodconst(s->type->width));
- }
- nextpc();
- p->as = AEND;
- outcode();
-}
-
-void
-nextpc(void)
-{
- Plist *pl;
-
- p = alloc(sizeof(*p));
- *p = zprog;
- p->lineno = nearln;
- p->pc = pc;
- pc++;
- if(lastp == nil) {
- pl = linknewplist(ctxt);
- pl->firstpc = p;
- } else
- lastp->link = p;
- lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
- int32 regs;
- Node fnxargs[20], *fnxp;
-
- regs = cursafe;
-
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
-
- curarg = 0;
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
-
- cursafe = regs;
-}
-
-int
-nareg(void)
-{
- int i, n;
-
- n = 0;
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i] == 0)
- n++;
- return n;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
- Node nod;
-
- if(n == Z)
- return;
- if(n->op == OLIST) {
- garg1(n->left, tn1, tn2, f, fnxp);
- garg1(n->right, tn1, tn2, f, fnxp);
- return;
- }
- if(f == 0) {
- if(n->complex >= FNX) {
- regsalloc(*fnxp, n);
- nod = znode;
- nod.op = OAS;
- nod.left = *fnxp;
- nod.right = n;
- nod.type = n->type;
- cgen(&nod, Z);
- (*fnxp)++;
- }
- return;
- }
- if(typesu[n->type->etype]) {
- regaalloc(tn2, n);
- if(n->complex >= FNX) {
- sugen(*fnxp, tn2, n->type->width);
- (*fnxp)++;
- } else
- sugen(n, tn2, n->type->width);
- return;
- }
- if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {
- regaalloc1(tn1, n);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- return;
- }
- if(vconst(n) == 0) {
- regaalloc(tn2, n);
- gmove(n, tn2);
- return;
- }
- regalloc(tn1, n, Z);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- regaalloc(tn2, n);
- gmove(tn1, tn2);
- regfree(tn1);
-}
-
-Node*
-nodgconst(vlong v, Type *t)
-{
- if(!typev[t->etype])
- return nodconst((int32)v);
- vconstnode.vconst = v;
- return &vconstnode;
-}
-
-Node*
-nodconst(int32 v)
-{
- constnode.vconst = v;
- return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
- fconstnode.fconst = d;
- return &fconstnode;
-}
-
-int
-isreg(Node *n, int r)
-{
-
- if(n->op == OREGISTER)
- if(n->reg == r)
- return 1;
- return 0;
-}
-
-int
-nodreg(Node *n, Node *nn, int r)
-{
- int et;
-
- *n = qregnode;
- n->reg = r;
- if(nn != Z){
- et = nn->type->etype;
- if(!typefd[et] && nn->type->width <= SZ_LONG && 0)
- n->type = typeu[et]? types[TUINT]: types[TINT];
- else
- n->type = nn->type;
-//print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]);
- n->lineno = nn->lineno;
- }
- if(reg[r] == 0)
- return 0;
- if(nn != Z) {
- if(nn->op == OREGISTER)
- if(nn->reg == r)
- return 0;
- }
- return 1;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
- int r;
-
- if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
- return;
- }
-
- if(mode == 1) {
- // fetch returned value after call.
- // already called gargs, so curarg is set.
- curarg = (curarg+7) & ~7;
- regaalloc(n, nn);
- return;
- }
-
- if(mode == 2) {
- // store value to be returned.
- // must compute arg offset.
- if(t->etype != TFUNC)
- fatal(Z, "bad regret func %T", t);
- *n = *nn;
- n->op = ONAME;
- n->class = CPARAM;
- n->sym = slookup(".ret");
- n->complex = nodret->complex;
- n->addable = 20;
- n->xoffset = argsize(0);
- return;
- }
-
- fatal(Z, "bad regret");
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
- int i;
-
- switch(tn->type->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= D_AX && i <= D_R15)
- goto out;
- }
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of fixed registers");
- goto err;
-
- case TFLOAT:
- case TDOUBLE:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= D_X0 && i <= D_X7)
- goto out;
- }
- for(i=D_X0; i<=D_X7; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of float registers");
- goto out;
- }
- diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
- i = 0;
-out:
- if(i)
- reg[i]++;
- nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
- Node nod;
-
- nod = *tn;
- nod.type = types[TIND];
- regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
- int i;
-
- i = 0;
- if(n->op != OREGISTER && n->op != OINDREG)
- goto err;
- i = n->reg;
- if(i < 0 || i >= nelem(reg))
- goto err;
- if(reg[i] <= 0)
- goto err;
- reg[i]--;
- return;
-err:
- diag(n, "error in regfree: %R", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
- cursafe = align(cursafe, nn->type, Aaut3, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
- *n = *nodsafe;
- n->xoffset = -(stkoff + cursafe);
- n->type = nn->type;
- n->etype = nn->type->etype;
- n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
- if(REGARG < 0) {
- fatal(n, "regaalloc1 and REGARG<0");
- return;
- }
- nodreg(n, nn, REGARG);
- reg[(uchar)REGARG]++;
- curarg = align(curarg, nn->type, Aarg1, nil);
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
- curarg = align(curarg, nn->type, Aarg1, nil);
- *n = *nn;
- n->op = OINDREG;
- n->reg = REGSP;
- n->xoffset = curarg;
- n->complex = 0;
- n->addable = 20;
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
- if(n->op != OREGISTER) {
- diag(n, "regind not OREGISTER");
- return;
- }
- n->op = OINDREG;
- n->type = nn->type;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
- int32 v;
-
- a->type = D_NONE;
- if(n == Z)
- return;
- switch(n->op) {
- default:
- bad:
- diag(n, "bad in naddr: %O %D", n->op, a);
- break;
-
- case OREGISTER:
- a->type = n->reg;
- a->sym = nil;
- break;
-
- case OEXREG:
- a->type = D_INDIR + D_TLS;
- a->offset = n->reg - 1;
- break;
-
- case OIND:
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_R15)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- break;
-
- case OINDEX:
- a->type = idx.ptr;
- if(n->left->op == OADDR || n->left->op == OCONST)
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_R15)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- a->index = idx.reg;
- a->scale = n->scale;
- a->offset += n->xoffset;
- break;
-
- case OINDREG:
- a->type = n->reg+D_INDIR;
- a->sym = nil;
- a->offset = n->xoffset;
- break;
-
- case ONAME:
- a->etype = n->etype;
- a->type = D_STATIC;
- a->sym = linksym(n->sym);
- a->offset = n->xoffset;
- if(n->class == CSTATIC)
- break;
- if(n->class == CEXTERN || n->class == CGLOBL) {
- a->type = D_EXTERN;
- break;
- }
- if(n->class == CAUTO) {
- a->type = D_AUTO;
- break;
- }
- if(n->class == CPARAM) {
- a->type = D_PARAM;
- break;
- }
- goto bad;
-
- case OCONST:
- if(typefd[n->type->etype]) {
- a->type = D_FCONST;
- a->u.dval = n->fconst;
- break;
- }
- a->sym = nil;
- a->type = D_CONST;
- if(typev[n->type->etype] || (n->type->etype == TIND && ewidth[TIND] == 8))
- a->offset = n->vconst;
- else
- a->offset = convvtox(n->vconst, typeu[n->type->etype]? TULONG: TLONG);
- break;
-
- case OADDR:
- naddr(n->left, a);
- if(a->type >= D_INDIR) {
- a->type -= D_INDIR;
- break;
- }
- if(a->type == D_EXTERN || a->type == D_STATIC ||
- a->type == D_AUTO || a->type == D_PARAM)
- if(a->index == D_NONE) {
- a->index = a->type;
- a->type = D_ADDR;
- break;
- }
- goto bad;
-
- case OADD:
- if(n->right->op == OCONST) {
- v = n->right->vconst;
- naddr(n->left, a);
- } else
- if(n->left->op == OCONST) {
- v = n->left->vconst;
- naddr(n->right, a);
- } else
- goto bad;
- a->offset += v;
- break;
-
- }
-}
-
-void
-gcmp(int op, Node *n, vlong val)
-{
- Node *cn, nod;
-
- cn = nodgconst(val, n->type);
- if(!immconst(cn)){
- regalloc(&nod, n, Z);
- gmove(cn, &nod);
- gopcode(op, n->type, n, &nod);
- regfree(&nod);
- }else
- gopcode(op, n->type, n, cn);
-}
-
-#define CASE(a,b) ((a<<8)|(b<<0))
-
-void
-gmove(Node *f, Node *t)
-{
- int ft, tt, t64, a;
- Node nod, nod1, nod2, nod3;
- Prog *p1, *p2;
-
- ft = f->type->etype;
- tt = t->type->etype;
- if(ewidth[TIND] == 4) {
- if(ft == TIND)
- ft = TUINT;
- if(tt == TIND)
- tt = TUINT;
- }
- t64 = tt == TVLONG || tt == TUVLONG || tt == TIND;
- if(debug['M'])
- print("gop: %O %O[%s],%O[%s]\n", OAS,
- f->op, tnames[ft], t->op, tnames[tt]);
- if(typefd[ft] && f->op == OCONST) {
- /* TO DO: pick up special constants, possibly preloaded */
- if(f->fconst == 0.0){
- regalloc(&nod, t, t);
- gins(AXORPD, &nod, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- }
-/*
- * load
- */
- if(ft == TVLONG || ft == TUVLONG)
- if(f->op == OCONST)
- if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
- if(t->op != OREGISTER) {
- regalloc(&nod, f, Z);
- gmove(f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
- if(f->op == ONAME || f->op == OINDREG ||
- f->op == OIND || f->op == OINDEX)
- switch(ft) {
- case TCHAR:
- a = AMOVBLSX;
- if(t64)
- a = AMOVBQSX;
- goto ld;
- case TUCHAR:
- a = AMOVBLZX;
- if(t64)
- a = AMOVBQZX;
- goto ld;
- case TSHORT:
- a = AMOVWLSX;
- if(t64)
- a = AMOVWQSX;
- goto ld;
- case TUSHORT:
- a = AMOVWLZX;
- if(t64)
- a = AMOVWQZX;
- goto ld;
- case TINT:
- case TLONG:
- if(typefd[tt]) {
- regalloc(&nod, t, t);
- if(tt == TDOUBLE)
- a = ACVTSL2SD;
- else
- a = ACVTSL2SS;
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- a = AMOVL;
- if(t64)
- a = AMOVLQSX;
- goto ld;
- case TUINT:
- case TULONG:
- a = AMOVL;
- if(t64)
- a = AMOVLQZX; /* could probably use plain MOVL */
- goto ld;
- case TVLONG:
- if(typefd[tt]) {
- regalloc(&nod, t, t);
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- else
- a = ACVTSQ2SS;
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- case TUVLONG:
- a = AMOVQ;
- goto ld;
- case TIND:
- a = AMOVQ;
- if(ewidth[TIND] == 4)
- a = AMOVL;
-
- ld:
- regalloc(&nod, f, t);
- nod.type = t64? types[TVLONG]: types[TINT];
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- a = AMOVSS;
- goto fld;
- case TDOUBLE:
- a = AMOVSD;
- fld:
- regalloc(&nod, f, t);
- if(tt != TDOUBLE && tt != TFLOAT){ /* TO DO: why is this here */
- prtree(f, "odd tree");
- nod.type = t64? types[TVLONG]: types[TINT];
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
-/*
- * store
- */
- if(t->op == ONAME || t->op == OINDREG ||
- t->op == OIND || t->op == OINDEX)
- switch(tt) {
- case TCHAR:
- case TUCHAR:
- a = AMOVB; goto st;
- case TSHORT:
- case TUSHORT:
- a = AMOVW; goto st;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- a = AMOVL; goto st;
- case TVLONG:
- case TUVLONG:
- case TIND:
- a = AMOVQ; goto st;
-
- st:
- if(f->op == OCONST) {
- gins(a, f, t);
- return;
- }
- fst:
- regalloc(&nod, t, f);
- gmove(f, &nod);
- gins(a, &nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- a = AMOVSS;
- goto fst;
- case TDOUBLE:
- a = AMOVSD;
- goto fst;
- }
-
-/*
- * convert
- */
- switch(CASE(ft,tt)) {
- default:
-/*
- * integer to integer
- ********
- a = AGOK; break;
-
- case CASE( TCHAR, TCHAR):
- case CASE( TUCHAR, TCHAR):
- case CASE( TSHORT, TCHAR):
- case CASE( TUSHORT,TCHAR):
- case CASE( TINT, TCHAR):
- case CASE( TUINT, TCHAR):
- case CASE( TLONG, TCHAR):
- case CASE( TULONG, TCHAR):
-
- case CASE( TCHAR, TUCHAR):
- case CASE( TUCHAR, TUCHAR):
- case CASE( TSHORT, TUCHAR):
- case CASE( TUSHORT,TUCHAR):
- case CASE( TINT, TUCHAR):
- case CASE( TUINT, TUCHAR):
- case CASE( TLONG, TUCHAR):
- case CASE( TULONG, TUCHAR):
-
- case CASE( TSHORT, TSHORT):
- case CASE( TUSHORT,TSHORT):
- case CASE( TINT, TSHORT):
- case CASE( TUINT, TSHORT):
- case CASE( TLONG, TSHORT):
- case CASE( TULONG, TSHORT):
-
- case CASE( TSHORT, TUSHORT):
- case CASE( TUSHORT,TUSHORT):
- case CASE( TINT, TUSHORT):
- case CASE( TUINT, TUSHORT):
- case CASE( TLONG, TUSHORT):
- case CASE( TULONG, TUSHORT):
-
- case CASE( TINT, TINT):
- case CASE( TUINT, TINT):
- case CASE( TLONG, TINT):
- case CASE( TULONG, TINT):
-
- case CASE( TINT, TUINT):
- case CASE( TUINT, TUINT):
- case CASE( TLONG, TUINT):
- case CASE( TULONG, TUINT):
- *****/
- a = AMOVL;
- break;
-
- case CASE( TINT, TIND):
- case CASE( TINT, TVLONG):
- case CASE( TINT, TUVLONG):
- case CASE( TLONG, TIND):
- case CASE( TLONG, TVLONG):
- case CASE( TLONG, TUVLONG):
- a = AMOVLQSX;
- if(f->op == OCONST) {
- f->vconst &= (uvlong)0xffffffffU;
- if(f->vconst & 0x80000000)
- f->vconst |= (vlong)0xffffffff << 32;
- a = AMOVQ;
- }
- break;
-
- case CASE( TUINT, TIND):
- case CASE( TUINT, TVLONG):
- case CASE( TUINT, TUVLONG):
- case CASE( TULONG, TVLONG):
- case CASE( TULONG, TUVLONG):
- case CASE( TULONG, TIND):
- a = AMOVLQZX;
- if(f->op == OCONST) {
- f->vconst &= (uvlong)0xffffffffU;
- a = AMOVQ;
- }
- break;
-
- case CASE( TIND, TCHAR):
- case CASE( TIND, TUCHAR):
- case CASE( TIND, TSHORT):
- case CASE( TIND, TUSHORT):
- case CASE( TIND, TINT):
- case CASE( TIND, TUINT):
- case CASE( TIND, TLONG):
- case CASE( TIND, TULONG):
- case CASE( TVLONG, TCHAR):
- case CASE( TVLONG, TUCHAR):
- case CASE( TVLONG, TSHORT):
- case CASE( TVLONG, TUSHORT):
- case CASE( TVLONG, TINT):
- case CASE( TVLONG, TUINT):
- case CASE( TVLONG, TLONG):
- case CASE( TVLONG, TULONG):
- case CASE( TUVLONG, TCHAR):
- case CASE( TUVLONG, TUCHAR):
- case CASE( TUVLONG, TSHORT):
- case CASE( TUVLONG, TUSHORT):
- case CASE( TUVLONG, TINT):
- case CASE( TUVLONG, TUINT):
- case CASE( TUVLONG, TLONG):
- case CASE( TUVLONG, TULONG):
- a = AMOVQL;
- if(f->op == OCONST) {
- f->vconst &= (int)0xffffffffU;
- a = AMOVL;
- }
- break;
-
- case CASE( TIND, TIND):
- case CASE( TIND, TVLONG):
- case CASE( TIND, TUVLONG):
- case CASE( TVLONG, TIND):
- case CASE( TVLONG, TVLONG):
- case CASE( TVLONG, TUVLONG):
- case CASE( TUVLONG, TIND):
- case CASE( TUVLONG, TVLONG):
- case CASE( TUVLONG, TUVLONG):
- a = AMOVQ;
- break;
-
- case CASE( TSHORT, TINT):
- case CASE( TSHORT, TUINT):
- case CASE( TSHORT, TLONG):
- case CASE( TSHORT, TULONG):
- a = AMOVWLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- if(f->vconst & 0x8000)
- f->vconst |= 0xffff0000;
- a = AMOVL;
- }
- break;
-
- case CASE( TSHORT, TVLONG):
- case CASE( TSHORT, TUVLONG):
- case CASE( TSHORT, TIND):
- a = AMOVWQSX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- if(f->vconst & 0x8000){
- f->vconst |= 0xffff0000;
- f->vconst |= (vlong)~0 << 32;
- }
- a = AMOVL;
- }
- break;
-
- case CASE( TUSHORT,TINT):
- case CASE( TUSHORT,TUINT):
- case CASE( TUSHORT,TLONG):
- case CASE( TUSHORT,TULONG):
- a = AMOVWLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- a = AMOVL;
- }
- break;
-
- case CASE( TUSHORT,TVLONG):
- case CASE( TUSHORT,TUVLONG):
- case CASE( TUSHORT,TIND):
- a = AMOVWQZX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- a = AMOVL; /* MOVL also zero-extends to 64 bits */
- }
- break;
-
- case CASE( TCHAR, TSHORT):
- case CASE( TCHAR, TUSHORT):
- case CASE( TCHAR, TINT):
- case CASE( TCHAR, TUINT):
- case CASE( TCHAR, TLONG):
- case CASE( TCHAR, TULONG):
- a = AMOVBLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- if(f->vconst & 0x80)
- f->vconst |= 0xffffff00;
- a = AMOVL;
- }
- break;
-
- case CASE( TCHAR, TVLONG):
- case CASE( TCHAR, TUVLONG):
- case CASE( TCHAR, TIND):
- a = AMOVBQSX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- if(f->vconst & 0x80){
- f->vconst |= 0xffffff00;
- f->vconst |= (vlong)~0 << 32;
- }
- a = AMOVQ;
- }
- break;
-
- case CASE( TUCHAR, TSHORT):
- case CASE( TUCHAR, TUSHORT):
- case CASE( TUCHAR, TINT):
- case CASE( TUCHAR, TUINT):
- case CASE( TUCHAR, TLONG):
- case CASE( TUCHAR, TULONG):
- a = AMOVBLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- a = AMOVL;
- }
- break;
-
- case CASE( TUCHAR, TVLONG):
- case CASE( TUCHAR, TUVLONG):
- case CASE( TUCHAR, TIND):
- a = AMOVBQZX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- a = AMOVL; /* zero-extends to 64-bits */
- }
- break;
-
-/*
- * float to fix
- */
- case CASE( TFLOAT, TCHAR):
- case CASE( TFLOAT, TUCHAR):
- case CASE( TFLOAT, TSHORT):
- case CASE( TFLOAT, TUSHORT):
- case CASE( TFLOAT, TINT):
- case CASE( TFLOAT, TUINT):
- case CASE( TFLOAT, TLONG):
- case CASE( TFLOAT, TULONG):
- case CASE( TFLOAT, TVLONG):
- case CASE( TFLOAT, TUVLONG):
- case CASE( TFLOAT, TIND):
-
- case CASE( TDOUBLE,TCHAR):
- case CASE( TDOUBLE,TUCHAR):
- case CASE( TDOUBLE,TSHORT):
- case CASE( TDOUBLE,TUSHORT):
- case CASE( TDOUBLE,TINT):
- case CASE( TDOUBLE,TUINT):
- case CASE( TDOUBLE,TLONG):
- case CASE( TDOUBLE,TULONG):
- case CASE( TDOUBLE,TVLONG):
- case CASE( TDOUBLE,TUVLONG):
- case CASE( TDOUBLE,TIND):
- regalloc(&nod, t, Z);
- if(ewidth[tt] == SZ_VLONG || typeu[tt] && ewidth[tt] == SZ_INT){
- if(ft == TFLOAT)
- a = ACVTTSS2SQ;
- else
- a = ACVTTSD2SQ;
- }else{
- if(ft == TFLOAT)
- a = ACVTTSS2SL;
- else
- a = ACVTTSD2SL;
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
-/*
- * uvlong to float
- */
- case CASE( TUVLONG, TDOUBLE):
- case CASE( TUVLONG, TFLOAT):
- a = ACVTSQ2SS;
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- regalloc(&nod, f, f);
- gmove(f, &nod);
- regalloc(&nod1, t, t);
- gins(ACMPQ, &nod, nodconst(0));
- gins(AJLT, Z, Z);
- p1 = p;
- gins(a, &nod, &nod1);
- gins(AJMP, Z, Z);
- p2 = p;
- patch(p1, pc);
- regalloc(&nod2, f, Z);
- regalloc(&nod3, f, Z);
- gmove(&nod, &nod2);
- gins(ASHRQ, nodconst(1), &nod2);
- gmove(&nod, &nod3);
- gins(AANDL, nodconst(1), &nod3);
- gins(AORQ, &nod3, &nod2);
- gins(a, &nod2, &nod1);
- gins(tt == TDOUBLE? AADDSD: AADDSS, &nod1, &nod1);
- regfree(&nod2);
- regfree(&nod3);
- patch(p2, pc);
- regfree(&nod);
- regfree(&nod1);
- return;
-
- case CASE( TULONG, TDOUBLE):
- case CASE( TUINT, TDOUBLE):
- case CASE( TULONG, TFLOAT):
- case CASE( TUINT, TFLOAT):
- a = ACVTSQ2SS;
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- regalloc(&nod, f, f);
- gins(AMOVLQZX, f, &nod);
- regalloc(&nod1, t, t);
- gins(a, &nod, &nod1);
- gmove(&nod1, t);
- regfree(&nod);
- regfree(&nod1);
- return;
-
-/*
- * fix to float
- */
- case CASE( TCHAR, TFLOAT):
- case CASE( TUCHAR, TFLOAT):
- case CASE( TSHORT, TFLOAT):
- case CASE( TUSHORT,TFLOAT):
- case CASE( TINT, TFLOAT):
- case CASE( TLONG, TFLOAT):
- case CASE( TVLONG, TFLOAT):
- case CASE( TIND, TFLOAT):
-
- case CASE( TCHAR, TDOUBLE):
- case CASE( TUCHAR, TDOUBLE):
- case CASE( TSHORT, TDOUBLE):
- case CASE( TUSHORT,TDOUBLE):
- case CASE( TINT, TDOUBLE):
- case CASE( TLONG, TDOUBLE):
- case CASE( TVLONG, TDOUBLE):
- case CASE( TIND, TDOUBLE):
- regalloc(&nod, t, t);
- if(ewidth[ft] == SZ_VLONG){
- if(tt == TFLOAT)
- a = ACVTSQ2SS;
- else
- a = ACVTSQ2SD;
- }else{
- if(tt == TFLOAT)
- a = ACVTSL2SS;
- else
- a = ACVTSL2SD;
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
-/*
- * float to float
- */
- case CASE( TFLOAT, TFLOAT):
- a = AMOVSS;
- break;
- case CASE( TDOUBLE,TFLOAT):
- a = ACVTSD2SS;
- break;
- case CASE( TFLOAT, TDOUBLE):
- a = ACVTSS2SD;
- break;
- case CASE( TDOUBLE,TDOUBLE):
- a = AMOVSD;
- break;
- }
- if(a == AMOVQ || a == AMOVSD || a == AMOVSS || a == AMOVL && ewidth[ft] == ewidth[tt]) /* TO DO: check AMOVL */
- if(samaddr(f, t))
- return;
- gins(a, f, t);
-}
-
-void
-doindex(Node *n)
-{
- Node nod, nod1;
- int32 v;
-
-if(debug['Y'])
-prtree(n, "index");
-
-if(n->left->complex >= FNX)
-print("botch in doindex\n");
-
- regalloc(&nod, &qregnode, Z);
- v = constnode.vconst;
- cgen(n->right, &nod);
- idx.ptr = D_NONE;
- if(n->left->op == OCONST)
- idx.ptr = D_CONST;
- else if(n->left->op == OREGISTER)
- idx.ptr = n->left->reg;
- else if(n->left->op != OADDR) {
- reg[D_BP]++; // can't be used as a base
- regalloc(&nod1, &qregnode, Z);
- cgen(n->left, &nod1);
- idx.ptr = nod1.reg;
- regfree(&nod1);
- reg[D_BP]--;
- }
- idx.reg = nod.reg;
- regfree(&nod);
- constnode.vconst = v;
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
- if(f != Z && f->op == OINDEX)
- doindex(f);
- if(t != Z && t->op == OINDEX)
- doindex(t);
- nextpc();
- p->as = a;
- if(f != Z)
- naddr(f, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-void
-gopcode(int o, Type *ty, Node *f, Node *t)
-{
- int a, et;
-
- et = TLONG;
- if(ty != T)
- et = ty->etype;
- if(et == TIND && ewidth[TIND] == 4)
- et = TUINT;
- if(debug['M']) {
- if(f != Z && f->type != T)
- print("gop: %O %O[%s],", o, f->op, tnames[et]);
- else
- print("gop: %O Z,", o);
- if(t != Z && t->type != T)
- print("%O[%s]\n", t->op, tnames[t->type->etype]);
- else
- print("Z\n");
- }
- a = AGOK;
- switch(o) {
- case OCOM:
- a = ANOTL;
- if(et == TCHAR || et == TUCHAR)
- a = ANOTB;
- if(et == TSHORT || et == TUSHORT)
- a = ANOTW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ANOTQ;
- break;
-
- case ONEG:
- a = ANEGL;
- if(et == TCHAR || et == TUCHAR)
- a = ANEGB;
- if(et == TSHORT || et == TUSHORT)
- a = ANEGW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ANEGQ;
- break;
-
- case OADDR:
- a = ALEAQ;
- break;
-
- case OASADD:
- case OADD:
- a = AADDL;
- if(et == TCHAR || et == TUCHAR)
- a = AADDB;
- if(et == TSHORT || et == TUSHORT)
- a = AADDW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AADDQ;
- if(et == TFLOAT)
- a = AADDSS;
- if(et == TDOUBLE)
- a = AADDSD;
- break;
-
- case OASSUB:
- case OSUB:
- a = ASUBL;
- if(et == TCHAR || et == TUCHAR)
- a = ASUBB;
- if(et == TSHORT || et == TUSHORT)
- a = ASUBW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASUBQ;
- if(et == TFLOAT)
- a = ASUBSS;
- if(et == TDOUBLE)
- a = ASUBSD;
- break;
-
- case OASOR:
- case OOR:
- a = AORL;
- if(et == TCHAR || et == TUCHAR)
- a = AORB;
- if(et == TSHORT || et == TUSHORT)
- a = AORW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AORQ;
- break;
-
- case OASAND:
- case OAND:
- a = AANDL;
- if(et == TCHAR || et == TUCHAR)
- a = AANDB;
- if(et == TSHORT || et == TUSHORT)
- a = AANDW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AANDQ;
- break;
-
- case OASXOR:
- case OXOR:
- a = AXORL;
- if(et == TCHAR || et == TUCHAR)
- a = AXORB;
- if(et == TSHORT || et == TUSHORT)
- a = AXORW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AXORQ;
- break;
-
- case OASLSHR:
- case OLSHR:
- a = ASHRL;
- if(et == TCHAR || et == TUCHAR)
- a = ASHRB;
- if(et == TSHORT || et == TUSHORT)
- a = ASHRW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASHRQ;
- break;
-
- case OASASHR:
- case OASHR:
- a = ASARL;
- if(et == TCHAR || et == TUCHAR)
- a = ASARB;
- if(et == TSHORT || et == TUSHORT)
- a = ASARW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASARQ;
- break;
-
- case OASASHL:
- case OASHL:
- a = ASALL;
- if(et == TCHAR || et == TUCHAR)
- a = ASALB;
- if(et == TSHORT || et == TUSHORT)
- a = ASALW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASALQ;
- break;
-
- case OROTL:
- a = AROLL;
- if(et == TCHAR || et == TUCHAR)
- a = AROLB;
- if(et == TSHORT || et == TUSHORT)
- a = AROLW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AROLQ;
- break;
-
- case OFUNC:
- a = ACALL;
- break;
-
- case OASMUL:
- case OMUL:
- if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
- t = Z;
- a = AIMULL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AIMULQ;
- if(et == TFLOAT)
- a = AMULSS;
- if(et == TDOUBLE)
- a = AMULSD;
- break;
-
- case OASMOD:
- case OMOD:
- case OASDIV:
- case ODIV:
- a = AIDIVL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AIDIVQ;
- if(et == TFLOAT)
- a = ADIVSS;
- if(et == TDOUBLE)
- a = ADIVSD;
- break;
-
- case OASLMUL:
- case OLMUL:
- a = AMULL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AMULQ;
- break;
-
- case OASLMOD:
- case OLMOD:
- case OASLDIV:
- case OLDIV:
- a = ADIVL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ADIVQ;
- break;
-
- case OEQ:
- case ONE:
- case OLT:
- case OLE:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHS:
- case OHI:
- a = ACMPL;
- if(et == TCHAR || et == TUCHAR)
- a = ACMPB;
- if(et == TSHORT || et == TUSHORT)
- a = ACMPW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ACMPQ;
- if(et == TFLOAT)
- a = AUCOMISS;
- if(et == TDOUBLE)
- a = AUCOMISD;
- gins(a, f, t);
- switch(o) {
- case OEQ: a = AJEQ; break;
- case ONE: a = AJNE; break;
- case OLT: a = AJLT; break;
- case OLE: a = AJLE; break;
- case OGE: a = AJGE; break;
- case OGT: a = AJGT; break;
- case OLO: a = AJCS; break;
- case OLS: a = AJLS; break;
- case OHS: a = AJCC; break;
- case OHI: a = AJHI; break;
- }
- gins(a, Z, Z);
- return;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- gins(a, f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
- return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
-}
-
-void
-gbranch(int o)
-{
- int a;
-
- a = AGOK;
- switch(o) {
- case ORETURN:
- a = ARET;
- break;
- case OGOTO:
- a = AJMP;
- break;
- }
- nextpc();
- if(a == AGOK) {
- diag(Z, "bad in gbranch %O", o);
- nextpc();
- }
- p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
- op->to.offset = pc;
- op->to.type = D_BRANCH;
- op->to.u.branch = nil;
- op->pcond = nil;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
- nextpc();
- p->as = a;
- p->from.type = D_EXTERN;
- p->from.sym = linksym(s);
-
- switch(a) {
- case ATEXT:
- p->from.scale = textflag;
- textflag = 0;
- break;
- case AGLOBL:
- p->from.scale = s->dataflag;
- break;
- }
-
- if(s->class == CSTATIC)
- p->from.type = D_STATIC;
- naddr(n, &p->to);
- if(a == ADATA || a == AGLOBL)
- pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
- Node n1;
-
- n1 = *nodconst(index);
- gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
- Node n1;
-
- regalloc(&n1, n, Z);
- gmove(n, &n1);
- n1.op = OINDREG;
- gins(APREFETCHNTA, &n1, Z);
- regfree(&n1);
-}
-
-int
-sconst(Node *n)
-{
- int32 v;
-
- if(n->op == OCONST && !typefd[n->type->etype]) {
- v = n->vconst;
- if(v >= -32766L && v < 32766L)
- return 1;
- }
- return 0;
-}
-
-int32
-exreg(Type *t)
-{
- int32 o;
-
- if(typechlpv[t->etype]) {
- if(exregoffset >= 64)
- return 0;
- o = exregoffset;
- exregoffset += ewidth[TIND];
- return o+1; // +1 to avoid 0 == failure; naddr's case OEXREG will subtract 1.
- }
- return 0;
-}
-
-schar ewidth[NTYPE] =
-{
- -1, /*[TXXX]*/
- SZ_CHAR, /*[TCHAR]*/
- SZ_CHAR, /*[TUCHAR]*/
- SZ_SHORT, /*[TSHORT]*/
- SZ_SHORT, /*[TUSHORT]*/
- SZ_INT, /*[TINT]*/
- SZ_INT, /*[TUINT]*/
- SZ_LONG, /*[TLONG]*/
- SZ_LONG, /*[TULONG]*/
- SZ_VLONG, /*[TVLONG]*/
- SZ_VLONG, /*[TUVLONG]*/
- SZ_FLOAT, /*[TFLOAT]*/
- SZ_DOUBLE, /*[TDOUBLE]*/
- SZ_IND, /*[TIND]*/
- 0, /*[TFUNC]*/
- -1, /*[TARRAY]*/
- 0, /*[TVOID]*/
- -1, /*[TSTRUCT]*/
- -1, /*[TUNION]*/
- SZ_INT, /*[TENUM]*/
-};
-int32 ncast[NTYPE] =
-{
- 0, /*[TXXX]*/
- BCHAR|BUCHAR, /*[TCHAR]*/
- BCHAR|BUCHAR, /*[TUCHAR]*/
- BSHORT|BUSHORT, /*[TSHORT]*/
- BSHORT|BUSHORT, /*[TUSHORT]*/
- BINT|BUINT|BLONG|BULONG, /*[TINT]*/
- BINT|BUINT|BLONG|BULONG, /*[TUINT]*/
- BINT|BUINT|BLONG|BULONG, /*[TLONG]*/
- BINT|BUINT|BLONG|BULONG, /*[TULONG]*/
- BVLONG|BUVLONG|BIND, /*[TVLONG]*/
- BVLONG|BUVLONG|BIND, /*[TUVLONG]*/
- BFLOAT, /*[TFLOAT]*/
- BDOUBLE, /*[TDOUBLE]*/
- BVLONG|BUVLONG|BIND, /*[TIND]*/
- 0, /*[TFUNC]*/
- 0, /*[TARRAY]*/
- 0, /*[TVOID]*/
- BSTRUCT, /*[TSTRUCT]*/
- BUNION, /*[TUNION]*/
- 0, /*[TENUM]*/
-};