commit 5403b6a8b32780b34bf2abade344b91f995f5b5d
parent 41d8bab34e6ac22f9659b623328c6d4dd4e7b9a4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 23 Oct 2024 16:16:02 +0200
build/cc2: Flat dir tree
This is a previous step to move forward a recursive Makefile.
Diffstat:
48 files changed, 2780 insertions(+), 2782 deletions(-)
diff --git a/src/cmd/scc-cc/cc2/Makefile b/src/cmd/scc-cc/cc2/Makefile
@@ -3,8 +3,6 @@
PROJECTDIR = ../../../..
include $(PROJECTDIR)/scripts/rules.mk
-MORE_CPPFLAGS = -I$(INCDIR)/$(STD) -I$(CMDDIR) -I.
-
OBJS =\
main.o\
parser.o\
@@ -33,9 +31,9 @@ error.h: cc2.h
clean:
rm -f target/*/*.o error.h
-include target/amd64-sysv/target.mk
-include target/i386-sysv/target.mk
-include target/qbe_amd64-sysv/target.mk
-include target/qbe_arm64-sysv/target.mk
-include target/z80-scc/target.mk
+include amd64-sysv/target.mk
+include i386-sysv/target.mk
+include qbe_amd64-sysv/target.mk
+include qbe_arm64-sysv/target.mk
+include z80-scc/target.mk
include deps.mk
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/arch.h b/src/cmd/scc-cc/cc2/amd64-sysv/arch.h
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c b/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c
@@ -0,0 +1,13 @@
+#include "arch.h"
+#include <scc/scc.h>
+#include "../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/code.c b/src/cmd/scc-cc/cc2/amd64-sysv/code.c
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\t.text\n",
+ [DATASEG] = "\t.data\n",
+ [BSSSEG] = "\t.bss\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".L%d", sym->numid);
+
+ return name;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ pprint(np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ if (tp->flags & STRF) {
+ s = "\t.ascii\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\t.byte\t";
+ break;
+ case 2:
+ s = "\t.short\t";
+ break;
+ case 4:
+ s = "\t.long\t";
+ break;
+ case 8:
+ s = "\t.quad\t";
+ break;
+ default:
+ s = "\t.space\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+ Type *tp = &sym->type;
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\t.extern\t%s\n", name);
+ case SLOCAL:
+ return;
+ case SGLOB:
+ printf("\t.global\t%s\n", name);
+ if (seg == BSSSEG)
+ printf("\t.comm\t%s,%lu\n", name, tp->size);
+ break;
+ }
+ if (sym->type.align != 1)
+ printf("\t.align\t%lu\n", sym->type.align );
+ printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+deftype(Type *tp)
+{
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/optm.c b/src/cmd/scc-cc/cc2/amd64-sysv/optm.c
@@ -0,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/amd64-sysv/target.mk
@@ -0,0 +1,9 @@
+OBJ-amd64-sysv = $(OBJS) \
+ amd64-sysv/cgen.o \
+ amd64-sysv/optm.o \
+ amd64-sysv/code.o \
+ amd64-sysv/types.o
+
+cc2-amd64-sysv: $(LIBSCC) $(OBJ-amd64-sysv)
+ $(CC) $(PROJ_LDFLAGS) $(OBJ-amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@
+ cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/types.c b/src/cmd/scc-cc/cc2/amd64-sysv/types.c
@@ -0,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 4
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 8,
+ .align = 8
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 16,
+ .align = 16
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+Type arg_type = {
+ .flags = ARRF,
+ .size = 24,
+ .align = 8
+};
diff --git a/src/cmd/scc-cc/cc2/arm64-sysv/types.c b/src/cmd/scc-cc/cc2/arm64-sysv/types.c
@@ -0,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 4
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 8,
+ .align = 8
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 16,
+ .align = 16
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+Type arg_type = {
+ .flags = ARRF,
+ .size = 24,
+ .align = 8
+};
diff --git a/src/cmd/scc-cc/cc2/deps.mk b/src/cmd/scc-cc/cc2/deps.mk
@@ -16,48 +16,48 @@ peep.o: $(INCDIR)/bits/scc/scc.h
peep.o: cc2.h
symbol.o: $(INCDIR)/bits/scc/scc.h
symbol.o: cc2.h
-target/amd64-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h
-target/amd64-sysv/cgen.o: target/amd64-sysv/../../cc2.h
-target/amd64-sysv/cgen.o: target/amd64-sysv/arch.h
-target/amd64-sysv/code.o: $(INCDIR)/bits/scc/cstd.h
-target/amd64-sysv/code.o: $(INCDIR)/bits/scc/scc.h
-target/amd64-sysv/code.o: target/amd64-sysv/../../cc2.h
-target/amd64-sysv/code.o: target/amd64-sysv/arch.h
-target/amd64-sysv/optm.o: $(INCDIR)/bits/scc/scc.h
-target/amd64-sysv/optm.o: target/amd64-sysv/../../cc2.h
-target/amd64-sysv/types.o: $(INCDIR)/bits/scc/scc.h
-target/amd64-sysv/types.o: target/amd64-sysv/../../cc2.h
-target/arm64-sysv/types.o: $(INCDIR)/bits/scc/scc.h
-target/arm64-sysv/types.o: target/arm64-sysv/../../cc2.h
-target/i386-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h
-target/i386-sysv/cgen.o: target/i386-sysv/../../cc2.h
-target/i386-sysv/cgen.o: target/i386-sysv/arch.h
-target/i386-sysv/code.o: $(INCDIR)/bits/scc/cstd.h
-target/i386-sysv/code.o: $(INCDIR)/bits/scc/scc.h
-target/i386-sysv/code.o: target/i386-sysv/../../cc2.h
-target/i386-sysv/code.o: target/i386-sysv/arch.h
-target/i386-sysv/optm.o: $(INCDIR)/bits/scc/scc.h
-target/i386-sysv/optm.o: target/i386-sysv/../../cc2.h
-target/i386-sysv/types.o: $(INCDIR)/bits/scc/scc.h
-target/i386-sysv/types.o: target/i386-sysv/../../cc2.h
-target/qbe/cgen.o: $(INCDIR)/bits/scc/cstd.h
-target/qbe/cgen.o: $(INCDIR)/bits/scc/scc.h
-target/qbe/cgen.o: target/qbe/../../cc2.h
-target/qbe/cgen.o: target/qbe/arch.h
-target/qbe/code.o: $(INCDIR)/bits/scc/cstd.h
-target/qbe/code.o: $(INCDIR)/bits/scc/scc.h
-target/qbe/code.o: target/qbe/../../cc2.h
-target/qbe/code.o: target/qbe/arch.h
-target/qbe/optm.o: $(INCDIR)/bits/scc/scc.h
-target/qbe/optm.o: target/qbe/../../cc2.h
-target/z80-scc/cgen.o: $(INCDIR)/bits/scc/scc.h
-target/z80-scc/cgen.o: target/z80-scc/../../cc2.h
-target/z80-scc/cgen.o: target/z80-scc/arch.h
-target/z80-scc/code.o: $(INCDIR)/bits/scc/cstd.h
-target/z80-scc/code.o: $(INCDIR)/bits/scc/scc.h
-target/z80-scc/code.o: target/z80-scc/../../cc2.h
-target/z80-scc/code.o: target/z80-scc/arch.h
-target/z80-scc/optm.o: $(INCDIR)/bits/scc/scc.h
-target/z80-scc/optm.o: target/z80-scc/../../cc2.h
-target/z80-scc/types.o: $(INCDIR)/bits/scc/scc.h
-target/z80-scc/types.o: target/z80-scc/../../cc2.h
+amd64-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h
+amd64-sysv/cgen.o: amd64-sysv/../cc2.h
+amd64-sysv/cgen.o: amd64-sysv/arch.h
+amd64-sysv/code.o: $(INCDIR)/bits/scc/cstd.h
+amd64-sysv/code.o: $(INCDIR)/bits/scc/scc.h
+amd64-sysv/code.o: amd64-sysv/../cc2.h
+amd64-sysv/code.o: amd64-sysv/arch.h
+amd64-sysv/optm.o: $(INCDIR)/bits/scc/scc.h
+amd64-sysv/optm.o: amd64-sysv/../cc2.h
+amd64-sysv/types.o: $(INCDIR)/bits/scc/scc.h
+amd64-sysv/types.o: amd64-sysv/../cc2.h
+arm64-sysv/types.o: $(INCDIR)/bits/scc/scc.h
+arm64-sysv/types.o: arm64-sysv/../cc2.h
+i386-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h
+i386-sysv/cgen.o: i386-sysv/../cc2.h
+i386-sysv/cgen.o: i386-sysv/arch.h
+i386-sysv/code.o: $(INCDIR)/bits/scc/cstd.h
+i386-sysv/code.o: $(INCDIR)/bits/scc/scc.h
+i386-sysv/code.o: i386-sysv/../cc2.h
+i386-sysv/code.o: i386-sysv/arch.h
+i386-sysv/optm.o: $(INCDIR)/bits/scc/scc.h
+i386-sysv/optm.o: i386-sysv/../cc2.h
+i386-sysv/types.o: $(INCDIR)/bits/scc/scc.h
+i386-sysv/types.o: i386-sysv/../cc2.h
+qbe/cgen.o: $(INCDIR)/bits/scc/cstd.h
+qbe/cgen.o: $(INCDIR)/bits/scc/scc.h
+qbe/cgen.o: qbe/../cc2.h
+qbe/cgen.o: qbe/arch.h
+qbe/code.o: $(INCDIR)/bits/scc/cstd.h
+qbe/code.o: $(INCDIR)/bits/scc/scc.h
+qbe/code.o: qbe/../cc2.h
+qbe/code.o: qbe/arch.h
+qbe/optm.o: $(INCDIR)/bits/scc/scc.h
+qbe/optm.o: qbe/../cc2.h
+z80-scc/cgen.o: $(INCDIR)/bits/scc/scc.h
+z80-scc/cgen.o: z80-scc/../cc2.h
+z80-scc/cgen.o: z80-scc/arch.h
+z80-scc/code.o: $(INCDIR)/bits/scc/cstd.h
+z80-scc/code.o: $(INCDIR)/bits/scc/scc.h
+z80-scc/code.o: z80-scc/../cc2.h
+z80-scc/code.o: z80-scc/arch.h
+z80-scc/optm.o: $(INCDIR)/bits/scc/scc.h
+z80-scc/optm.o: z80-scc/../cc2.h
+z80-scc/types.o: $(INCDIR)/bits/scc/scc.h
+z80-scc/types.o: z80-scc/../cc2.h
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/arch.h b/src/cmd/scc-cc/cc2/i386-sysv/arch.h
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/cgen.c b/src/cmd/scc-cc/cc2/i386-sysv/cgen.c
@@ -0,0 +1,14 @@
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/code.c b/src/cmd/scc-cc/cc2/i386-sysv/code.c
@@ -0,0 +1,213 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\t.text\n",
+ [DATASEG] = "\t.data\n",
+ [BSSSEG] = "\t.bss\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".L%d", sym->numid);
+
+ return name;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ pprint(np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ if (tp->flags & STRF) {
+ s = "\t.ascii\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\t.byte\t";
+ break;
+ case 2:
+ s = "\t.short\t";
+ break;
+ case 4:
+ s = "\t.long\t";
+ break;
+ case 8:
+ s = "\t.quad\t";
+ break;
+ default:
+ s = "\t.space\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+ Type *tp = &sym->type;
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\t.extern\t%s\n", name);
+ case SLOCAL:
+ return;
+ case SGLOB:
+ printf("\t.global\t%s\n", name);
+ if (seg == BSSSEG)
+ printf("\t.comm\t%s,%lu\n", name, tp->size);
+ break;
+ }
+ if (sym->type.align != 1)
+ printf("\t.align\t%lu\n", sym->type.align );
+ printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+deftype(Type *tp)
+{
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/optm.c b/src/cmd/scc-cc/cc2/i386-sysv/optm.c
@@ -0,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/target.mk b/src/cmd/scc-cc/cc2/i386-sysv/target.mk
@@ -0,0 +1,9 @@
+OBJ-i386-sysv = $(OBJS) \
+ i386-sysv/cgen.o \
+ i386-sysv/optm.o \
+ i386-sysv/code.o \
+ i386-sysv/types.o
+
+cc2-i386-sysv: $(LIBSCC) $(OBJ-i386-sysv)
+ $(CC) $(PROJ_LDFLAGS) $(OBJ-i386-sysv) -lscc $(PROJ_LDLIBS) -o $@
+ cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/types.c b/src/cmd/scc-cc/cc2/i386-sysv/types.c
@@ -0,0 +1,92 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 4
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 2
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 4
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 4
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 8,
+ .align = 4
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 12,
+ .align = 4
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+Type arg_type = {
+ .size = 4,
+ .align = 4
+};
diff --git a/src/cmd/scc-cc/cc2/target/qbe/arch.h b/src/cmd/scc-cc/cc2/qbe/arch.h
diff --git a/src/cmd/scc-cc/cc2/qbe/cgen.c b/src/cmd/scc-cc/cc2/qbe/cgen.c
@@ -0,0 +1,782 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+#define I1BYTES 0
+#define I2BYTES 1
+#define I4BYTES 2
+#define I8BYTES 3
+
+static unsigned char opasmw[][2] = {
+ [OADD] = {ASADDW, ASADDW},
+ [OSUB] = {ASSUBW, ASSUBW},
+ [OMUL] = {ASMULW, ASMULW},
+ [OMOD] = {ASMODW, ASUMODW},
+ [ODIV] = {ASDIVW, ASUDIVW},
+ [OSHL] = {ASSHLW, ASSHLW},
+ [OSHR] = {ASSHRW, ASUSHRW},
+ [OLT] = {ASLTW, ASULTW},
+ [OGT] = {ASGTW, ASUGTW},
+ [OLE] = {ASLEW, ASULEW},
+ [OGE] = {ASGEW, ASUGEW},
+ [OEQ] = {ASEQW, ASEQW},
+ [ONE] = {ASNEW, ASNEW},
+ [OBAND] = {ASBANDW, ASBANDW},
+ [OBOR] = {ASBORW, ASBORW},
+ [OBXOR] = {ASBXORW, ASBXORW},
+};
+
+static unsigned char opasml[][2] = {
+ [OADD] = {ASADDL, ASADDL},
+ [OSUB] = {ASSUBL, ASSUBL},
+ [OMUL] = {ASMULL, ASMULL},
+ [OMOD] = {ASMODL, ASUMODL},
+ [ODIV] = {ASDIVL, ASUDIVL},
+ [OSHL] = {ASSHLL, ASSHLL},
+ [OSHR] = {ASSHRL, ASUSHRL},
+ [OLT] = {ASLTL, ASULTL},
+ [OGT] = {ASGTL, ASUGTL},
+ [OLE] = {ASLEL, ASULEL},
+ [OGE] = {ASGEL, ASUGEL},
+ [OEQ] = {ASEQL, ASEQL},
+ [ONE] = {ASNEL, ASNEL},
+ [OBAND] = {ASBANDL, ASBANDL},
+ [OBOR] = {ASBORL, ASBORL},
+ [OBXOR] = {ASBXORL, ASBXORL},
+};
+
+static unsigned char opasms[][2] = {
+ [OADD] = {ASADDS, ASADDS},
+ [OSUB] = {ASSUBS, ASSUBS},
+ [OMUL] = {ASMULS, ASMULS},
+ [ODIV] = {ASDIVS, ASDIVS},
+ [OLT] = {ASLTS, ASLTS},
+ [OGT] = {ASGTS, ASGTS},
+ [OLE] = {ASLES, ASLES},
+ [OGE] = {ASGES, ASGES},
+ [OEQ] = {ASEQS, ASEQS},
+ [ONE] = {ASNES, ASNES},
+};
+
+static unsigned char opasmd[][2] = {
+ [OADD] = {ASADDD, ASADDD},
+ [OSUB] = {ASSUBD, ASSUBD},
+ [OMUL] = {ASMULD, ASMULD},
+ [ODIV] = {ASDIVD, ASDIVD},
+ [OLT] = {ASLTD, ASLTD},
+ [OGT] = {ASGTD, ASGTD},
+ [OLE] = {ASLED, ASLED},
+ [OGE] = {ASGED, ASGED},
+ [OEQ] = {ASEQD, ASEQD},
+ [ONE] = {ASNED, ASNED},
+};
+
+static unsigned char (*opbin[][2])[2] = {
+ {opasmw, opasml},
+ {opasms, opasmd},
+};
+
+static unsigned char i2i_conv[4][4][2] = {
+ [I1BYTES] = {
+ [I4BYTES] = {ASEXTBW, ASUEXTBW},
+ [I8BYTES] = {ASEXTBL, ASUEXTBL},
+ },
+ [I2BYTES] = {
+ [I4BYTES] = {ASEXTHW, ASUEXTHW},
+ [I8BYTES] = {ASEXTHL, ASUEXTHL},
+ },
+ [I4BYTES] = {
+ [I8BYTES] = {ASEXTWL, ASUEXTWL},
+ }
+};
+
+static unsigned char f2i_conv[4][4][2] = {
+ [I4BYTES] = {
+ [I4BYTES] = {ASSTOW, ASSTOUW},
+ [I8BYTES] = {ASSTOL, ASDTOUL},
+ },
+ [I8BYTES] = {
+ [I4BYTES] = {ASDTOW, ASDTOUW},
+ [I8BYTES] = {ASDTOL, ASDTOUL},
+ }
+};
+
+static unsigned char i2f_conv[4][4][2] = {
+ [I4BYTES] = {
+ [I4BYTES] = {ASSWTOS, ASUWTOS},
+ [I8BYTES] = {ASSWTOD, ASUWTOD},
+ },
+ [I8BYTES] = {
+ [I4BYTES] = {ASSLTOS, ASULTOS},
+ [I8BYTES] = {ASSLTOD, ASULTOD},
+ }
+};
+
+extern Type int32type, uint32type, ptrtype;
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ * AUTO => 11 value+fp
+ * REG => 11 reg
+ * STATIC => 11 (value)
+ * CONST => 11 $value
+ * These values of addressability are not used in the code generation.
+ * They are only used to calculate the Sethi-Ullman numbers. Since
+ * QBE is AMD64 targered we could do a better job there, and try to
+ * detect some of the complex addressing modes of these processors.
+ */
+static Node *
+complex(Node *np)
+{
+ Node *lp = np->left, *rp = np->right;
+
+ if (np->address > 10)
+ return np;
+ if (lp)
+ np->complex = lp->complex;
+ if (rp) {
+ int d = np->complex - rp->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = rp->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+
+ return np;
+}
+
+Node *
+sethi(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->address = 0;
+ lp = np->left;
+ rp = np->right;
+
+ switch (np->op) {
+ case OAUTO:
+ case OREG:
+ case OMEM:
+ case OCONST:
+ np->address = 11;
+ break;
+ case OASSIG:
+ assert(lp->op != OCAST);
+ goto binary;
+ case OCPL:
+ assert(np->type.flags & INTF);
+ np->op = OBXOR;
+ rp = constnode(NULL, ~(TUINT) 0, &np->type);
+ goto binary;
+ case OSNEG:
+ np->op = OSUB;
+ rp = lp;
+ lp = constnode(NULL, 0, &np->type);
+ if ((np->type.flags & INTF) == 0)
+ lp->u.f = 0.0;
+ default:
+ binary:
+ lp = sethi(lp);
+ rp = sethi(rp);
+ break;
+ }
+ np->left = lp;
+ np->right = rp;
+
+ return complex(np);
+}
+
+static int
+bytes2idx(int nbytes)
+{
+ if (nbytes== 1)
+ return I1BYTES;
+ else if (nbytes == 2)
+ return I2BYTES;
+ else if (nbytes == 4)
+ return I4BYTES;
+ else if (nbytes == 8)
+ return I8BYTES;
+ else
+ abort();
+}
+
+static Node *
+load(Type *tp, Node *np)
+{
+ int op;
+ Node *new;
+ int flags = tp->flags;
+
+ if (flags & (AGGRF|FUNF|ARRF|PTRF))
+ return np;
+
+ switch (tp->size) {
+ case 1:
+ op = ASLDSB;
+ break;
+ case 2:
+ op = ASLDSH;
+ break;
+ case 4:
+ op = (flags & FLOATF) ? ASLDS : ASLDSW;
+ break;
+ case 8:
+ op = (flags & FLOATF) ? ASLDD : ASLDL;
+ break;
+ default:
+ abort();
+ }
+ /*
+ * unsigned version of operations are always +1 the
+ * signed version
+ */
+ if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
+ ++op;
+
+ new = tmpnode(tp);
+ code(op, new, np, NULL);
+
+ return new;
+}
+
+static Node *rhs(Node *np);
+
+static Node *
+cast(Type *td, Node *np)
+{
+ Type *ts;
+ Node *tmp;
+ int op, d_isint, s_isint, sidx, didx, sign;
+
+ ts = &np->type;
+ d_isint = (td->flags & INTF) != 0;
+ s_isint = (ts->flags & INTF) != 0;
+
+ sidx = bytes2idx(ts->size);
+ didx = bytes2idx(td->size);
+
+ sign = (ts->flags & SIGNF) == 0;
+
+ if (d_isint && s_isint) {
+ /* conversion from int to int */
+ if (didx < I4BYTES)
+ didx = bytes2idx(4);
+
+ if (didx <= sidx) {
+ np->type = *td;
+ return np;
+ }
+
+ op = i2i_conv[sidx][didx][sign];
+ } else if (d_isint) {
+ /* conversion from float to int */
+ if (didx < I4BYTES)
+ didx = bytes2idx(4);
+
+ op = f2i_conv[sidx][didx][sign];
+ } else if (s_isint) {
+ /* conversion from int to float */
+ if (sidx == I1BYTES || sidx == I2BYTES) {
+ ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
+ np = cast(ts, np);
+ }
+ op = i2f_conv[sidx][didx][sign];
+ } else {
+ /* conversion from float to float */
+ op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD;
+ }
+
+ assert(op != 0);
+ tmp = tmpnode(td);
+ code(op, tmp, np, NULL);
+
+ return tmp;
+}
+
+static Node *
+call(Node *np, Node *fun)
+{
+ int n, op;
+ Type *tp;
+ Node **q, *tmp, *p, *pars[NR_FUNPARAM];
+
+ for (n = 0, p = np->right; p; p = p->right)
+ pars[n++] = rhs(p->left);
+
+ tp = &np->type;
+ tmp = tmpnode(tp);
+ code(ASCALL, tmp, fun, NULL);
+
+ for (q = pars; q < &pars[n]; ++q) {
+ op = (q == &pars[n-1]) ? ASPARE : ASPAR;
+ code(op, NULL, *q, tmpnode(&(*q)->type));
+ }
+ code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
+
+ return tmp;
+}
+
+static Node *
+copy(Type *tp, Node *to, Node *from)
+{
+ int op;
+
+ switch (tp->size) {
+ case 0:
+ return from;
+ case 1:
+ op = ASCOPYB;
+ break;
+ case 2:
+ op = ASCOPYH;
+ break;
+ case 4:
+ op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
+ break;
+ case 8:
+ op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
+ break;
+ default:
+ abort();
+ }
+ code(op, to, from, NULL);
+ return from;
+}
+
+static Node *
+field(Node *np, int islhs)
+{
+ Node *tmp, *addr;
+ TUINT offset = np->right->u.sym->u.off;
+
+ addr = rhs(np->left);
+ tmp = node(OADD);
+ tmp->type = ptrtype;
+ tmp->left = addr;
+ tmp->right = constnode(NULL, offset, &ptrtype);
+ addr = rhs(tmp);
+
+ if (!islhs)
+ addr = load(&np->type, addr);
+ return addr;
+}
+
+static Node *
+lhs(Node *np)
+{
+ switch (np->op) {
+ case OREG:
+ case OMEM:
+ case OAUTO:
+ return np;
+ case OPTR:
+ return rhs(np->left);
+ case OFIELD:
+ return field(np, 1);
+ default:
+ abort();
+ }
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+ Node *l = np->left, *r = np->right;
+ Node ret, ifyes, ifno;
+ Symbol *label;
+
+ switch (np->op) {
+ case ONEG:
+ bool(l, false, true);
+ break;
+ case OAND:
+ label = newlabel();
+ bool(l, label, false);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ case OOR:
+ label = newlabel();
+ bool(l, true, label);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ default:
+ label2node(&ifyes, true);
+ label2node(&ifno, false);
+ code(ASBRANCH, rhs(np), &ifyes, &ifno);
+ break;
+ }
+}
+
+static Node *
+ternary(Node *np)
+{
+ Node ifyes, ifno, phi, *colon, *tmp;
+
+ tmp = tmpnode(&np->type);
+ label2node(&ifyes, NULL);
+ label2node(&ifno, NULL);
+ label2node(&phi, NULL);
+
+ colon = np->right;
+ code(ASBRANCH, rhs(np->left), &ifyes, &ifno);
+
+ setlabel(ifyes.u.sym);
+ copy(&tmp->type, tmp, rhs(colon->left));
+ code(ASJMP, NULL, &phi, NULL);
+
+ setlabel(ifno.u.sym);
+ copy(&tmp->type, tmp, rhs(colon->right));
+ setlabel(phi.u.sym);
+
+ return tmp;
+}
+
+static Node *
+function(void)
+{
+ Node aux;
+ Symbol *p;
+
+ /* allocate stack space for parameters */
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) == 0)
+ continue;
+ if ((p->type.flags & AGGRF) != 0)
+ continue;
+ code(ASALLOC, label2node(&aux, p), NULL, NULL);
+ }
+
+ /* allocate stack space for local variables) */
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) != 0)
+ continue;
+ if (p->kind != SAUTO || p->id == TMPSYM)
+ continue;
+ code(ASALLOC, label2node(&aux, p), NULL, NULL);
+ }
+
+ /* store formal parameters in parameters */
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) == 0)
+ continue;
+ if ((p->type.flags & AGGRF) != 0)
+ continue;
+ if ((p->type.flags & (ARRF|AGGRF)) == 0)
+ code(ASFORM, label2node(&aux, p), NULL, NULL);
+ }
+ return NULL;
+}
+
+static void
+swtch_if(Node *idx)
+{
+ Node aux1, aux2, *np;
+ Symbol *deflabel = NULL;
+
+ for (;;) {
+ np = delstmt();
+ setlabel(np->label);
+
+ switch (np->op) {
+ case OESWITCH:
+ if (!deflabel)
+ deflabel = np->u.sym;
+ aux1.op = OJMP;
+ aux1.label = NULL;
+ aux1.u.sym = deflabel;
+ cgen(&aux1);
+ return;
+ case OCASE:
+ aux1 = *np;
+ aux1.op = OBRANCH;
+ aux1.label = NULL;
+ aux1.left = &aux2;
+
+ aux2.op = OEQ;
+ aux2.type = idx->type;
+ aux2.left = np->left;
+ aux2.right = idx;
+
+ cgen(&aux1);
+ break;
+ case ODEFAULT:
+ deflabel = np->u.sym;
+ break;
+ default:
+ abort();
+ }
+ }
+}
+
+static int
+assignop(Type *tp)
+{
+ int flags = tp->flags;
+
+ if (flags & (AGGRF|FUNF|ARRF))
+ return ASSTM;
+
+ switch (tp->size) {
+ case 1:
+ return ASSTB;
+ case 2:
+ return ASSTH;
+ case 4:
+ return (tp->flags & FLOATF) ? ASSTS : ASSTW;
+ case 8:
+ return (tp->flags & FLOATF) ? ASSTD : ASSTL;
+ default:
+ abort();
+ }
+}
+
+static void
+rhs_rhs(Node **lp, Node **rp)
+{
+ Node *l = *lp, *r = *rp;
+
+ if (l->complex >= r->complex) {
+ l = rhs(l);
+ r = rhs(r);
+ } else {
+ r = rhs(r);
+ l = rhs(l);
+ }
+
+ *lp = l, *rp = r;
+}
+
+static void
+lhs_rhs(Node **lp, Node **rp)
+{
+ Node *l = *lp, *r = *rp;
+
+ if (l->complex >= r->complex) {
+ l = lhs(l);
+ r = rhs(r);
+ } else {
+ r = rhs(r);
+ l = lhs(l);
+ }
+
+ *lp = l, *rp = r;
+}
+
+static Node *
+assign(Node *np)
+{
+ Node *ret, aux;
+ Node *l = np->left, *r = np->right;
+ int op;
+
+ switch (np->u.subop) {
+ break;
+ case OINC:
+ op = OADD;
+ goto post_oper;
+ case ODEC:
+ op = OSUB;
+ post_oper:
+ lhs_rhs(&l, &r);
+ ret = load(&l->type, l);
+ aux.op = op;
+ aux.left = ret;
+ aux.right = r;
+ aux.type = np->type;
+ r = rhs(sethi(&aux));
+ break;
+ default:
+ /* assign abbreviation */
+ assert(l->type.size == r->type.size);
+ if (r->type.size < 4) {
+ lhs_rhs(&l, &r);
+ aux.op = np->u.subop;
+ aux.left = load(&r->type, l);
+ aux.right = r;
+ aux.type = int32type;
+ aux.address = np->address;
+ ret = r = sethi(rhs(&aux));
+ break;
+ }
+
+ aux.op = np->u.subop;
+ aux.left = l;
+ aux.right = r;
+ aux.type = np->type;
+ aux.address = np->address;
+ r = sethi(&aux);
+ case 0:
+ lhs_rhs(&l, &r);
+ ret = r;
+ break;
+ }
+
+ code(assignop(&np->type), l, r, NULL);
+ return ret;
+}
+
+static Node *
+rhs(Node *np)
+{
+ Node *tmp, aux1, aux2;
+ Node *phi, *l = np->left, *r = np->right;
+ Type *tp;
+ int sign, size, isfloat, op;
+ Symbol *true, *false;
+
+ tp = &np->type;
+
+ switch (np->op) {
+ case OBFUN:
+ return function();
+ case ONOP:
+ case OBLOOP:
+ case OELOOP:
+ case OEFUN:
+ return NULL;
+ case OTMP:
+ case OCONST:
+ return np;
+ case OMEM:
+ case OREG:
+ case OAUTO:
+ return load(tp, np);
+ case ONEG:
+ case OAND:
+ case OOR:
+ true = newlabel();
+ false = newlabel();
+ phi = label2node(&aux1, NULL);
+ tmp = tmpnode(&int32type);
+
+ bool(np, true, false);
+
+ setlabel(true);
+ code(ASCOPYW, tmp, constnode(&aux2, 1, &int32type), NULL);
+ code(ASJMP, NULL, phi, NULL);
+
+ setlabel(false);
+ code(ASCOPYW, tmp, constnode(&aux2, 0, &int32type), NULL);
+
+ setlabel(phi->u.sym);
+ return tmp;
+ case OMOD:
+ case OSHL:
+ case OBAND:
+ case OBOR:
+ case OBXOR:
+ case OSHR:
+ assert(tp->flags & INTF);
+ case ODIV:
+ case OLT:
+ case OGT:
+ case OLE:
+ case OGE:
+ case OADD:
+ case OSUB:
+ case OMUL:
+ case OEQ:
+ case ONE:
+ assert(tp->size == 4 || tp->size == 8);
+
+ sign = (tp->flags & SIGNF) == 0;
+ size = tp->size == 8;
+ isfloat = (tp->flags & FLOATF) != 0;
+ op = opbin[isfloat][size][np->op][sign];
+ rhs_rhs(&l, &r);
+ tmp = tmpnode(tp);
+ code(op, tmp, l, r);
+ return tmp;
+ case OCALL:
+ case OCALLE:
+ if (l->op == OPTR)
+ l = rhs(l);
+ return call(np, l);
+ case OCAST:
+ return cast(tp, rhs(l));
+ case OASSIG:
+ return assign(np);
+ case OASK:
+ return ternary(np);
+ case OCOMMA:
+ rhs(l);
+ return rhs(r);
+ case OPTR:
+ return load(tp, rhs(l));
+ case OADDR:
+ l = lhs(l);
+ l->type = *tp;
+ l->type.flags |= PTRF;
+ return l;
+ case OFIELD:
+ return field(np, 0);
+ case OBUILTIN:
+ switch (np->u.subop) {
+ case BVA_START:
+ l = rhs(l);
+ code(ASVSTAR, NULL, l, NULL);
+ case BVA_END:
+ return NULL;
+ case BVA_ARG:
+ l = rhs(l);
+ tmp = tmpnode(tp);
+ code(ASVARG, tmp, l, NULL);
+ return tmp;
+ default:
+ abort();
+ }
+ default:
+ abort();
+ }
+ abort();
+}
+
+Node *
+cgen(Node *np)
+{
+ Node aux, *p, *next;
+
+ setlabel(np->label);
+ switch (np->op) {
+ case OJMP:
+ label2node(&aux, np->u.sym);
+ code(ASJMP, NULL, &aux, NULL);
+ break;
+ case OBRANCH:
+ next = np->next;
+ if (!next->label)
+ next->label = newlabel();
+ bool(np->left, np->u.sym, next->label);
+ break;
+ case ORET:
+ p = (np->left) ? rhs(np->left) : NULL;
+ code(ASRET, NULL, p, NULL);
+ break;
+ case OBSWITCH:
+ p = rhs(np->left);
+ swtch_if(p);
+ break;
+ default:
+ rhs(np);
+ break;
+ }
+ return NULL;
+}
diff --git a/src/cmd/scc-cc/cc2/qbe/code.c b/src/cmd/scc-cc/cc2/qbe/code.c
@@ -0,0 +1,605 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+#define ADDR_LEN (INTIDENTSIZ+64)
+
+static void binary(void), unary(void), store(void), jmp(void), ret(void),
+ branch(void), call(void), ecall(void), param(void),
+ asalloc(void), form2local(void), blit(void), vastart(void),
+ vaarg(void);
+
+static struct opdata {
+ void (*fun)(void);
+ char *txt;
+ char letter;
+} optbl [] = {
+ [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'},
+ [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'},
+ [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'},
+ [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'},
+ [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'},
+ [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'},
+ [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'},
+ [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'},
+ [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'},
+
+ [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'},
+ [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'},
+ [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'},
+ [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'},
+ [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'},
+ [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'},
+
+ [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'},
+ [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'},
+ [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'},
+ [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'},
+ [ASSTM] = {.fun = blit},
+ [ASSTS] = {.fun = store, .txt = "store", .letter = 's'},
+ [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'},
+
+ [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'},
+ [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'},
+ [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'},
+ [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'},
+ [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'},
+ [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'},
+ [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'},
+ [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'},
+ [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'},
+ [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'},
+ [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'},
+ [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'},
+ [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'},
+ [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'},
+ [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'},
+ [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'},
+ [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'},
+ [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'},
+ [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'},
+ [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'},
+ [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'},
+ [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'},
+ [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'},
+
+ [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'},
+ [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'},
+ [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'},
+ [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'},
+ [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'},
+ [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'},
+ [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'},
+ [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'},
+ [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'},
+ [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'},
+ [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'},
+ [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'},
+ [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'},
+ [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'},
+ [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'},
+ [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'},
+ [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'},
+ [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'},
+ [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'},
+ [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'},
+ [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'},
+ [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'},
+ [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'},
+
+ [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'},
+ [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'},
+ [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'},
+ [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'},
+ [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'},
+ [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'},
+ [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'},
+ [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'},
+ [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'},
+ [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'},
+
+ [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'},
+ [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'},
+ [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'},
+ [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'},
+ [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'},
+ [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'},
+ [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'},
+ [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'},
+ [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'},
+ [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'},
+
+ [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'},
+ [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'},
+ [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'},
+ [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'},
+ [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'},
+ [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'},
+ [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'},
+ [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'},
+ [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'},
+ [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'},
+
+ [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
+ [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'},
+ [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
+ [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'},
+ [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
+ [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'},
+ [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
+ [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'},
+
+ [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
+ [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'},
+ [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
+ [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'},
+ [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
+ [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'},
+ [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
+ [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'},
+
+ [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
+ [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
+
+ [ASBRANCH] = {.fun = branch},
+ [ASJMP] = {.fun = jmp},
+ [ASRET] = {.fun = ret},
+ [ASCALL] = {.fun = call},
+ [ASCALLE] = {.fun = ecall, .txt = ")"},
+ [ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
+ [ASPAR] = {.fun = param, .txt = "%s %s, "},
+ [ASPARE] = {.fun = param, .txt = "%s %s"},
+ [ASALLOC] = {.fun = asalloc},
+ [ASFORM] = {.fun = form2local},
+
+ [ASVSTAR] = {.fun = vastart},
+ [ASVARG] = {.fun = vaarg},
+};
+
+static char buff[ADDR_LEN];
+/*
+ * : is for user-defined Aggregate Types
+ * $ is for globals (represented by a pointer)
+ * % is for function-scope temporaries
+ * @ is for block labels
+ */
+static char
+sigil(Symbol *sym)
+{
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ case SLOCAL:
+ return '$';
+ case SAUTO:
+ case STMP:
+ return '%';
+ case SLABEL:
+ return '@';
+ default:
+ abort();
+ }
+}
+
+static char *
+symname(Symbol *sym)
+{
+ char c = sigil(sym);
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ sprintf(buff, "%c%s", c, sym->name);
+ return buff;
+ case SLOCAL:
+ case SPRIV:
+ case SAUTO:
+ sprintf(buff, "%c%s.L%u", c, sym->name, sym->id);
+ return buff;
+ default:
+ abort();
+ }
+ }
+ sprintf(buff, "%c.L%u", c, sym->numid);
+
+ return buff;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ pprint(np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+
+static char *
+size2asm(Type *tp)
+{
+ static char spec[ADDR_LEN];
+
+ if (tp->flags & STRF) {
+ return "b";
+ } else if (tp->flags & INTF) {
+ switch (tp->size) {
+ case 1:
+ return "b";
+ case 2:
+ return "h";
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+ }
+ } else if (tp->flags & FLOATF) {
+ if (tp->size == 4)
+ return "s";
+ else if (tp->size == 8)
+ return "d";
+ }
+
+ abort();
+}
+
+void
+defglobal(Symbol *sym)
+{
+ Type *tp = &sym->type;
+
+ if (sym->kind == SEXTRN)
+ return;
+ if (sym->kind == SGLOB)
+ fputs("export ", stdout);
+ if ((tp->flags & INITF) == 0)
+ fputs("common ", stdout);
+
+ printf("data %s = align %d {\n",
+ symname(sym),
+ tp->align);
+ if ((tp->flags & INITF) == 0)
+ printf("\tz\t%lu\n}\n", tp->size);
+}
+
+void
+defpar(Symbol *sym)
+{
+ if (sym->kind == SREG)
+ sym->kind = SAUTO;
+ sym->type.flags |= PARF;
+}
+
+void
+defvar(Symbol *sym)
+{
+ if (sym->kind == SREG)
+ sym->kind = SAUTO;
+}
+
+void
+data(Node *np)
+{
+ printf("\t%s\t", size2asm(&np->type));
+ emittree(np);
+ putchar(',');
+ putchar('\n');
+}
+
+static char *
+size2stack(Type *tp)
+{
+ static char spec[ADDR_LEN];
+
+ if (tp->flags & INTF) {
+ switch (tp->size) {
+ case 1:
+ case 2:
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+ }
+ } else if (tp->flags & FLOATF) {
+ if (tp->size == 4)
+ return "s";
+ else if (tp->size == 8)
+ return "d";
+ } else if (tp->flags & (ARRF|AGGRF)) {
+ sprintf(spec, ":.%u", tp->id);
+ return spec;
+ } else if (tp->size == 0) {
+ return "w";
+ }
+ abort();
+}
+
+void
+deftype(Type *tp)
+{
+ printf("type :.%u = align %d { %lu }\n",
+ tp->id, tp->align, tp->size);
+}
+
+void
+writeout(void)
+{
+ Symbol *p;
+ Type *tp;
+ char *sep;
+ int haslabel = 0;
+
+ if (!curfun)
+ return;
+ if (curfun->kind == SGLOB)
+ fputs("export ", stdout);
+ printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
+
+ /* declare formal parameters */
+ sep = "";
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) == 0)
+ continue;
+ printf("%s%s %s%s",
+ sep, size2stack(&p->type),
+ symname(p),
+ (p->type.flags & AGGRF) ? "" : ".val");
+ sep = ",";
+ }
+ printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
+
+ /* emit assembler instructions */
+ for (pc = prog; pc; pc = pc->next) {
+ if (pc->label) {
+ haslabel = 1;
+ printf("%s\n", symname(pc->label));
+ }
+ if (pc->op == ASLABEL)
+ continue;
+ if (pc->flags&BBENTRY && !haslabel)
+ printf("%s\n", symname(newlabel()));
+ (*optbl[pc->op].fun)();
+ if (!pc->label)
+ haslabel = 0;
+ }
+
+ puts("}");
+}
+
+static char *
+addr2txt(Addr *a)
+{
+ switch (a->kind) {
+ case SCONST:
+ sprintf(buff, "%llu", (unsigned long long) a->u.i);
+ return buff;
+ case SAUTO:
+ case SLABEL:
+ case STMP:
+ case SGLOB:
+ case SEXTRN:
+ case SPRIV:
+ case SLOCAL:
+ return symname(a->u.sym);
+ default:
+ abort();
+ }
+}
+
+static void
+binary(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from1, addr2txt(&pc->from1));
+ strcpy(from2, addr2txt(&pc->from2));
+ printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
+}
+
+static void
+blit(void)
+{
+ Type *tp = &pc->to.u.sym->type;
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size);
+}
+
+static void
+store(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
+}
+
+static void
+unary(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
+}
+
+static void
+call(void)
+{
+ char to[ADDR_LEN], from[ADDR_LEN];
+ Symbol *sym = pc->to.u.sym;
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t%s =%s\tcall\t%s(",
+ to, size2stack(&sym->type), from);
+}
+
+static void
+param(void)
+{
+ Symbol *sym = pc->from2.u.sym;
+
+ printf(optbl[pc->op].txt,
+ size2stack(&sym->type), addr2txt(&pc->from1));
+}
+
+static void
+ecall(void)
+{
+ struct opdata *p = &optbl[pc->op];
+
+ puts(p->txt);
+}
+
+static void
+ret(void)
+{
+ if (pc->from1.kind == SNONE)
+ puts("\t\tret");
+ else
+ printf("\t\tret\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+jmp(void)
+{
+ printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+branch(void)
+{
+ char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from1, addr2txt(&pc->from1));
+ strcpy(from2, addr2txt(&pc->from2));
+ printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
+}
+
+static void
+vastart(void)
+{
+ printf("\t\tvastart %s\n", addr2txt(&pc->from1));
+}
+
+static void
+vaarg(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
+}
+
+static void
+asalloc(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ extern Type ptrtype;
+
+ printf("\t%s =%s\talloc%lu\t%lu\n",
+ symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
+}
+
+static void
+form2local(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ char *name = symname(sym);
+
+ printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
+}
+
+void
+endinit(void)
+{
+ puts("}");
+}
+
+void
+getbblocks(void)
+{
+ Inst *i;
+
+ if (!prog)
+ return;
+
+ prog->flags |= BBENTRY;
+ for (pc = prog; pc; pc = pc->next) {
+ switch (pc->op) {
+ case ASBRANCH:
+ i = pc->from2.u.sym->u.inst;
+ i->flags |= BBENTRY;
+ case ASJMP:
+ i = pc->from1.u.sym->u.inst;
+ i->flags |= BBENTRY;
+ case ASRET:
+ if (pc->next)
+ pc->next->flags |= BBENTRY;
+ break;
+ }
+ }
+}
diff --git a/src/cmd/scc-cc/cc2/qbe/optm.c b/src/cmd/scc-cc/cc2/qbe/optm.c
@@ -0,0 +1,56 @@
+#include <stddef.h>
+
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ int op = np->op;
+ Node *p, *dst, *next = np->next;
+ Symbol *sym, *osym;
+
+ switch (op) {
+ case OEFUN:
+ /*
+ * In QBE we need at the end of a basic block
+ * a jump, so we have to ensure that the last
+ * statement of the function is a ret, a jmp
+ * or a branch. In the same way, QBE does
+ * not accept labels at the end of a function
+ * (ONOP is used for labels) so we have to add
+ * a ret there, and in the case of branches
+ * we need a label for the next statement
+ */
+ op = (np->prev) ? np->prev->op : 0;
+ if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
+ addstmt(node(ORET), KEEPCUR);
+ break;
+ case OBRANCH:
+ if (!next->label) {
+ sym = getsym(TMPSYM);
+ sym->kind = SLABEL;
+ next->label = sym;
+ }
+ case OJMP:
+ for (;;) {
+ dst = np->u.sym->u.stmt;
+ if (dst->op != OJMP)
+ break;
+ np->u.sym = dst->u.sym;
+ }
+ for (p = np->next; p; p = p->next) {
+ if (p == dst)
+ return NULL;
+ if (p->op == ONOP ||
+ p->op == OBLOOP ||
+ p->op == OELOOP) {
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ return np;
+}
diff --git a/src/cmd/scc-cc/cc2/qbe_amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/qbe_amd64-sysv/target.mk
@@ -0,0 +1,9 @@
+OBJ-qbe_amd64-sysv = $(OBJS) \
+ qbe/cgen.o \
+ qbe/optm.o \
+ qbe/code.o \
+ amd64-sysv/types.o
+
+cc2-qbe_amd64-sysv: $(LIBSCC) $(OBJ-qbe_amd64-sysv)
+ $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@
+ cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/qbe_arm64-sysv/target.mk b/src/cmd/scc-cc/cc2/qbe_arm64-sysv/target.mk
@@ -0,0 +1,9 @@
+OBJ-qbe_arm64-sysv = $(OBJS) \
+ qbe/cgen.o \
+ qbe/optm.o \
+ qbe/code.o \
+ arm64-sysv/types.o \
+
+cc2-qbe_arm64-sysv: $(LIBSCC) $(OBJ-qbe_arm64-sysv)
+ $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_arm64-sysv) -lscc $(PROJ_LDLIBS) -o $@
+ cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/cgen.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/cgen.c
@@ -1,13 +0,0 @@
-#include "arch.h"
-#include <scc/scc.h>
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/code.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/code.c
@@ -1,214 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\t.text\n",
- [DATASEG] = "\t.data\n",
- [BSSSEG] = "\t.bss\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".L%d", sym->numid);
-
- return name;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- pprint(np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- if (tp->flags & STRF) {
- s = "\t.ascii\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\t.byte\t";
- break;
- case 2:
- s = "\t.short\t";
- break;
- case 4:
- s = "\t.long\t";
- break;
- case 8:
- s = "\t.quad\t";
- break;
- default:
- s = "\t.space\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
- Type *tp = &sym->type;
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\t.extern\t%s\n", name);
- case SLOCAL:
- return;
- case SGLOB:
- printf("\t.global\t%s\n", name);
- if (seg == BSSSEG)
- printf("\t.comm\t%s,%lu\n", name, tp->size);
- break;
- }
- if (sym->type.align != 1)
- printf("\t.align\t%lu\n", sym->type.align );
- printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-deftype(Type *tp)
-{
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/optm.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/optm.c
@@ -1,9 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/amd64-sysv/target.mk
@@ -1,9 +0,0 @@
-OBJ-amd64-sysv = $(OBJS) \
- target/amd64-sysv/cgen.o \
- target/amd64-sysv/optm.o \
- target/amd64-sysv/code.o \
- target/amd64-sysv/types.o
-
-cc2-amd64-sysv: $(LIBSCC) $(OBJ-amd64-sysv)
- $(CC) $(PROJ_LDFLAGS) $(OBJ-amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@
- cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/types.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/types.c
@@ -1,93 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 2
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 4
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 8
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 2
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 4
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 8
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 8,
- .align = 8
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 4
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 8,
- .align = 8
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 16,
- .align = 16
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-Type arg_type = {
- .flags = ARRF,
- .size = 24,
- .align = 8
-};
diff --git a/src/cmd/scc-cc/cc2/target/arm64-sysv/types.c b/src/cmd/scc-cc/cc2/target/arm64-sysv/types.c
@@ -1,93 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 2
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 4
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 8
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 2
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 4
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 8
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 8,
- .align = 8
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 4
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 8,
- .align = 8
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 16,
- .align = 16
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-Type arg_type = {
- .flags = ARRF,
- .size = 24,
- .align = 8
-};
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/cgen.c b/src/cmd/scc-cc/cc2/target/i386-sysv/cgen.c
@@ -1,14 +0,0 @@
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/code.c b/src/cmd/scc-cc/cc2/target/i386-sysv/code.c
@@ -1,213 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\t.text\n",
- [DATASEG] = "\t.data\n",
- [BSSSEG] = "\t.bss\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".L%d", sym->numid);
-
- return name;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- pprint(np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- if (tp->flags & STRF) {
- s = "\t.ascii\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\t.byte\t";
- break;
- case 2:
- s = "\t.short\t";
- break;
- case 4:
- s = "\t.long\t";
- break;
- case 8:
- s = "\t.quad\t";
- break;
- default:
- s = "\t.space\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
- Type *tp = &sym->type;
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\t.extern\t%s\n", name);
- case SLOCAL:
- return;
- case SGLOB:
- printf("\t.global\t%s\n", name);
- if (seg == BSSSEG)
- printf("\t.comm\t%s,%lu\n", name, tp->size);
- break;
- }
- if (sym->type.align != 1)
- printf("\t.align\t%lu\n", sym->type.align );
- printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-deftype(Type *tp)
-{
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/optm.c b/src/cmd/scc-cc/cc2/target/i386-sysv/optm.c
@@ -1,9 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/target.mk b/src/cmd/scc-cc/cc2/target/i386-sysv/target.mk
@@ -1,9 +0,0 @@
-OBJ-i386-sysv = $(OBJS) \
- target/i386-sysv/cgen.o \
- target/i386-sysv/optm.o \
- target/i386-sysv/code.o \
- target/i386-sysv/types.o
-
-cc2-i386-sysv: $(LIBSCC) $(OBJ-i386-sysv)
- $(CC) $(PROJ_LDFLAGS) $(OBJ-i386-sysv) -lscc $(PROJ_LDLIBS) -o $@
- cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/types.c b/src/cmd/scc-cc/cc2/target/i386-sysv/types.c
@@ -1,92 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 2
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 4
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 4
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 2
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 2
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 4
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 4,
- .align = 4
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 4
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 8,
- .align = 4
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 12,
- .align = 4
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-Type arg_type = {
- .size = 4,
- .align = 4
-};
diff --git a/src/cmd/scc-cc/cc2/target/qbe/cgen.c b/src/cmd/scc-cc/cc2/target/qbe/cgen.c
@@ -1,782 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-#define I1BYTES 0
-#define I2BYTES 1
-#define I4BYTES 2
-#define I8BYTES 3
-
-static unsigned char opasmw[][2] = {
- [OADD] = {ASADDW, ASADDW},
- [OSUB] = {ASSUBW, ASSUBW},
- [OMUL] = {ASMULW, ASMULW},
- [OMOD] = {ASMODW, ASUMODW},
- [ODIV] = {ASDIVW, ASUDIVW},
- [OSHL] = {ASSHLW, ASSHLW},
- [OSHR] = {ASSHRW, ASUSHRW},
- [OLT] = {ASLTW, ASULTW},
- [OGT] = {ASGTW, ASUGTW},
- [OLE] = {ASLEW, ASULEW},
- [OGE] = {ASGEW, ASUGEW},
- [OEQ] = {ASEQW, ASEQW},
- [ONE] = {ASNEW, ASNEW},
- [OBAND] = {ASBANDW, ASBANDW},
- [OBOR] = {ASBORW, ASBORW},
- [OBXOR] = {ASBXORW, ASBXORW},
-};
-
-static unsigned char opasml[][2] = {
- [OADD] = {ASADDL, ASADDL},
- [OSUB] = {ASSUBL, ASSUBL},
- [OMUL] = {ASMULL, ASMULL},
- [OMOD] = {ASMODL, ASUMODL},
- [ODIV] = {ASDIVL, ASUDIVL},
- [OSHL] = {ASSHLL, ASSHLL},
- [OSHR] = {ASSHRL, ASUSHRL},
- [OLT] = {ASLTL, ASULTL},
- [OGT] = {ASGTL, ASUGTL},
- [OLE] = {ASLEL, ASULEL},
- [OGE] = {ASGEL, ASUGEL},
- [OEQ] = {ASEQL, ASEQL},
- [ONE] = {ASNEL, ASNEL},
- [OBAND] = {ASBANDL, ASBANDL},
- [OBOR] = {ASBORL, ASBORL},
- [OBXOR] = {ASBXORL, ASBXORL},
-};
-
-static unsigned char opasms[][2] = {
- [OADD] = {ASADDS, ASADDS},
- [OSUB] = {ASSUBS, ASSUBS},
- [OMUL] = {ASMULS, ASMULS},
- [ODIV] = {ASDIVS, ASDIVS},
- [OLT] = {ASLTS, ASLTS},
- [OGT] = {ASGTS, ASGTS},
- [OLE] = {ASLES, ASLES},
- [OGE] = {ASGES, ASGES},
- [OEQ] = {ASEQS, ASEQS},
- [ONE] = {ASNES, ASNES},
-};
-
-static unsigned char opasmd[][2] = {
- [OADD] = {ASADDD, ASADDD},
- [OSUB] = {ASSUBD, ASSUBD},
- [OMUL] = {ASMULD, ASMULD},
- [ODIV] = {ASDIVD, ASDIVD},
- [OLT] = {ASLTD, ASLTD},
- [OGT] = {ASGTD, ASGTD},
- [OLE] = {ASLED, ASLED},
- [OGE] = {ASGED, ASGED},
- [OEQ] = {ASEQD, ASEQD},
- [ONE] = {ASNED, ASNED},
-};
-
-static unsigned char (*opbin[][2])[2] = {
- {opasmw, opasml},
- {opasms, opasmd},
-};
-
-static unsigned char i2i_conv[4][4][2] = {
- [I1BYTES] = {
- [I4BYTES] = {ASEXTBW, ASUEXTBW},
- [I8BYTES] = {ASEXTBL, ASUEXTBL},
- },
- [I2BYTES] = {
- [I4BYTES] = {ASEXTHW, ASUEXTHW},
- [I8BYTES] = {ASEXTHL, ASUEXTHL},
- },
- [I4BYTES] = {
- [I8BYTES] = {ASEXTWL, ASUEXTWL},
- }
-};
-
-static unsigned char f2i_conv[4][4][2] = {
- [I4BYTES] = {
- [I4BYTES] = {ASSTOW, ASSTOUW},
- [I8BYTES] = {ASSTOL, ASDTOUL},
- },
- [I8BYTES] = {
- [I4BYTES] = {ASDTOW, ASDTOUW},
- [I8BYTES] = {ASDTOL, ASDTOUL},
- }
-};
-
-static unsigned char i2f_conv[4][4][2] = {
- [I4BYTES] = {
- [I4BYTES] = {ASSWTOS, ASUWTOS},
- [I8BYTES] = {ASSWTOD, ASUWTOD},
- },
- [I8BYTES] = {
- [I4BYTES] = {ASSLTOS, ASULTOS},
- [I8BYTES] = {ASSLTOD, ASULTOD},
- }
-};
-
-extern Type int32type, uint32type, ptrtype;
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REG => 11 reg
- * STATIC => 11 (value)
- * CONST => 11 $value
- * These values of addressability are not used in the code generation.
- * They are only used to calculate the Sethi-Ullman numbers. Since
- * QBE is AMD64 targered we could do a better job there, and try to
- * detect some of the complex addressing modes of these processors.
- */
-static Node *
-complex(Node *np)
-{
- Node *lp = np->left, *rp = np->right;
-
- if (np->address > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
-
- return np;
-}
-
-Node *
-sethi(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->address = 0;
- lp = np->left;
- rp = np->right;
-
- switch (np->op) {
- case OAUTO:
- case OREG:
- case OMEM:
- case OCONST:
- np->address = 11;
- break;
- case OASSIG:
- assert(lp->op != OCAST);
- goto binary;
- case OCPL:
- assert(np->type.flags & INTF);
- np->op = OBXOR;
- rp = constnode(NULL, ~(TUINT) 0, &np->type);
- goto binary;
- case OSNEG:
- np->op = OSUB;
- rp = lp;
- lp = constnode(NULL, 0, &np->type);
- if ((np->type.flags & INTF) == 0)
- lp->u.f = 0.0;
- default:
- binary:
- lp = sethi(lp);
- rp = sethi(rp);
- break;
- }
- np->left = lp;
- np->right = rp;
-
- return complex(np);
-}
-
-static int
-bytes2idx(int nbytes)
-{
- if (nbytes== 1)
- return I1BYTES;
- else if (nbytes == 2)
- return I2BYTES;
- else if (nbytes == 4)
- return I4BYTES;
- else if (nbytes == 8)
- return I8BYTES;
- else
- abort();
-}
-
-static Node *
-load(Type *tp, Node *np)
-{
- int op;
- Node *new;
- int flags = tp->flags;
-
- if (flags & (AGGRF|FUNF|ARRF|PTRF))
- return np;
-
- switch (tp->size) {
- case 1:
- op = ASLDSB;
- break;
- case 2:
- op = ASLDSH;
- break;
- case 4:
- op = (flags & FLOATF) ? ASLDS : ASLDSW;
- break;
- case 8:
- op = (flags & FLOATF) ? ASLDD : ASLDL;
- break;
- default:
- abort();
- }
- /*
- * unsigned version of operations are always +1 the
- * signed version
- */
- if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
- ++op;
-
- new = tmpnode(tp);
- code(op, new, np, NULL);
-
- return new;
-}
-
-static Node *rhs(Node *np);
-
-static Node *
-cast(Type *td, Node *np)
-{
- Type *ts;
- Node *tmp;
- int op, d_isint, s_isint, sidx, didx, sign;
-
- ts = &np->type;
- d_isint = (td->flags & INTF) != 0;
- s_isint = (ts->flags & INTF) != 0;
-
- sidx = bytes2idx(ts->size);
- didx = bytes2idx(td->size);
-
- sign = (ts->flags & SIGNF) == 0;
-
- if (d_isint && s_isint) {
- /* conversion from int to int */
- if (didx < I4BYTES)
- didx = bytes2idx(4);
-
- if (didx <= sidx) {
- np->type = *td;
- return np;
- }
-
- op = i2i_conv[sidx][didx][sign];
- } else if (d_isint) {
- /* conversion from float to int */
- if (didx < I4BYTES)
- didx = bytes2idx(4);
-
- op = f2i_conv[sidx][didx][sign];
- } else if (s_isint) {
- /* conversion from int to float */
- if (sidx == I1BYTES || sidx == I2BYTES) {
- ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
- np = cast(ts, np);
- }
- op = i2f_conv[sidx][didx][sign];
- } else {
- /* conversion from float to float */
- op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD;
- }
-
- assert(op != 0);
- tmp = tmpnode(td);
- code(op, tmp, np, NULL);
-
- return tmp;
-}
-
-static Node *
-call(Node *np, Node *fun)
-{
- int n, op;
- Type *tp;
- Node **q, *tmp, *p, *pars[NR_FUNPARAM];
-
- for (n = 0, p = np->right; p; p = p->right)
- pars[n++] = rhs(p->left);
-
- tp = &np->type;
- tmp = tmpnode(tp);
- code(ASCALL, tmp, fun, NULL);
-
- for (q = pars; q < &pars[n]; ++q) {
- op = (q == &pars[n-1]) ? ASPARE : ASPAR;
- code(op, NULL, *q, tmpnode(&(*q)->type));
- }
- code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
-
- return tmp;
-}
-
-static Node *
-copy(Type *tp, Node *to, Node *from)
-{
- int op;
-
- switch (tp->size) {
- case 0:
- return from;
- case 1:
- op = ASCOPYB;
- break;
- case 2:
- op = ASCOPYH;
- break;
- case 4:
- op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
- break;
- case 8:
- op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
- break;
- default:
- abort();
- }
- code(op, to, from, NULL);
- return from;
-}
-
-static Node *
-field(Node *np, int islhs)
-{
- Node *tmp, *addr;
- TUINT offset = np->right->u.sym->u.off;
-
- addr = rhs(np->left);
- tmp = node(OADD);
- tmp->type = ptrtype;
- tmp->left = addr;
- tmp->right = constnode(NULL, offset, &ptrtype);
- addr = rhs(tmp);
-
- if (!islhs)
- addr = load(&np->type, addr);
- return addr;
-}
-
-static Node *
-lhs(Node *np)
-{
- switch (np->op) {
- case OREG:
- case OMEM:
- case OAUTO:
- return np;
- case OPTR:
- return rhs(np->left);
- case OFIELD:
- return field(np, 1);
- default:
- abort();
- }
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
- Node *l = np->left, *r = np->right;
- Node ret, ifyes, ifno;
- Symbol *label;
-
- switch (np->op) {
- case ONEG:
- bool(l, false, true);
- break;
- case OAND:
- label = newlabel();
- bool(l, label, false);
- setlabel(label);
- bool(r, true, false);
- break;
- case OOR:
- label = newlabel();
- bool(l, true, label);
- setlabel(label);
- bool(r, true, false);
- break;
- default:
- label2node(&ifyes, true);
- label2node(&ifno, false);
- code(ASBRANCH, rhs(np), &ifyes, &ifno);
- break;
- }
-}
-
-static Node *
-ternary(Node *np)
-{
- Node ifyes, ifno, phi, *colon, *tmp;
-
- tmp = tmpnode(&np->type);
- label2node(&ifyes, NULL);
- label2node(&ifno, NULL);
- label2node(&phi, NULL);
-
- colon = np->right;
- code(ASBRANCH, rhs(np->left), &ifyes, &ifno);
-
- setlabel(ifyes.u.sym);
- copy(&tmp->type, tmp, rhs(colon->left));
- code(ASJMP, NULL, &phi, NULL);
-
- setlabel(ifno.u.sym);
- copy(&tmp->type, tmp, rhs(colon->right));
- setlabel(phi.u.sym);
-
- return tmp;
-}
-
-static Node *
-function(void)
-{
- Node aux;
- Symbol *p;
-
- /* allocate stack space for parameters */
- for (p = locals; p; p = p->next) {
- if ((p->type.flags & PARF) == 0)
- continue;
- if ((p->type.flags & AGGRF) != 0)
- continue;
- code(ASALLOC, label2node(&aux, p), NULL, NULL);
- }
-
- /* allocate stack space for local variables) */
- for (p = locals; p; p = p->next) {
- if ((p->type.flags & PARF) != 0)
- continue;
- if (p->kind != SAUTO || p->id == TMPSYM)
- continue;
- code(ASALLOC, label2node(&aux, p), NULL, NULL);
- }
-
- /* store formal parameters in parameters */
- for (p = locals; p; p = p->next) {
- if ((p->type.flags & PARF) == 0)
- continue;
- if ((p->type.flags & AGGRF) != 0)
- continue;
- if ((p->type.flags & (ARRF|AGGRF)) == 0)
- code(ASFORM, label2node(&aux, p), NULL, NULL);
- }
- return NULL;
-}
-
-static void
-swtch_if(Node *idx)
-{
- Node aux1, aux2, *np;
- Symbol *deflabel = NULL;
-
- for (;;) {
- np = delstmt();
- setlabel(np->label);
-
- switch (np->op) {
- case OESWITCH:
- if (!deflabel)
- deflabel = np->u.sym;
- aux1.op = OJMP;
- aux1.label = NULL;
- aux1.u.sym = deflabel;
- cgen(&aux1);
- return;
- case OCASE:
- aux1 = *np;
- aux1.op = OBRANCH;
- aux1.label = NULL;
- aux1.left = &aux2;
-
- aux2.op = OEQ;
- aux2.type = idx->type;
- aux2.left = np->left;
- aux2.right = idx;
-
- cgen(&aux1);
- break;
- case ODEFAULT:
- deflabel = np->u.sym;
- break;
- default:
- abort();
- }
- }
-}
-
-static int
-assignop(Type *tp)
-{
- int flags = tp->flags;
-
- if (flags & (AGGRF|FUNF|ARRF))
- return ASSTM;
-
- switch (tp->size) {
- case 1:
- return ASSTB;
- case 2:
- return ASSTH;
- case 4:
- return (tp->flags & FLOATF) ? ASSTS : ASSTW;
- case 8:
- return (tp->flags & FLOATF) ? ASSTD : ASSTL;
- default:
- abort();
- }
-}
-
-static void
-rhs_rhs(Node **lp, Node **rp)
-{
- Node *l = *lp, *r = *rp;
-
- if (l->complex >= r->complex) {
- l = rhs(l);
- r = rhs(r);
- } else {
- r = rhs(r);
- l = rhs(l);
- }
-
- *lp = l, *rp = r;
-}
-
-static void
-lhs_rhs(Node **lp, Node **rp)
-{
- Node *l = *lp, *r = *rp;
-
- if (l->complex >= r->complex) {
- l = lhs(l);
- r = rhs(r);
- } else {
- r = rhs(r);
- l = lhs(l);
- }
-
- *lp = l, *rp = r;
-}
-
-static Node *
-assign(Node *np)
-{
- Node *ret, aux;
- Node *l = np->left, *r = np->right;
- int op;
-
- switch (np->u.subop) {
- break;
- case OINC:
- op = OADD;
- goto post_oper;
- case ODEC:
- op = OSUB;
- post_oper:
- lhs_rhs(&l, &r);
- ret = load(&l->type, l);
- aux.op = op;
- aux.left = ret;
- aux.right = r;
- aux.type = np->type;
- r = rhs(sethi(&aux));
- break;
- default:
- /* assign abbreviation */
- assert(l->type.size == r->type.size);
- if (r->type.size < 4) {
- lhs_rhs(&l, &r);
- aux.op = np->u.subop;
- aux.left = load(&r->type, l);
- aux.right = r;
- aux.type = int32type;
- aux.address = np->address;
- ret = r = sethi(rhs(&aux));
- break;
- }
-
- aux.op = np->u.subop;
- aux.left = l;
- aux.right = r;
- aux.type = np->type;
- aux.address = np->address;
- r = sethi(&aux);
- case 0:
- lhs_rhs(&l, &r);
- ret = r;
- break;
- }
-
- code(assignop(&np->type), l, r, NULL);
- return ret;
-}
-
-static Node *
-rhs(Node *np)
-{
- Node *tmp, aux1, aux2;
- Node *phi, *l = np->left, *r = np->right;
- Type *tp;
- int sign, size, isfloat, op;
- Symbol *true, *false;
-
- tp = &np->type;
-
- switch (np->op) {
- case OBFUN:
- return function();
- case ONOP:
- case OBLOOP:
- case OELOOP:
- case OEFUN:
- return NULL;
- case OTMP:
- case OCONST:
- return np;
- case OMEM:
- case OREG:
- case OAUTO:
- return load(tp, np);
- case ONEG:
- case OAND:
- case OOR:
- true = newlabel();
- false = newlabel();
- phi = label2node(&aux1, NULL);
- tmp = tmpnode(&int32type);
-
- bool(np, true, false);
-
- setlabel(true);
- code(ASCOPYW, tmp, constnode(&aux2, 1, &int32type), NULL);
- code(ASJMP, NULL, phi, NULL);
-
- setlabel(false);
- code(ASCOPYW, tmp, constnode(&aux2, 0, &int32type), NULL);
-
- setlabel(phi->u.sym);
- return tmp;
- case OMOD:
- case OSHL:
- case OBAND:
- case OBOR:
- case OBXOR:
- case OSHR:
- assert(tp->flags & INTF);
- case ODIV:
- case OLT:
- case OGT:
- case OLE:
- case OGE:
- case OADD:
- case OSUB:
- case OMUL:
- case OEQ:
- case ONE:
- assert(tp->size == 4 || tp->size == 8);
-
- sign = (tp->flags & SIGNF) == 0;
- size = tp->size == 8;
- isfloat = (tp->flags & FLOATF) != 0;
- op = opbin[isfloat][size][np->op][sign];
- rhs_rhs(&l, &r);
- tmp = tmpnode(tp);
- code(op, tmp, l, r);
- return tmp;
- case OCALL:
- case OCALLE:
- if (l->op == OPTR)
- l = rhs(l);
- return call(np, l);
- case OCAST:
- return cast(tp, rhs(l));
- case OASSIG:
- return assign(np);
- case OASK:
- return ternary(np);
- case OCOMMA:
- rhs(l);
- return rhs(r);
- case OPTR:
- return load(tp, rhs(l));
- case OADDR:
- l = lhs(l);
- l->type = *tp;
- l->type.flags |= PTRF;
- return l;
- case OFIELD:
- return field(np, 0);
- case OBUILTIN:
- switch (np->u.subop) {
- case BVA_START:
- l = rhs(l);
- code(ASVSTAR, NULL, l, NULL);
- case BVA_END:
- return NULL;
- case BVA_ARG:
- l = rhs(l);
- tmp = tmpnode(tp);
- code(ASVARG, tmp, l, NULL);
- return tmp;
- default:
- abort();
- }
- default:
- abort();
- }
- abort();
-}
-
-Node *
-cgen(Node *np)
-{
- Node aux, *p, *next;
-
- setlabel(np->label);
- switch (np->op) {
- case OJMP:
- label2node(&aux, np->u.sym);
- code(ASJMP, NULL, &aux, NULL);
- break;
- case OBRANCH:
- next = np->next;
- if (!next->label)
- next->label = newlabel();
- bool(np->left, np->u.sym, next->label);
- break;
- case ORET:
- p = (np->left) ? rhs(np->left) : NULL;
- code(ASRET, NULL, p, NULL);
- break;
- case OBSWITCH:
- p = rhs(np->left);
- swtch_if(p);
- break;
- default:
- rhs(np);
- break;
- }
- return NULL;
-}
diff --git a/src/cmd/scc-cc/cc2/target/qbe/code.c b/src/cmd/scc-cc/cc2/target/qbe/code.c
@@ -1,605 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-#define ADDR_LEN (INTIDENTSIZ+64)
-
-static void binary(void), unary(void), store(void), jmp(void), ret(void),
- branch(void), call(void), ecall(void), param(void),
- asalloc(void), form2local(void), blit(void), vastart(void),
- vaarg(void);
-
-static struct opdata {
- void (*fun)(void);
- char *txt;
- char letter;
-} optbl [] = {
- [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'},
- [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'},
- [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'},
- [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'},
- [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'},
- [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'},
- [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'},
- [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'},
- [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'},
-
- [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'},
- [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'},
- [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'},
- [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'},
- [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'},
- [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'},
-
- [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'},
- [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'},
- [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'},
- [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'},
- [ASSTM] = {.fun = blit},
- [ASSTS] = {.fun = store, .txt = "store", .letter = 's'},
- [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'},
-
- [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'},
- [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'},
- [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'},
- [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'},
- [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'},
- [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'},
- [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'},
- [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'},
- [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'},
- [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'},
- [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'},
- [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'},
- [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'},
- [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'},
- [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'},
- [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'},
- [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'},
- [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'},
- [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'},
- [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'},
- [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'},
- [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'},
- [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'},
-
- [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'},
- [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'},
- [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'},
- [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'},
- [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'},
- [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'},
- [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'},
- [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'},
- [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'},
- [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'},
- [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'},
- [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'},
- [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'},
- [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'},
- [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'},
- [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'},
- [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'},
- [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'},
- [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'},
- [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'},
- [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'},
- [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'},
- [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'},
-
- [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'},
- [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'},
- [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'},
- [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'},
- [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'},
- [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'},
- [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'},
- [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'},
- [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'},
- [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'},
-
- [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'},
- [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'},
- [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'},
- [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'},
- [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'},
- [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'},
- [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'},
- [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'},
- [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'},
- [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'},
-
- [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'},
- [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'},
- [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'},
- [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'},
- [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'},
- [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'},
- [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'},
- [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'},
- [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'},
- [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'},
-
- [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
- [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'},
- [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
- [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'},
- [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
- [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'},
- [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
- [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'},
-
- [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
- [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'},
- [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
- [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'},
- [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
- [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'},
- [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
- [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'},
-
- [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
- [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
-
- [ASBRANCH] = {.fun = branch},
- [ASJMP] = {.fun = jmp},
- [ASRET] = {.fun = ret},
- [ASCALL] = {.fun = call},
- [ASCALLE] = {.fun = ecall, .txt = ")"},
- [ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
- [ASPAR] = {.fun = param, .txt = "%s %s, "},
- [ASPARE] = {.fun = param, .txt = "%s %s"},
- [ASALLOC] = {.fun = asalloc},
- [ASFORM] = {.fun = form2local},
-
- [ASVSTAR] = {.fun = vastart},
- [ASVARG] = {.fun = vaarg},
-};
-
-static char buff[ADDR_LEN];
-/*
- * : is for user-defined Aggregate Types
- * $ is for globals (represented by a pointer)
- * % is for function-scope temporaries
- * @ is for block labels
- */
-static char
-sigil(Symbol *sym)
-{
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- case SLOCAL:
- return '$';
- case SAUTO:
- case STMP:
- return '%';
- case SLABEL:
- return '@';
- default:
- abort();
- }
-}
-
-static char *
-symname(Symbol *sym)
-{
- char c = sigil(sym);
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- sprintf(buff, "%c%s", c, sym->name);
- return buff;
- case SLOCAL:
- case SPRIV:
- case SAUTO:
- sprintf(buff, "%c%s.L%u", c, sym->name, sym->id);
- return buff;
- default:
- abort();
- }
- }
- sprintf(buff, "%c.L%u", c, sym->numid);
-
- return buff;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- pprint(np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-
-static char *
-size2asm(Type *tp)
-{
- static char spec[ADDR_LEN];
-
- if (tp->flags & STRF) {
- return "b";
- } else if (tp->flags & INTF) {
- switch (tp->size) {
- case 1:
- return "b";
- case 2:
- return "h";
- case 4:
- return "w";
- case 8:
- return "l";
- }
- } else if (tp->flags & FLOATF) {
- if (tp->size == 4)
- return "s";
- else if (tp->size == 8)
- return "d";
- }
-
- abort();
-}
-
-void
-defglobal(Symbol *sym)
-{
- Type *tp = &sym->type;
-
- if (sym->kind == SEXTRN)
- return;
- if (sym->kind == SGLOB)
- fputs("export ", stdout);
- if ((tp->flags & INITF) == 0)
- fputs("common ", stdout);
-
- printf("data %s = align %d {\n",
- symname(sym),
- tp->align);
- if ((tp->flags & INITF) == 0)
- printf("\tz\t%lu\n}\n", tp->size);
-}
-
-void
-defpar(Symbol *sym)
-{
- if (sym->kind == SREG)
- sym->kind = SAUTO;
- sym->type.flags |= PARF;
-}
-
-void
-defvar(Symbol *sym)
-{
- if (sym->kind == SREG)
- sym->kind = SAUTO;
-}
-
-void
-data(Node *np)
-{
- printf("\t%s\t", size2asm(&np->type));
- emittree(np);
- putchar(',');
- putchar('\n');
-}
-
-static char *
-size2stack(Type *tp)
-{
- static char spec[ADDR_LEN];
-
- if (tp->flags & INTF) {
- switch (tp->size) {
- case 1:
- case 2:
- case 4:
- return "w";
- case 8:
- return "l";
- }
- } else if (tp->flags & FLOATF) {
- if (tp->size == 4)
- return "s";
- else if (tp->size == 8)
- return "d";
- } else if (tp->flags & (ARRF|AGGRF)) {
- sprintf(spec, ":.%u", tp->id);
- return spec;
- } else if (tp->size == 0) {
- return "w";
- }
- abort();
-}
-
-void
-deftype(Type *tp)
-{
- printf("type :.%u = align %d { %lu }\n",
- tp->id, tp->align, tp->size);
-}
-
-void
-writeout(void)
-{
- Symbol *p;
- Type *tp;
- char *sep;
- int haslabel = 0;
-
- if (!curfun)
- return;
- if (curfun->kind == SGLOB)
- fputs("export ", stdout);
- printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
-
- /* declare formal parameters */
- sep = "";
- for (p = locals; p; p = p->next) {
- if ((p->type.flags & PARF) == 0)
- continue;
- printf("%s%s %s%s",
- sep, size2stack(&p->type),
- symname(p),
- (p->type.flags & AGGRF) ? "" : ".val");
- sep = ",";
- }
- printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
-
- /* emit assembler instructions */
- for (pc = prog; pc; pc = pc->next) {
- if (pc->label) {
- haslabel = 1;
- printf("%s\n", symname(pc->label));
- }
- if (pc->op == ASLABEL)
- continue;
- if (pc->flags&BBENTRY && !haslabel)
- printf("%s\n", symname(newlabel()));
- (*optbl[pc->op].fun)();
- if (!pc->label)
- haslabel = 0;
- }
-
- puts("}");
-}
-
-static char *
-addr2txt(Addr *a)
-{
- switch (a->kind) {
- case SCONST:
- sprintf(buff, "%llu", (unsigned long long) a->u.i);
- return buff;
- case SAUTO:
- case SLABEL:
- case STMP:
- case SGLOB:
- case SEXTRN:
- case SPRIV:
- case SLOCAL:
- return symname(a->u.sym);
- default:
- abort();
- }
-}
-
-static void
-binary(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from1, addr2txt(&pc->from1));
- strcpy(from2, addr2txt(&pc->from2));
- printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
-}
-
-static void
-blit(void)
-{
- Type *tp = &pc->to.u.sym->type;
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size);
-}
-
-static void
-store(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
-}
-
-static void
-unary(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
-}
-
-static void
-call(void)
-{
- char to[ADDR_LEN], from[ADDR_LEN];
- Symbol *sym = pc->to.u.sym;
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t%s =%s\tcall\t%s(",
- to, size2stack(&sym->type), from);
-}
-
-static void
-param(void)
-{
- Symbol *sym = pc->from2.u.sym;
-
- printf(optbl[pc->op].txt,
- size2stack(&sym->type), addr2txt(&pc->from1));
-}
-
-static void
-ecall(void)
-{
- struct opdata *p = &optbl[pc->op];
-
- puts(p->txt);
-}
-
-static void
-ret(void)
-{
- if (pc->from1.kind == SNONE)
- puts("\t\tret");
- else
- printf("\t\tret\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-jmp(void)
-{
- printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-branch(void)
-{
- char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from1, addr2txt(&pc->from1));
- strcpy(from2, addr2txt(&pc->from2));
- printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
-}
-
-static void
-vastart(void)
-{
- printf("\t\tvastart %s\n", addr2txt(&pc->from1));
-}
-
-static void
-vaarg(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
-}
-
-static void
-asalloc(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- extern Type ptrtype;
-
- printf("\t%s =%s\talloc%lu\t%lu\n",
- symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
-}
-
-static void
-form2local(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- char *name = symname(sym);
-
- printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
-}
-
-void
-endinit(void)
-{
- puts("}");
-}
-
-void
-getbblocks(void)
-{
- Inst *i;
-
- if (!prog)
- return;
-
- prog->flags |= BBENTRY;
- for (pc = prog; pc; pc = pc->next) {
- switch (pc->op) {
- case ASBRANCH:
- i = pc->from2.u.sym->u.inst;
- i->flags |= BBENTRY;
- case ASJMP:
- i = pc->from1.u.sym->u.inst;
- i->flags |= BBENTRY;
- case ASRET:
- if (pc->next)
- pc->next->flags |= BBENTRY;
- break;
- }
- }
-}
diff --git a/src/cmd/scc-cc/cc2/target/qbe/optm.c b/src/cmd/scc-cc/cc2/target/qbe/optm.c
@@ -1,56 +0,0 @@
-#include <stddef.h>
-
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- int op = np->op;
- Node *p, *dst, *next = np->next;
- Symbol *sym, *osym;
-
- switch (op) {
- case OEFUN:
- /*
- * In QBE we need at the end of a basic block
- * a jump, so we have to ensure that the last
- * statement of the function is a ret, a jmp
- * or a branch. In the same way, QBE does
- * not accept labels at the end of a function
- * (ONOP is used for labels) so we have to add
- * a ret there, and in the case of branches
- * we need a label for the next statement
- */
- op = (np->prev) ? np->prev->op : 0;
- if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
- addstmt(node(ORET), KEEPCUR);
- break;
- case OBRANCH:
- if (!next->label) {
- sym = getsym(TMPSYM);
- sym->kind = SLABEL;
- next->label = sym;
- }
- case OJMP:
- for (;;) {
- dst = np->u.sym->u.stmt;
- if (dst->op != OJMP)
- break;
- np->u.sym = dst->u.sym;
- }
- for (p = np->next; p; p = p->next) {
- if (p == dst)
- return NULL;
- if (p->op == ONOP ||
- p->op == OBLOOP ||
- p->op == OELOOP) {
- continue;
- }
- break;
- }
- break;
- }
- return np;
-}
diff --git a/src/cmd/scc-cc/cc2/target/qbe_amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/qbe_amd64-sysv/target.mk
@@ -1,9 +0,0 @@
-OBJ-qbe_amd64-sysv = $(OBJS) \
- target/qbe/cgen.o \
- target/qbe/optm.o \
- target/qbe/code.o \
- target/amd64-sysv/types.o
-
-cc2-qbe_amd64-sysv: $(LIBSCC) $(OBJ-qbe_amd64-sysv)
- $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@
- cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/qbe_arm64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/qbe_arm64-sysv/target.mk
@@ -1,9 +0,0 @@
-OBJ-qbe_arm64-sysv = $(OBJS) \
- target/qbe/cgen.o \
- target/qbe/optm.o \
- target/qbe/code.o \
- target/arm64-sysv/types.o \
-
-cc2-qbe_arm64-sysv: $(LIBSCC) $(OBJ-qbe_arm64-sysv)
- $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_arm64-sysv) -lscc $(PROJ_LDLIBS) -o $@
- cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/cgen.c b/src/cmd/scc-cc/cc2/target/z80-scc/cgen.c
@@ -1,159 +0,0 @@
-#include <stdlib.h>
-
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-static void
-swtch(Node *idx)
-{
-}
-
-static Node *
-rhs(Node *np, Node *ret)
-{
-}
-
-static Node *
-field(Node *np, Node *ret, int islhs)
-{
-}
-
-static Node *
-lhs(Node *np, Node *new)
-{
- switch (np->op) {
- case OMEM:
- case OAUTO:
- *new = *np;
- return new;
- case OPTR:
- return rhs(np->left, new);
- case OFIELD:
- return field(np, new, 1);
- default:
- abort();
- }
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
- Node *l = np->left, *r = np->right;
- Node ret, ifyes, ifno;
- Symbol *label;
-
- switch (np->op) {
- case ONEG:
- bool(l, false, true);
- break;
- case OAND:
- label = newlabel();
- bool(l, label, false);
- setlabel(label);
- bool(r, true, false);
- break;
- case OOR:
- label = newlabel();
- bool(l, true, label);
- setlabel(label);
- bool(r, true, false);
- break;
- default:
- label2node(&ifyes, true);
- label2node(&ifno, false);
- code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
- break;
- }
-}
-
-Node *
-cgen(Node *np)
-{
- Node aux, *p, *next;
-
- setlabel(np->label);
- switch (np->op) {
- case OJMP:
- label2node(&aux, np->u.sym);
- code(ASJMP, NULL, &aux, NULL);
- break;
- case OBRANCH:
- next = np->next;
- if (!next->label)
- next->label = newlabel();
- bool(np->left, np->u.sym, next->label);
- break;
- case ORET:
- p = np->left;
- if (p)
- p = rhs(np->left, &aux);
- code(ASRET, NULL, p, NULL);
- break;
- case OBSWITCH:
- swtch(rhs(np->left, &aux));
- break;
- default:
- rhs(np, &aux);
- break;
- }
- return NULL;
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REG => 13 reg
- * STATIC => 12 (value)
- * CONST => 20 $value
- */
-Node *
-sethi(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->address = 0;
- lp = np->left;
- rp = np->right;
- switch (np->op) {
- case OAUTO:
- np->address = 11;
- break;
- case OREG:
- np->address = 13;
- break;
- case OMEM:
- np->address = 12;
- break;
- case OCONST:
- np->address = 20;
- break;
- default:
- sethi(lp);
- sethi(rp);
- break;
- }
-
- if (np->address > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
- return np;
-}
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/code.c b/src/cmd/scc-cc/cc2/target/z80-scc/code.c
@@ -1,232 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-static unsigned long offpar, offvar;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\tCSEG\n",
- [DATASEG] = "\tDSEG\n",
- [BSSSEG] = "\tASEG\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SGLOB:
- case SEXTRN:
- snprintf(name, sizeof(name), "_%s", sym->name);
- return name;
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".%d", sym->numid);
-
- return name;
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\tEXTRN\t%s\n", name);
- return;
- case SGLOB:
- printf("\tPUBLIC\t%s\n", name);
- break;
- }
-
- printf("%s:\n", name);
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- pprint(np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- /*
- * In z80 we can ignore the alignment
- */
- if (tp->flags & STRF) {
- s = "\tDB\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\tDB\t";
- break;
- case 2:
- s = "\tDW\t";
- break;
- case 4:
- s = "\tDD\t";
- break;
- default:
- s = "\tDS\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-void
-newfun()
-{
- offpar = offvar = 0;
-}
-
-void
-defpar(Symbol *sym)
-{
- unsigned long align, size;
-
- if (sym->kind != SREG && sym->kind != SAUTO)
- return;
- align = sym->type.align;
- size = sym->type.size;
-
- offpar -= align-1 & ~align;
- sym->u.off = offpar;
- offpar -= size;
- sym->kind = SAUTO;
-}
-
-void
-defvar(Symbol *sym)
-{
- unsigned long align, size;
-
- if (sym->kind != SREG && sym->kind != SAUTO)
- return;
- align = sym->type.align;
- size = sym->type.size;
-
- offvar += align-1 & ~align;
- sym->u.off = offvar;
- offvar += size;
- sym->kind = SAUTO;
-}
-
-void
-deftype(Type *tp)
-{
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/optm.c b/src/cmd/scc-cc/cc2/target/z80-scc/optm.c
@@ -1,9 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/target.mk b/src/cmd/scc-cc/cc2/target/z80-scc/target.mk
@@ -1,9 +0,0 @@
-OBJ-z80-scc = $(OBJS) \
- target/z80-scc/cgen.o \
- target/z80-scc/optm.o \
- target/z80-scc/code.o \
- target/z80-scc/types.o \
-
-cc2-z80-scc: $(LIBSCC) $(OBJ-z80-scc)
- $(CC) $(PROJ_LDFLAGS) $(OBJ-z80-scc) -lscc $(PROJ_LDLIBS) -o $@
- cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/types.c b/src/cmd/scc-cc/cc2/target/z80-scc/types.c
@@ -1,92 +0,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 1
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 1
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 1
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 1
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 1
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 1
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 2,
- .align = 1
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-Type arg_type = {
- .size = 2,
- .align = 1
-};
diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/arch.h b/src/cmd/scc-cc/cc2/z80-scc/arch.h
diff --git a/src/cmd/scc-cc/cc2/z80-scc/cgen.c b/src/cmd/scc-cc/cc2/z80-scc/cgen.c
@@ -0,0 +1,159 @@
+#include <stdlib.h>
+
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+static void
+swtch(Node *idx)
+{
+}
+
+static Node *
+rhs(Node *np, Node *ret)
+{
+}
+
+static Node *
+field(Node *np, Node *ret, int islhs)
+{
+}
+
+static Node *
+lhs(Node *np, Node *new)
+{
+ switch (np->op) {
+ case OMEM:
+ case OAUTO:
+ *new = *np;
+ return new;
+ case OPTR:
+ return rhs(np->left, new);
+ case OFIELD:
+ return field(np, new, 1);
+ default:
+ abort();
+ }
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+ Node *l = np->left, *r = np->right;
+ Node ret, ifyes, ifno;
+ Symbol *label;
+
+ switch (np->op) {
+ case ONEG:
+ bool(l, false, true);
+ break;
+ case OAND:
+ label = newlabel();
+ bool(l, label, false);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ case OOR:
+ label = newlabel();
+ bool(l, true, label);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ default:
+ label2node(&ifyes, true);
+ label2node(&ifno, false);
+ code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
+ break;
+ }
+}
+
+Node *
+cgen(Node *np)
+{
+ Node aux, *p, *next;
+
+ setlabel(np->label);
+ switch (np->op) {
+ case OJMP:
+ label2node(&aux, np->u.sym);
+ code(ASJMP, NULL, &aux, NULL);
+ break;
+ case OBRANCH:
+ next = np->next;
+ if (!next->label)
+ next->label = newlabel();
+ bool(np->left, np->u.sym, next->label);
+ break;
+ case ORET:
+ p = np->left;
+ if (p)
+ p = rhs(np->left, &aux);
+ code(ASRET, NULL, p, NULL);
+ break;
+ case OBSWITCH:
+ swtch(rhs(np->left, &aux));
+ break;
+ default:
+ rhs(np, &aux);
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ * AUTO => 11 value+fp
+ * REG => 13 reg
+ * STATIC => 12 (value)
+ * CONST => 20 $value
+ */
+Node *
+sethi(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->address = 0;
+ lp = np->left;
+ rp = np->right;
+ switch (np->op) {
+ case OAUTO:
+ np->address = 11;
+ break;
+ case OREG:
+ np->address = 13;
+ break;
+ case OMEM:
+ np->address = 12;
+ break;
+ case OCONST:
+ np->address = 20;
+ break;
+ default:
+ sethi(lp);
+ sethi(rp);
+ break;
+ }
+
+ if (np->address > 10)
+ return np;
+ if (lp)
+ np->complex = lp->complex;
+ if (rp) {
+ int d = np->complex - rp->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = rp->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+ return np;
+}
diff --git a/src/cmd/scc-cc/cc2/z80-scc/code.c b/src/cmd/scc-cc/cc2/z80-scc/code.c
@@ -0,0 +1,232 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+static unsigned long offpar, offvar;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\tCSEG\n",
+ [DATASEG] = "\tDSEG\n",
+ [BSSSEG] = "\tASEG\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SGLOB:
+ case SEXTRN:
+ snprintf(name, sizeof(name), "_%s", sym->name);
+ return name;
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".%d", sym->numid);
+
+ return name;
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\tEXTRN\t%s\n", name);
+ return;
+ case SGLOB:
+ printf("\tPUBLIC\t%s\n", name);
+ break;
+ }
+
+ printf("%s:\n", name);
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ pprint(np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ /*
+ * In z80 we can ignore the alignment
+ */
+ if (tp->flags & STRF) {
+ s = "\tDB\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\tDB\t";
+ break;
+ case 2:
+ s = "\tDW\t";
+ break;
+ case 4:
+ s = "\tDD\t";
+ break;
+ default:
+ s = "\tDS\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+void
+newfun()
+{
+ offpar = offvar = 0;
+}
+
+void
+defpar(Symbol *sym)
+{
+ unsigned long align, size;
+
+ if (sym->kind != SREG && sym->kind != SAUTO)
+ return;
+ align = sym->type.align;
+ size = sym->type.size;
+
+ offpar -= align-1 & ~align;
+ sym->u.off = offpar;
+ offpar -= size;
+ sym->kind = SAUTO;
+}
+
+void
+defvar(Symbol *sym)
+{
+ unsigned long align, size;
+
+ if (sym->kind != SREG && sym->kind != SAUTO)
+ return;
+ align = sym->type.align;
+ size = sym->type.size;
+
+ offvar += align-1 & ~align;
+ sym->u.off = offvar;
+ offvar += size;
+ sym->kind = SAUTO;
+}
+
+void
+deftype(Type *tp)
+{
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
diff --git a/src/cmd/scc-cc/cc2/z80-scc/optm.c b/src/cmd/scc-cc/cc2/z80-scc/optm.c
@@ -0,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
diff --git a/src/cmd/scc-cc/cc2/z80-scc/target.mk b/src/cmd/scc-cc/cc2/z80-scc/target.mk
@@ -0,0 +1,9 @@
+OBJ-z80-scc = $(OBJS) \
+ z80-scc/cgen.o \
+ z80-scc/optm.o \
+ z80-scc/code.o \
+ z80-scc/types.o \
+
+cc2-z80-scc: $(LIBSCC) $(OBJ-z80-scc)
+ $(CC) $(PROJ_LDFLAGS) $(OBJ-z80-scc) -lscc $(PROJ_LDLIBS) -o $@
+ cp $@ $(LIBEXEC)/scc
diff --git a/src/cmd/scc-cc/cc2/z80-scc/types.c b/src/cmd/scc-cc/cc2/z80-scc/types.c
@@ -0,0 +1,92 @@
+#include <scc/scc.h>
+
+#include "../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 1
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 1
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 1
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 1
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+Type arg_type = {
+ .size = 2,
+ .align = 1
+};