commit ad4a862a25648e29e4fe409a555878178b617360 parent 6f59bc4250f2f8ccd693f5184f1f002561be532c Author: Roberto E. Vargas Caballero <k0ga@shike2.com> Date: Wed, 23 Oct 2024 16:16:02 +0200 build/as: Flat dir tree This is a previous step to move forward a recursive Makefile. Diffstat:
47 files changed, 1753 insertions(+), 1835 deletions(-)
diff --git a/src/cmd/scc-as/Makefile b/src/cmd/scc-as/Makefile @@ -39,13 +39,12 @@ lexh: lexh.o genhash.o $(HOSTCC) -o $@ lexh.o genhash.o clean: - rm -f target/*/*.o target/*/*tbl.c lexh + rm -f */*.o */*tbl.c lexh rm -f as -include target/powerpc/powerpc64.mk -include target/powerpc/powerpc.mk -include target/x86/amd64.mk -include target/x86/i386.mk -include target/x86/i286.mk -include target/x80/z80.mk -include deps.mk +include powerpc/powerpc64.mk +include powerpc/powerpc.mk +include x86/amd64.mk +include x86/i386.mk +include x86/i286.mk +include x80/z80.mk diff --git a/src/cmd/scc-as/deps.mk b/src/cmd/scc-as/deps.mk @@ -1,81 +0,0 @@ -#deps -as.o: $(INCDIR)/bits/scc/arg.h -as.o: $(INCDIR)/bits/scc/config.h -as.o: $(INCDIR)/bits/scc/scc.h -expr.o: $(INCDIR)/bits/scc/mach.h -expr.o: $(INCDIR)/bits/scc/scc.h -expr.o: as.h -ins.o: $(INCDIR)/bits/scc/mach.h -ins.o: $(INCDIR)/bits/scc/scc.h -ins.o: as.h -main.o: $(INCDIR)/bits/scc/arg.h -main.o: $(INCDIR)/bits/scc/mach.h -main.o: $(INCDIR)/bits/scc/scc.h -main.o: as.h -parser.o: $(INCDIR)/bits/scc/cstd.h -parser.o: $(INCDIR)/bits/scc/mach.h -parser.o: $(INCDIR)/bits/scc/scc.h -parser.o: as.h -symbol.o: $(INCDIR)/bits/scc/cstd.h -symbol.o: $(INCDIR)/bits/scc/mach.h -symbol.o: $(INCDIR)/bits/scc/scc.h -symbol.o: as.h -target/powerpc/ins.o: $(INCDIR)/bits/scc/mach.h -target/powerpc/ins.o: $(INCDIR)/bits/scc/scc.h -target/powerpc/ins.o: target/powerpc/../../as.h -target/powerpc/ins.o: target/powerpc/proc.h -target/powerpc/powerpc.o: $(INCDIR)/bits/scc/mach.h -target/powerpc/powerpc.o: $(INCDIR)/bits/scc/scc.h -target/powerpc/powerpc.o: target/powerpc/../../as.h -target/powerpc/powerpc.o: target/powerpc/proc.h -target/powerpc/powerpc64.o: $(INCDIR)/bits/scc/mach.h -target/powerpc/powerpc64.o: $(INCDIR)/bits/scc/scc.h -target/powerpc/powerpc64.o: target/powerpc/../../as.h -target/powerpc/powerpc64.o: target/powerpc/proc.h -target/powerpc/powerpc64tbl.o: $(INCDIR)/bits/scc/mach.h -target/powerpc/powerpc64tbl.o: $(INCDIR)/bits/scc/scc.h -target/powerpc/powerpc64tbl.o: target/powerpc/../../as.h -target/powerpc/powerpc64tbl.o: target/powerpc/../powerpc/proc.h -target/powerpc/powerpctbl.o: $(INCDIR)/bits/scc/mach.h -target/powerpc/powerpctbl.o: $(INCDIR)/bits/scc/scc.h -target/powerpc/powerpctbl.o: target/powerpc/../../as.h -target/powerpc/powerpctbl.o: target/powerpc/../powerpc/proc.h -target/x80/ins.o: $(INCDIR)/bits/scc/mach.h -target/x80/ins.o: $(INCDIR)/bits/scc/scc.h -target/x80/ins.o: target/x80/../../as.h -target/x80/ins.o: target/x80/proc.h -target/x80/z80.o: $(INCDIR)/bits/scc/mach.h -target/x80/z80.o: $(INCDIR)/bits/scc/scc.h -target/x80/z80.o: target/x80/../../as.h -target/x80/z80.o: target/x80/../x80/proc.h -target/x80/z80tbl.o: $(INCDIR)/bits/scc/mach.h -target/x80/z80tbl.o: $(INCDIR)/bits/scc/scc.h -target/x80/z80tbl.o: target/x80/../../as.h -target/x80/z80tbl.o: target/x80/../x80/proc.h -target/x86/amd64.o: $(INCDIR)/bits/scc/mach.h -target/x86/amd64.o: $(INCDIR)/bits/scc/scc.h -target/x86/amd64.o: target/x86/../../as.h -target/x86/amd64tbl.o: $(INCDIR)/bits/scc/mach.h -target/x86/amd64tbl.o: $(INCDIR)/bits/scc/scc.h -target/x86/amd64tbl.o: target/x86/../../as.h -target/x86/amd64tbl.o: target/x86/../x86/proc.h -target/x86/i286.o: $(INCDIR)/bits/scc/mach.h -target/x86/i286.o: $(INCDIR)/bits/scc/scc.h -target/x86/i286.o: target/x86/../../as.h -target/x86/i286.o: target/x86/../x86/proc.h -target/x86/i286tbl.o: $(INCDIR)/bits/scc/mach.h -target/x86/i286tbl.o: $(INCDIR)/bits/scc/scc.h -target/x86/i286tbl.o: target/x86/../../as.h -target/x86/i286tbl.o: target/x86/../x86/proc.h -target/x86/i386.o: $(INCDIR)/bits/scc/mach.h -target/x86/i386.o: $(INCDIR)/bits/scc/scc.h -target/x86/i386.o: target/x86/../../as.h -target/x86/i386.o: target/x86/../x86/proc.h -target/x86/i386tbl.o: $(INCDIR)/bits/scc/mach.h -target/x86/i386tbl.o: $(INCDIR)/bits/scc/scc.h -target/x86/i386tbl.o: target/x86/../../as.h -target/x86/i386tbl.o: target/x86/../x86/proc.h -target/x86/ins.o: $(INCDIR)/bits/scc/mach.h -target/x86/ins.o: $(INCDIR)/bits/scc/scc.h -target/x86/ins.o: target/x86/../../as.h -target/x86/ins.o: target/x86/proc.h diff --git a/src/cmd/scc-as/mktbl b/src/cmd/scc-as/mktbl @@ -25,10 +25,10 @@ done echo cpu=${cpu:=z80} family=${family:=x80} -rm -f $$.c target/$family/${cpu}tbl.c +rm -f $$.c $family/${cpu}tbl.c trap "rm -f $$.c" 0 2 3 -awk '!/^$/ {print $1,NR,$2,$3,$4,$5,$6}' target/$family/ops.dat | +awk '!/^$/ {print $1,NR,$2,$3,$4,$5,$6}' $family/ops.dat | sort -k1 -k2n | LC_ALL=C awk -v cpu=`echo $cpu | tr a-z A-Z` -v family=$family -f mktbl.awk > $$.c && -mv $$.c target/$family/${cpu}tbl.c +mv $$.c $family/${cpu}tbl.c diff --git a/src/cmd/scc-as/mktbl.awk b/src/cmd/scc-as/mktbl.awk @@ -3,10 +3,10 @@ BEGIN { nvar=0 printf "#include <scc/mach.h>\n"\ "#include <scc/scc.h>\n"\ - "#include \"../../as.h\"\n"\ + "#include \"../as.h\"\n"\ "#include \"../" family "/proc.h\"\n" - rules = "target/" family "/opers.dat" + rules = family "/opers.dat" while (getline < rules > 0) { regex[++nregs] = $1 value[nregs] = $2 diff --git a/src/cmd/scc-as/target/powerpc/.gitignore b/src/cmd/scc-as/powerpc/.gitignore diff --git a/src/cmd/scc-as/powerpc/ins.c b/src/cmd/scc-as/powerpc/ins.c @@ -0,0 +1,354 @@ +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "proc.h" + +/* + * This code is derived from PowerISA_V2.06B_V2_PUBLIC document. + * All the names used in the specification are preserved in + * this code. + */ + +static int +getclass(Node *np) +{ + if (np->addr != AREG) + return 0; + + switch (np->sym->value) { + case AREG_R0: + case AREG_R1: + case AREG_R2: + case AREG_R3: + case AREG_R4: + case AREG_R5: + case AREG_R6: + case AREG_R7: + case AREG_R8: + case AREG_R9: + case AREG_R10: + case AREG_R11: + case AREG_R12: + case AREG_R13: + case AREG_R14: + case AREG_R15: + case AREG_R16: + case AREG_R17: + case AREG_R18: + case AREG_R19: + case AREG_R20: + case AREG_R21: + case AREG_R22: + case AREG_R23: + case AREG_R24: + case AREG_R25: + case AREG_R26: + case AREG_R27: + case AREG_R29: + case AREG_R30: + case AREG_R31: + return GPRSCLASS; + default: + abort(); + } +} + +int +match(Op *op, Node **args) +{ + unsigned char *p; + int arg, class, rep, opt; + Node *np; + + if (!op->args) + return args == NULL; + + opt = rep = 0; + for (p = op->args; arg = *p; ++p) { + if (rep) + --p; + if ((np = *args++) == NULL) + return (rep|opt) != 0; + + switch (arg) { + case AOPT: + opt = 1; + break; + case AREP: + rep = 1; + break; + case AREG_GPRSCLASS: + class = GPRSCLASS; + check_class: + if ((getclass(np) & class) == 0) + return 0; + break; + case AIMM2: + case AIMM5: + case AIMM8: + case AIMM16: + case AIMM32: + case AIMM64: + if (np->addr != AIMM) + return 0; + if (toobig(np, arg)) + error("overflow in immediate operand"); + break; + case ASYM: + if (np->op != IDEN) + return 0; + break; + case ADIRECT: + case ASTR: + if (np->addr != arg) + return 0; + break; + default: + abort(); + } + } + + return *args == NULL; +} + +Node * +moperand(void) +{ + abort(); +} + +static void +emit_packed(unsigned long ins) +{ + char buff[4]; + + if (endian == BIG_ENDIAN) { + buff[0] = ins >> 24; + buff[1] = ins >> 16; + buff[2] = ins >> 8; + buff[3] = ins; + } else { + buff[0] = ins; + buff[1] = ins >> 8; + buff[2] = ins >> 16; + buff[3] = ins >> 24; + } + + emit(buff, 4); +} + +void +i_form(Op *op, Node **args) +{ + unsigned long ins, opcd, li, aa, lk; + long long dst; + long long max = 1l << 23; + long long min = -(1l << 23); + + opcd = op->bytes[0]; + aa = op->bytes[1]; + lk = op->bytes[2]; + + dst = args[0]->sym->value; + if (dst & 0x3) + error("unaligned branch"); + if (aa) + dst -= getpc() - 4; + if (dst < min || dst > max) + error("out of range branch"); + + li = dst; + li >>= 2; + ins = opcd<<26 | li<<2 | aa<<1 | lk; + emit_packed(ins); +} + +void +b_form(Op *op, Node **args) +{ + unsigned long ins, opcd, bo, bi, bd, aa, lk; + long long dst; + long long max = 1l << 13; + long long min = -(1l << 13); + + opcd = op->bytes[0]; + aa = op->bytes[1]; + lk = op->bytes[2]; + + bo = args[0]->sym->value; + bi = args[1]->sym->value; + + dst = args[2]->sym->value; + if (dst & 0x3) + error("unaligned branch"); + if (aa) + dst -= getpc() - 4; + + if (dst < min || dst > max) + error("out of range branch"); + bd = dst; + bd >>= 2; + + ins = opcd<<26 | bo<<21 | bi<<16 | bd<<11 | aa<<1 | lk; + emit_packed(ins); +} + +void +sc_form(Op *op, Node **args) +{ + abort(); +} + +void +d_form(Op *op, Node **args) +{ + abort(); +} + +void +ds_form(Op *op, Node **args) +{ + abort(); +} + +void +dq_form(Op *op, Node **args) +{ + abort(); +} + +void +x_form(Op *op, Node **args) +{ + abort(); +} + +void +xl_form(Op *op, Node **args) +{ + unsigned long ins, bo, bi, bh, lk; + unsigned long opcd1, opcd2; + long long dst; + + opcd1 = op->bytes[0]; + opcd2 = op->bytes[1]<<8 | op->bytes[2]; + lk = op->bytes[3]; + + bo = args[0]->sym->value; + bi = args[1]->sym->value; + bh = args[2]->sym->value; + + ins = opcd1<<26 | bo<<21 | bi<<16 | bh<<11 | opcd2<<1 | lk; + emit_packed(ins); +} + +void +xfx_form(Op *op, Node **args) +{ + abort(); +} + +void +xlfdorm_form(Op *op, Node **args) +{ + abort(); +} + +void +xx1_form(Op *op, Node **args) +{ + abort(); +} + +void +xx2_form(Op *op, Node **args) +{ + abort(); +} + +void +xx3_form(Op *op, Node **args) +{ + abort(); +} + +void +xx4_form(Op *op, Node **args) +{ + abort(); +} + +void +xs_form(Op *op, Node **args) +{ + abort(); +} + +void +xo_form(Op *op, Node **args) +{ + abort(); +} + +void +a_form(Op *op, Node **args) +{ + abort(); +} + +void +m_form(Op *op, Node **args) +{ + abort(); +} + +void +md_form(Op *op, Node **args) +{ + abort(); +} + +void +mds_form(Op *op, Node **args) +{ + abort(); +} + +void +va_form(Op *op, Node **args) +{ + abort(); +} + +void +vc_form(Op *op, Node **args) +{ + abort(); +} + +void +vx_form(Op *op, Node **args) +{ + abort(); +} + +void +evs_form(Op *op, Node **args) +{ + abort(); +} + +void +z22_form(Op *op, Node **args) +{ + abort(); +} + +void +z23_form(Op *op, Node **args) +{ + abort(); +} diff --git a/src/cmd/scc-as/target/powerpc/opers.dat b/src/cmd/scc-as/powerpc/opers.dat diff --git a/src/cmd/scc-as/target/powerpc/ops.dat b/src/cmd/scc-as/powerpc/ops.dat diff --git a/src/cmd/scc-as/powerpc/powerpc.c b/src/cmd/scc-as/powerpc/powerpc.c @@ -0,0 +1,63 @@ +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "proc.h" + +TUINT maxaddr = 0xFFFF; +int endian = BIG_ENDIAN; +int left2right = 0; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "R0", AREG_R0, + "R1", AREG_R1, + "R2", AREG_R2, + "R3", AREG_R3, + "R4", AREG_R4, + "R5", AREG_R5, + "R6", AREG_R6, + "R7", AREG_R7, + "R8", AREG_R8, + "R9", AREG_R9, + + "R10", AREG_R10, + "R11", AREG_R11, + "R12", AREG_R12, + "R13", AREG_R13, + "R14", AREG_R14, + "R15", AREG_R15, + "R16", AREG_R16, + "R17", AREG_R17, + "R18", AREG_R18, + "R19", AREG_R19, + + "R20", AREG_R20, + "R21", AREG_R21, + "R22", AREG_R22, + "R23", AREG_R23, + "R24", AREG_R24, + "R25", AREG_R25, + "R26", AREG_R26, + "R27", AREG_R27, + "R28", AREG_R28, + "R29", AREG_R29, + "R30", AREG_R30, + "R31", AREG_R31, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/cmd/scc-as/powerpc/powerpc.mk b/src/cmd/scc-as/powerpc/powerpc.mk @@ -0,0 +1,13 @@ +POWERPC = powerpc +POWERPC_OBJ =\ + $(OBJS)\ + $(POWERPC)/powerpctbl.o\ + $(POWERPC)/powerpc.o\ + $(POWERPC)/ins.o\ + +$(POWERPC)/powerpctbl.c: $(POWERPC)/ops.dat $(POWERPC)/opers.dat lexh + ./mktbl -f powerpc -c powerpc + +as-powerpc: $(POWERPC_OBJ) + $(CC) $(PROJ_LDFLAGS) $(POWERPC_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/powerpc/powerpc64.c b/src/cmd/scc-as/powerpc/powerpc64.c @@ -0,0 +1,63 @@ +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "proc.h" + +TUINT maxaddr = 0xFFFF; +int endian = BIG_ENDIAN; +int left2right = 0; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "R0", AREG_R0, + "R1", AREG_R1, + "R2", AREG_R2, + "R3", AREG_R3, + "R4", AREG_R4, + "R5", AREG_R5, + "R6", AREG_R6, + "R7", AREG_R7, + "R8", AREG_R8, + "R9", AREG_R9, + + "R10", AREG_R10, + "R11", AREG_R11, + "R12", AREG_R12, + "R13", AREG_R13, + "R14", AREG_R14, + "R15", AREG_R15, + "R16", AREG_R16, + "R17", AREG_R17, + "R18", AREG_R18, + "R19", AREG_R19, + + "R20", AREG_R20, + "R21", AREG_R21, + "R22", AREG_R22, + "R23", AREG_R23, + "R24", AREG_R24, + "R25", AREG_R25, + "R26", AREG_R26, + "R27", AREG_R27, + "R28", AREG_R28, + "R29", AREG_R29, + "R30", AREG_R30, + "R31", AREG_R31, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/cmd/scc-as/powerpc/powerpc64.mk b/src/cmd/scc-as/powerpc/powerpc64.mk @@ -0,0 +1,13 @@ +POWERPC = powerpc +POWERPC64_OBJ =\ + $(OBJS)\ + $(POWERPC)/powerpc64tbl.o\ + $(POWERPC)/powerpc64.o\ + $(POWERPC)/ins.o\ + +$(POWERPC)/powerpc64tbl.c: $(POWERPC)/ops.dat $(POWERPC)/opers.dat lexh + ./mktbl -f powerpc -c powerpc64 + +as-powerpc64: $(POWERPC64_OBJ) + $(CC) $(PROJ_LDFLAGS) $(POWERPC64_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/powerpc/proc.h b/src/cmd/scc-as/powerpc/proc.h diff --git a/src/cmd/scc-as/target/powerpc/ins.c b/src/cmd/scc-as/target/powerpc/ins.c @@ -1,354 +0,0 @@ -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "proc.h" - -/* - * This code is derived from PowerISA_V2.06B_V2_PUBLIC document. - * All the names used in the specification are preserved in - * this code. - */ - -static int -getclass(Node *np) -{ - if (np->addr != AREG) - return 0; - - switch (np->sym->value) { - case AREG_R0: - case AREG_R1: - case AREG_R2: - case AREG_R3: - case AREG_R4: - case AREG_R5: - case AREG_R6: - case AREG_R7: - case AREG_R8: - case AREG_R9: - case AREG_R10: - case AREG_R11: - case AREG_R12: - case AREG_R13: - case AREG_R14: - case AREG_R15: - case AREG_R16: - case AREG_R17: - case AREG_R18: - case AREG_R19: - case AREG_R20: - case AREG_R21: - case AREG_R22: - case AREG_R23: - case AREG_R24: - case AREG_R25: - case AREG_R26: - case AREG_R27: - case AREG_R29: - case AREG_R30: - case AREG_R31: - return GPRSCLASS; - default: - abort(); - } -} - -int -match(Op *op, Node **args) -{ - unsigned char *p; - int arg, class, rep, opt; - Node *np; - - if (!op->args) - return args == NULL; - - opt = rep = 0; - for (p = op->args; arg = *p; ++p) { - if (rep) - --p; - if ((np = *args++) == NULL) - return (rep|opt) != 0; - - switch (arg) { - case AOPT: - opt = 1; - break; - case AREP: - rep = 1; - break; - case AREG_GPRSCLASS: - class = GPRSCLASS; - check_class: - if ((getclass(np) & class) == 0) - return 0; - break; - case AIMM2: - case AIMM5: - case AIMM8: - case AIMM16: - case AIMM32: - case AIMM64: - if (np->addr != AIMM) - return 0; - if (toobig(np, arg)) - error("overflow in immediate operand"); - break; - case ASYM: - if (np->op != IDEN) - return 0; - break; - case ADIRECT: - case ASTR: - if (np->addr != arg) - return 0; - break; - default: - abort(); - } - } - - return *args == NULL; -} - -Node * -moperand(void) -{ - abort(); -} - -static void -emit_packed(unsigned long ins) -{ - char buff[4]; - - if (endian == BIG_ENDIAN) { - buff[0] = ins >> 24; - buff[1] = ins >> 16; - buff[2] = ins >> 8; - buff[3] = ins; - } else { - buff[0] = ins; - buff[1] = ins >> 8; - buff[2] = ins >> 16; - buff[3] = ins >> 24; - } - - emit(buff, 4); -} - -void -i_form(Op *op, Node **args) -{ - unsigned long ins, opcd, li, aa, lk; - long long dst; - long long max = 1l << 23; - long long min = -(1l << 23); - - opcd = op->bytes[0]; - aa = op->bytes[1]; - lk = op->bytes[2]; - - dst = args[0]->sym->value; - if (dst & 0x3) - error("unaligned branch"); - if (aa) - dst -= getpc() - 4; - if (dst < min || dst > max) - error("out of range branch"); - - li = dst; - li >>= 2; - ins = opcd<<26 | li<<2 | aa<<1 | lk; - emit_packed(ins); -} - -void -b_form(Op *op, Node **args) -{ - unsigned long ins, opcd, bo, bi, bd, aa, lk; - long long dst; - long long max = 1l << 13; - long long min = -(1l << 13); - - opcd = op->bytes[0]; - aa = op->bytes[1]; - lk = op->bytes[2]; - - bo = args[0]->sym->value; - bi = args[1]->sym->value; - - dst = args[2]->sym->value; - if (dst & 0x3) - error("unaligned branch"); - if (aa) - dst -= getpc() - 4; - - if (dst < min || dst > max) - error("out of range branch"); - bd = dst; - bd >>= 2; - - ins = opcd<<26 | bo<<21 | bi<<16 | bd<<11 | aa<<1 | lk; - emit_packed(ins); -} - -void -sc_form(Op *op, Node **args) -{ - abort(); -} - -void -d_form(Op *op, Node **args) -{ - abort(); -} - -void -ds_form(Op *op, Node **args) -{ - abort(); -} - -void -dq_form(Op *op, Node **args) -{ - abort(); -} - -void -x_form(Op *op, Node **args) -{ - abort(); -} - -void -xl_form(Op *op, Node **args) -{ - unsigned long ins, bo, bi, bh, lk; - unsigned long opcd1, opcd2; - long long dst; - - opcd1 = op->bytes[0]; - opcd2 = op->bytes[1]<<8 | op->bytes[2]; - lk = op->bytes[3]; - - bo = args[0]->sym->value; - bi = args[1]->sym->value; - bh = args[2]->sym->value; - - ins = opcd1<<26 | bo<<21 | bi<<16 | bh<<11 | opcd2<<1 | lk; - emit_packed(ins); -} - -void -xfx_form(Op *op, Node **args) -{ - abort(); -} - -void -xlfdorm_form(Op *op, Node **args) -{ - abort(); -} - -void -xx1_form(Op *op, Node **args) -{ - abort(); -} - -void -xx2_form(Op *op, Node **args) -{ - abort(); -} - -void -xx3_form(Op *op, Node **args) -{ - abort(); -} - -void -xx4_form(Op *op, Node **args) -{ - abort(); -} - -void -xs_form(Op *op, Node **args) -{ - abort(); -} - -void -xo_form(Op *op, Node **args) -{ - abort(); -} - -void -a_form(Op *op, Node **args) -{ - abort(); -} - -void -m_form(Op *op, Node **args) -{ - abort(); -} - -void -md_form(Op *op, Node **args) -{ - abort(); -} - -void -mds_form(Op *op, Node **args) -{ - abort(); -} - -void -va_form(Op *op, Node **args) -{ - abort(); -} - -void -vc_form(Op *op, Node **args) -{ - abort(); -} - -void -vx_form(Op *op, Node **args) -{ - abort(); -} - -void -evs_form(Op *op, Node **args) -{ - abort(); -} - -void -z22_form(Op *op, Node **args) -{ - abort(); -} - -void -z23_form(Op *op, Node **args) -{ - abort(); -} diff --git a/src/cmd/scc-as/target/powerpc/powerpc.c b/src/cmd/scc-as/target/powerpc/powerpc.c @@ -1,63 +0,0 @@ -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "proc.h" - -TUINT maxaddr = 0xFFFF; -int endian = BIG_ENDIAN; -int left2right = 0; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "R0", AREG_R0, - "R1", AREG_R1, - "R2", AREG_R2, - "R3", AREG_R3, - "R4", AREG_R4, - "R5", AREG_R5, - "R6", AREG_R6, - "R7", AREG_R7, - "R8", AREG_R8, - "R9", AREG_R9, - - "R10", AREG_R10, - "R11", AREG_R11, - "R12", AREG_R12, - "R13", AREG_R13, - "R14", AREG_R14, - "R15", AREG_R15, - "R16", AREG_R16, - "R17", AREG_R17, - "R18", AREG_R18, - "R19", AREG_R19, - - "R20", AREG_R20, - "R21", AREG_R21, - "R22", AREG_R22, - "R23", AREG_R23, - "R24", AREG_R24, - "R25", AREG_R25, - "R26", AREG_R26, - "R27", AREG_R27, - "R28", AREG_R28, - "R29", AREG_R29, - "R30", AREG_R30, - "R31", AREG_R31, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/src/cmd/scc-as/target/powerpc/powerpc.mk b/src/cmd/scc-as/target/powerpc/powerpc.mk @@ -1,13 +0,0 @@ -POWERPC = target/powerpc -POWERPC_OBJ =\ - $(OBJS)\ - $(POWERPC)/powerpctbl.o\ - $(POWERPC)/powerpc.o\ - $(POWERPC)/ins.o\ - -$(POWERPC)/powerpctbl.c: $(POWERPC)/ops.dat $(POWERPC)/opers.dat lexh - ./mktbl -f powerpc -c powerpc - -as-powerpc: $(POWERPC_OBJ) - $(CC) $(PROJ_LDFLAGS) $(POWERPC_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/powerpc/powerpc64.c b/src/cmd/scc-as/target/powerpc/powerpc64.c @@ -1,63 +0,0 @@ -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "proc.h" - -TUINT maxaddr = 0xFFFF; -int endian = BIG_ENDIAN; -int left2right = 0; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "R0", AREG_R0, - "R1", AREG_R1, - "R2", AREG_R2, - "R3", AREG_R3, - "R4", AREG_R4, - "R5", AREG_R5, - "R6", AREG_R6, - "R7", AREG_R7, - "R8", AREG_R8, - "R9", AREG_R9, - - "R10", AREG_R10, - "R11", AREG_R11, - "R12", AREG_R12, - "R13", AREG_R13, - "R14", AREG_R14, - "R15", AREG_R15, - "R16", AREG_R16, - "R17", AREG_R17, - "R18", AREG_R18, - "R19", AREG_R19, - - "R20", AREG_R20, - "R21", AREG_R21, - "R22", AREG_R22, - "R23", AREG_R23, - "R24", AREG_R24, - "R25", AREG_R25, - "R26", AREG_R26, - "R27", AREG_R27, - "R28", AREG_R28, - "R29", AREG_R29, - "R30", AREG_R30, - "R31", AREG_R31, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/src/cmd/scc-as/target/powerpc/powerpc64.mk b/src/cmd/scc-as/target/powerpc/powerpc64.mk @@ -1,13 +0,0 @@ -POWERPC = target/powerpc -POWERPC64_OBJ =\ - $(OBJS)\ - $(POWERPC)/powerpc64tbl.o\ - $(POWERPC)/powerpc64.o\ - $(POWERPC)/ins.o\ - -$(POWERPC)/powerpc64tbl.c: $(POWERPC)/ops.dat $(POWERPC)/opers.dat lexh - ./mktbl -f powerpc -c powerpc64 - -as-powerpc64: $(POWERPC64_OBJ) - $(CC) $(PROJ_LDFLAGS) $(POWERPC64_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x80/ins.c b/src/cmd/scc-as/target/x80/ins.c @@ -1,604 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "proc.h" - -/* - * This implementation is based in: - * - Zilog Z80 CPU Specifications by Sean Young - * - Decoding Z80 opcodes - of use to disassembler and emulator - * writers - by Cristian Dinu. - */ - -static int -getclass(Node *np) -{ - if (np->addr != AREG) - return 0; - - switch (np->sym->value) { - case AREG_C: - return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; - case AREG_A: - case AREG_B: - case AREG_D: - case AREG_E: - return RCLASS | PCLASS | QCLASS; - case AREG_H: - case AREG_L: - return RCLASS; - case AREG_IXL: - case AREG_IXH: - return PCLASS; - case AREG_IYL: - case AREG_IYH: - return QCLASS; - case AREG_HL: - return DDCLASS | QQCLASS; - case AREG_BC: - case AREG_DE: - return DDCLASS | QQCLASS | PPCLASS | RRCLASS; - case AREG_SP: - return DDCLASS | PPCLASS | RRCLASS; - case AREG_AF: - return QQCLASS; - case AREG_IX: - return PPCLASS; - case AREG_IY: - return RRCLASS; - case AREG_PO: - case AREG_PE: - case AREG_P: - case AREG_M: - return CCCLASS; - case AREG_NZ: - case AREG_Z: - case AREG_NC: - return CCCLASS | SSCLASS; - default: - return 0; - } -} - -int -match(Op *op, Node **args) -{ - unsigned char *p; - int arg, class, rep, opt; - Node *np; - - if (!op->args) - return args == NULL; - - opt = rep = 0; - for (p = op->args; arg = *p; ++p) { - if (rep) - --p; - if ((np = *args++) == NULL) - return (rep|opt) != 0; - - switch (arg) { - case AOPT: - opt = 1; - break; - case AREP: - rep = 1; - break; - case AINDER_C: - arg = AREG_C; - goto indirect; - case AINDER_HL: - arg = AREG_HL; - goto indirect; - case AINDER_DE: - arg = AREG_DE; - goto indirect; - case AINDER_BC: - arg = AREG_BC; - goto indirect; - case AINDER_IX: - arg = AREG_IX; - goto indirect; - case AINDER_IY: - arg = AREG_IY; - goto indirect; - case AINDER_SP: - arg = AREG_SP; - indirect: - if (np->addr != AINDIR) - return 0; - np = np->left; - case AREG_A: - case AREG_I: - case AREG_R: - case AREG_F: - case AREG_HL: - case AREG_BC: - case AREG_DE: - case AREG_IY: - case AREG_IX: - case AREG_SP: - case AREG_AF: - case AREG_AF_: - if (np->addr != AREG || np->sym->value != arg) - return 0; - break; - case AREG_RCLASS: - class = RCLASS; - goto check_class; - case AREG_PCLASS: - class = PCLASS; - goto check_class; - case AREG_QCLASS: - class = QCLASS; - goto check_class; - case AREG_QQCLASS: - class = QQCLASS; - goto check_class; - case AREG_PPCLASS: - class = PPCLASS; - goto check_class; - case AREG_RRCLASS: - class = RRCLASS; - goto check_class; - case AREG_CCCLASS: - class = CCCLASS; - goto check_class; - case AREG_SSCLASS: - class = SSCLASS; - goto check_class; - case AREG_DDCLASS: - class = DDCLASS; - check_class: - if ((getclass(np) & class) == 0) - return 0; - break; - case AINDEX_IY: - arg = AREG_IY; - goto index_address; - case AINDEX_IX: - arg = AREG_IX; - index_address: - if (np->addr != AINDEX) - return 0; - np = np->left->left; - if (np->sym->value != arg) - return 0; - if (toobig(np, AIMM8)) - error("overflow in index"); - break; - case ARST: - if (np->addr != AIMM) - return 0; - if ((np->sym->value & ~0x38) != 0) - return 0; - break; - case AZERO: - if (np->addr != AIMM) - return 0; - break; - case AIMM3: - case AIMM8: - case AIMM16: - case AIMM32: - case AIMM64: - if (np->addr != AIMM) - return 0; - if (toobig(np, arg)) - error("overflow in immediate operand"); - break; - case ASYM: - if (np->op != IDEN) - return 0; - break; - case ADIRECT: - case ASTR: - if (np->addr != arg) - return 0; - break; - default: - abort(); - } - } - - return *args == NULL; -} - -/* - * (expr) -> ADIRECT - * (REG) -> AINDIR - * (REG + expr) -> AINDEX - * (REG - expr) -> AINDEX - * expr (REG) -> AINDEX - */ -Node * -moperand(void) -{ - int op; - Node *np, *dir, *off, *reg; - - dir = off = reg = NULL; - if (accept('(')) { - if (yytoken != REG) { - dir = expr(); - } else { - reg = getreg(); - switch (yytoken) { - case '+': - case '-': - off = expr(); - case ')': - break; - default: - unexpected(); - } - } - } else { - off = expr(); - expect('('); - reg = getreg(); - } - expect(')'); - - if (dir) { - op = ADIRECT; - np = dir; - } else if (off) { - np = node(AREG_OFF, reg, off); - op = AINDEX; - } else { - np = reg; - op = AINDIR; - } - np = node(op, np, NULL); - np->addr = op; - return np; -} - -static int -reg2int(Node *np) -{ - switch (np->sym->value) { - case AREG_F: - case AREG_B: return 0; - case AREG_C: return 1; - case AREG_D: return 2; - case AREG_E: return 3; - case AREG_IXH: - case AREG_IYH: - case AREG_H: return 4; - case AREG_IXL: - case AREG_IYL: - case AREG_L: return 5; - case AREG_A: return 7; - case AREG_BC: return 0; - case AREG_DE: return 1; - case AREG_HL: - case AREG_IX: - case AREG_IY: return 2; - case AREG_AF: - case AREG_SP: return 3; - default: abort(); - } -} - -static int -cc2int(Node *np) -{ - switch (np->sym->value) { - case AREG_NZ: return 0; - case AREG_Z: return 1; - case AREG_NC: return 2; - case AREG_C: return 3; - case AREG_PO: return 4; - case AREG_PE: return 5; - case AREG_P: return 6; - case AREG_M: return 7; - default: abort(); - } -} - -static int -ss2int(Node *np) -{ - switch (np->sym->value) { - case AREG_NZ: return 4; - case AREG_Z: return 5; - case AREG_NC: return 6; - case AREG_C: return 7; - default: abort(); - } -} - -void -dir(Op *op, Node **args) -{ - Node *imm; - unsigned char buf[4]; - unsigned val; - int n = op->size; - - imm = (args[1]->addr == ADIRECT) ? args[1] : args[0]; - imm = imm->left; - memcpy(buf, op->bytes, n); - val = imm->sym->value; - buf[n-1] = val >> 8; - buf[n-2] = val; - emit(buf, n); -} - -void -ld8(Op *op, Node **args) -{ - Node *par1 = args[0], *par2 = args[1]; - int n = op->size, i = n; - unsigned regval = 0; - unsigned char buf[4]; - - memcpy(buf, op->bytes, n); - - if (par1->addr == AREG) - regval |= reg2int(par1) << 3; - if (par2->addr == AREG) - regval |= reg2int(par2); - else if (par2->addr == AIMM) - buf[--i] = par2->sym->value; - - buf[--i] |= regval; - emit(buf, n); -} - -void -alu16(Op *op, Node **args) -{ - Node *par; - int n = op->size; - unsigned val; - unsigned char buf[4]; - - par = (args[1]) ? args[1] : args[0]; - val = reg2int(par); - memcpy(buf, op->bytes, n); - buf[n-1] |= val << 4; - emit(buf, n); -} - -void -ld16(Op *op, Node **args) -{ - Node *dst, *src, *tmp; - int n = op->size; - unsigned val; - unsigned char buf[4]; - - dst = args[0]; - src = args[1]; - if (!src) { - alu16(op, args); - return; - } - - if (dst->addr != AREG) { - tmp = src; - src = dst; - dst = tmp; - } - - memcpy(buf, op->bytes, n); - if (src->addr == ADIRECT) - src = src->left; - val = src->sym->value; - buf[n-1] = val >> 8; - buf[n-2] = val; - buf[n-3] |= reg2int(dst) << 4; - emit(buf, n); -} - -void -alu8(Op *op, Node **args) -{ - Node *par = args[1]; - unsigned char buf[4]; - int n = op->size, shift; - unsigned val; - - if (args[1]) { - shift = 0; - par = args[1]; - } else { - shift = 3; - par = args[0]; - } - - switch (par->addr) { - case AIMM: - val = par->sym->value; - break; - case AREG: - val = reg2int(par) << shift; - break; - case AINDEX: - val = par->left->right->sym->value; - break; - case AINDIR: - val = 0; - break; - default: - abort(); - } - - memcpy(buf, op->bytes, n); - buf[n-1] |= val; - emit(buf, n); -} - -void -idx(Op *op, Node **args) -{ - Node *tmp, *idx, *imm, *reg; - unsigned char buf[4]; - int n = op->size, i = n, shift = 0; - - imm = reg = NULL; - if (args[0]->addr != AINDEX) { - shift = 3; - tmp = args[0]; - args[0] = args[1]; - args[1] = tmp; - } - idx = args[0]->left->right; - - if (args[1]->addr == AREG) - reg = args[1]; - else - imm = args[1]; - - memcpy(buf, op->bytes, n); - - if (imm) - buf[--i] = imm->sym->value; - buf[--i] = idx->sym->value; - if (reg) - buf[--i] |= reg2int(reg) << shift; - - emit(buf, n); -} - -void -inout(Op *op, Node **args) -{ - Node *port, *value; - unsigned val; - int n = op->size; - unsigned char buf[5]; - - port = args[0]; - value = args[1]; - if (port->addr != ADIRECT && port->addr != AINDIR) { - value = port; - port = args[1]; - } - - if (port->addr == ADIRECT) - val = port->left->sym->value; - else if (value->addr == AREG) - val = reg2int(value) << 3; - else - val = 0; - - memcpy(buf, op->bytes, n); - buf[n-1] |= val; - emit(buf, n); -} - -void -rot_bit(Op *op, Node **args) -{ - Node *par = args[0]; - unsigned char buf[5]; - int n = op->size; - unsigned val, npar = 0; - - memcpy(buf, op->bytes, n); - - par = args[0]; - if (par->addr == AIMM) { - buf[n-1] |= par->sym->value << 3; - par = args[npar = 1]; - } - - switch (par->addr) { - case AINDEX: - val = par->left->right->sym->value; - buf[n-2] = val; - par = args[npar+1]; - if (!par) - break; - case AREG: - val = reg2int(par); - buf[n-1] |= val; - case AINDIR: - break; - default: - abort(); - } - - emit(buf, n); -} - -void -im(Op *op, Node **args) -{ - unsigned val = args[0]->sym->value; - unsigned char buf[4]; - int n = op->size; - - if (val > 0) - ++val; - - memcpy(buf, op->bytes, n); - buf[n-1] |= val << 3; - emit(buf, n); -} - -void -branch(int relative, Op *op, Node **args) -{ - unsigned char buf[4]; - Node *flag, *imm; - int n = op->size, i = n; - unsigned val; - int (*fun)(Node *); - - flag = imm = NULL; - if (args[0]->addr == AREG) { - flag = args[0]; - imm = args[1]; - } else if (args[0]->addr == AIMM) { - imm = args[0]; - } - memcpy(buf, op->bytes, n); - - if (imm) { - val = imm->sym->value; - if (!relative) - buf[--i] = val >> 8; - else - val -= getpc() - 2; - buf[--i] = val; - - } - if (flag) { - fun = (relative) ? ss2int : cc2int; - buf[--i] |= (*fun)(flag) << 3; - } - - - emit(buf, n); -} - -void -jp(Op *op, Node **args) -{ - branch(0, op, args); -} - -void -jr(Op *op, Node **args) -{ - branch(1, op, args); -} - -void -rst(Op *op, Node **args) -{ - unsigned char buf[1]; - - buf[0] = op->bytes[0]; - buf[0] |= args[0]->sym->value; - emit(buf, 1); -} diff --git a/src/cmd/scc-as/target/x80/z80.c b/src/cmd/scc-as/target/x80/z80.c @@ -1,64 +0,0 @@ -#include <stdlib.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "../x80/proc.h" - -TUINT maxaddr = 0xFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "AF", AREG_AF, - "A", AREG_A, - "F", AREG_F, - - "BC", AREG_BC, - "B", AREG_B, - "C", AREG_C, - - "HL", AREG_HL, - "H", AREG_H, - "L", AREG_L, - - "DE", AREG_DE, - "D", AREG_D, - "E", AREG_E, - - "IX", AREG_IX, - "IXL", AREG_IXL, - "IXH", AREG_IXH, - - "IY", AREG_IY, - "IYL", AREG_IYL, - "IYH", AREG_IYH, - - "R", AREG_R, - "I", AREG_I, - "AF'", AREG_AF_, - "SP", AREG_SP, - - "NZ", AREG_NZ, - "Z", AREG_Z, - "NC", AREG_NC, - "PO", AREG_PO, - "PE", AREG_PE, - "P", AREG_P, - "M", AREG_M, - - NULL, - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/src/cmd/scc-as/target/x80/z80.mk b/src/cmd/scc-as/target/x80/z80.mk @@ -1,12 +0,0 @@ -Z80_OBJ =\ - $(OBJS)\ - target/x80/z80tbl.o\ - target/x80/z80.o\ - target/x80/ins.o\ - -target/x80/z80tbl.c: target/x80/ops.dat target/x80/opers.dat lexh - ./mktbl -f x80 -c z80 - -as-z80: $(OBJ) $(Z80_OBJ) - $(CC) $(PROJ_LDFLAGS) $(Z80_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x86/amd64.c b/src/cmd/scc-as/target/x86/amd64.c @@ -1,12 +0,0 @@ -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" - -TUINT maxaddr = 0xFFFFFFFFFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ -} diff --git a/src/cmd/scc-as/target/x86/amd64.mk b/src/cmd/scc-as/target/x86/amd64.mk @@ -1,12 +0,0 @@ -AMD64_OBJ =\ - $(OBJS)\ - target/x86/amd64tbl.o\ - target/x86/amd64.o\ - target/x86/ins.o\ - -target/x86/amd64tbl.c: target/x86/ops.dat target/x86/opers.dat lexh - ./mktbl -f x86 -c amd64 - -as-amd64: $(AMD64_OBJ) - $(CC) $(PROJ_LDFLAGS) $(AMD64_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x86/i286.c b/src/cmd/scc-as/target/x86/i286.c @@ -1,53 +0,0 @@ -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "../x86/proc.h" - -TUINT maxaddr = 0xFFFF; -int endian = LITTLE_ENDIAN; -int left2right = 0; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "CS", AREG_CS, - "DS", AREG_DS, - "SS", AREG_SS, - "ES", AREG_ES, - - "AX", AREG_AX, - "AL", AREG_AL, - "AH", AREG_AH, - - "BX", AREG_BX, - "BL", AREG_BL, - "BH", AREG_BH, - - "CX", AREG_CX, - "CL", AREG_CL, - "CH", AREG_CH, - - "DX", AREG_DX, - "DL", AREG_DL, - "DH", AREG_DH, - - "SI", AREG_SI, - "DI", AREG_DI, - - "SP", AREG_SP, - "BP", AREG_BP, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/src/cmd/scc-as/target/x86/i286.mk b/src/cmd/scc-as/target/x86/i286.mk @@ -1,12 +0,0 @@ -I286_OBJ =\ - $(OBJS)\ - target/x86/i286tbl.o\ - target/x86/i286.o\ - target/x86/ins.o\ - -target/x86/i286tbl.c: target/x86/ops.dat target/x86/opers.dat lexh - ./mktbl -f x86 -c i286 - -as-i286: $(I286_OBJ) - $(CC) $(PROJ_LDFLAGS) $(I286_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x86/i386.c b/src/cmd/scc-as/target/x86/i386.c @@ -1,100 +0,0 @@ -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "../x86/proc.h" - -TUINT maxaddr = 0xFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ - static struct { - char *name; - unsigned char type; - } regs[] = { - "CS", AREG_CS, - "DS", AREG_DS, - "SS", AREG_SS, - "ES", AREG_ES, - "FS", AREG_FS, - "GS", AREG_GS, - - "AX", AREG_AX, - "AL", AREG_AL, - "AH", AREG_AH, - "EAX", AREG_EAX, - - "BC", AREG_BX, - "BL", AREG_BL, - "BH", AREG_BH, - "EBX", AREG_EBX, - - "CX", AREG_CX, - "CL", AREG_CL, - "CH", AREG_CH, - "ECX", AREG_ECX, - - "DX", AREG_DX, - "DL", AREG_DL, - "DH", AREG_DH, - "EDX", AREG_EDX, - - "SI", AREG_SI, - "ESI", AREG_ESI, - "DI", AREG_DI, - "EDI", AREG_EDI, - - "SP", AREG_SP, - "ESP", AREG_ESP, - - "BP", AREG_BP, - "EBP", AREG_EBP, - - "R0", AREG_R0, - "MM0", AREG_MM0, - "R1", AREG_R1, - "MM1", AREG_MM1, - "R2", AREG_R2, - "MM2", AREG_MM2, - "R3", AREG_R3, - "MM3", AREG_MM3, - "R4", AREG_R4, - "MM4", AREG_MM4, - "R5", AREG_R5, - "MM5", AREG_MM5, - "R6", AREG_R6, - "MM6", AREG_MM6, - "R7", AREG_R7, - "MM7", AREG_MM7, - - "XMM0", AREG_XMM0, - "XMM1", AREG_XMM1, - "XMM2", AREG_XMM2, - "XMM3", AREG_XMM3, - "XMM4", AREG_XMM4, - "XMM5", AREG_XMM5, - "XMM6", AREG_XMM6, - "XMM7", AREG_XMM7, - - "YMM0", AREG_YMM0, - "YMM1", AREG_YMM1, - "YMM2", AREG_YMM2, - "YMM3", AREG_YMM3, - "YMM4", AREG_YMM4, - "YMM5", AREG_YMM5, - "YMM6", AREG_YMM6, - "YMM7", AREG_YMM7, - - "MXCSR", AREG_MXCSR, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/src/cmd/scc-as/target/x86/i386.mk b/src/cmd/scc-as/target/x86/i386.mk @@ -1,12 +0,0 @@ -I386_OBJ =\ - $(OBJS)\ - target/x86/i386tbl.o\ - target/x86/i386.o\ - target/x86/ins.o\ - -target/x86/i386tbl.c: target/x86/ops.dat target/x86/opers.dat lexh - ./mktbl -f x86 -c i386 - -as-i386: $(I386_OBJ) - $(CC) $(PROJ_LDFLAGS) $(I386_OBJ) $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x86/ins.c b/src/cmd/scc-as/target/x86/ins.c @@ -1,354 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include <scc/mach.h> -#include <scc/scc.h> - -#include "../../as.h" -#include "proc.h" - -#define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm)) - -/* - * This implementation is based in: - * - x86 Opcode Structure and Instruction Overview - Fraunhofer-Institut - * fÜr kommunikation, informationsverarbeitung und ergonomie fkie. - * - Intel® 64 and IA-32 Architectures Software Developer’s Manual. - * - Encoding Real x86 Instructions - CIS-77 lectures. - */ -enum addr_mode { - MEM_MODE = 0, - MEM8_MODE = 1, - MEM16_MODE = 2, - REG_MODE = 3, -}; - -static int -getclass(Node *np) -{ - if (np->addr != AREG) - return 0; - - switch (np->sym->value) { - case AREG_AL: - case AREG_AH: - case AREG_BL: - case AREG_BH: - case AREG_CL: - case AREG_CH: - case AREG_DL: - case AREG_DH: - return R8CLASS; - - case AREG_AX: - case AREG_BX: - case AREG_CX: - case AREG_DX: - case AREG_DI: - case AREG_SI: - case AREG_SP: - case AREG_BP: - return R16CLASS; - - case AREG_CS: - case AREG_DS: - case AREG_SS: - case AREG_ES: - case AREG_FS: - case AREG_GS: - - case AREG_EFLAGS: - case AREG_CF: - case AREG_PF: - case AREG_AF: - case AREG_ZF: - case AREG_SF: - case AREG_TF: - case AREG_IF: - case AREG_DF: - case AREG_OF: - case AREG_IOPL: - case AREG_NT: - case AREG_RF: - case AREG_VM: - case AREG_AC: - case AREG_VIF: - case AREG_VIP: - case AREG_ID: - - case AREG_EAX: - case AREG_RAX: - - case AREG_EBX: - case AREG_RBX: - - case AREG_ECX: - case AREG_RCX: - - case AREG_EDX: - case AREG_RDX: - - case AREG_SIL: - case AREG_ESI: - case AREG_RSI: - case AREG_DIL: - case AREG_EDI: - case AREG_RDI: - - case AREG_SPL: - case AREG_ESP: - case AREG_RSP: - - case AREG_BPL: - case AREG_EBP: - case AREG_RBP: - - case AREG_R0: - case AREG_MM0: - case AREG_R1: - case AREG_MM1: - case AREG_R2: - case AREG_MM2: - case AREG_R3: - case AREG_MM3: - case AREG_R4: - case AREG_MM4: - case AREG_R5: - case AREG_MM5: - case AREG_R6: - case AREG_MM6: - case AREG_R7: - case AREG_MM7: - - case AREG_R8: - case AREG_R8L: - case AREG_R8W: - case AREG_R9: - case AREG_R9L: - case AREG_R9W: - case AREG_R10: - case AREG_R10L: - case AREG_R10W: - case AREG_R11: - case AREG_R11L: - case AREG_R11W: - case AREG_R12: - case AREG_R12L: - case AREG_R12W: - case AREG_R13: - case AREG_R13L: - case AREG_R13W: - case AREG_R14: - case AREG_R14L: - case AREG_R14W: - case AREG_R15: - case AREG_R15L: - case AREG_R15W: - - case AREG_XMM0: - case AREG_XMM1: - case AREG_XMM2: - case AREG_XMM3: - case AREG_XMM4: - case AREG_XMM5: - case AREG_XMM6: - case AREG_XMM7: - case AREG_XMM8: - case AREG_XMM9: - case AREG_XMM10: - case AREG_XMM11: - case AREG_XMM12: - case AREG_XMM13: - case AREG_XMM14: - case AREG_XMM15: - - case AREG_YMM0: - case AREG_YMM1: - case AREG_YMM2: - case AREG_YMM3: - case AREG_YMM4: - case AREG_YMM5: - case AREG_YMM6: - case AREG_YMM7: - case AREG_YMM8: - case AREG_YMM9: - case AREG_YMM10: - case AREG_YMM11: - case AREG_YMM12: - case AREG_YMM13: - case AREG_YMM14: - case AREG_YMM15: - - case AREG_MXCSR: - return 0; - default: - abort(); - } -} - -int -match(Op *op, Node **args) -{ - unsigned char *p; - int arg, class, rep, opt; - Node *np; - - if (!op->args) - return args == NULL; - - opt = rep = 0; - for (p = op->args; arg = *p; ++p) { - if (rep) - --p; - if ((np = *args++) == NULL) - return (rep|opt) != 0; - - switch (arg) { - case AOPT: - opt = 1; - break; - case AREP: - rep = 1; - break; - case AREG_R8CLASS: - class = R8CLASS; - goto check_class; - case AREG_R16CLASS: - class = R16CLASS; - check_class: - if ((getclass(np) & class) == 0) - return 0; - break; - case AIMM8: - case AIMM16: - case AIMM32: - case AIMM64: - if (np->addr != AIMM) - return 0; - if (toobig(np, arg)) - error("overflow in immediate operand"); - break; - case ASYM: - if (np->op != IDEN) - return 0; - break; - case ADIRECT: - case ASTR: - if (np->addr != arg) - return 0; - break; - default: - abort(); - } - } - - return *args == NULL; -} - -Node * -moperand(void) -{ -} - -static int -reg8toint(Node *np) -{ - switch (np->sym->value) { - case AREG_AL: return 0; - case AREG_CL: return 1; - case AREG_DL: return 2; - case AREG_BL: return 3; - case AREG_AH: return 4; - case AREG_CH: return 5; - case AREG_DH: return 6; - case AREG_BH: return 7; - default: abort(); - } -} - -static int -reg16toint(Node *np) -{ - switch (np->sym->value) { - case AREG_AX: return 0; - case AREG_CX: return 1; - case AREG_DX: return 2; - case AREG_BX: return 3; - case AREG_SP: return 4; - case AREG_BP: return 5; - case AREG_SI: return 6; - case AREG_DI: return 7; - default: abort(); - } -} - -static int -reg32toint(Node *np) -{ - switch (np->sym->value) { - case AREG_EAX: return 0; - case AREG_ECX: return 1; - case AREG_EDX: return 2; - case AREG_EBX: return 3; - case AREG_ESP: return 4; - case AREG_EBP: return 5; - case AREG_ESI: return 6; - case AREG_EDI: return 7; - default: abort(); - } -} - -void -reg8_reg8(Op *op, Node **args) -{ - int src, dst; - char buf[op->size]; - - src = reg8toint(args[0]); - dst = reg8toint(args[1]); - memcpy(buf, op->bytes, op->size - 1); - buf[op->size - 1] = addrbyte(REG_MODE, src, dst); - emit(buf, op->size); -} - -void -imm8_reg8(Op *op, Node **args) -{ - int src, dst; - char buf[op->size]; - - src = (*args)->sym->value; - dst = reg8toint(args[1]); - memcpy(buf, op->bytes, op->size - 2); - buf[op->size - 2] = addrbyte(REG_MODE, 0, dst); - buf[op->size - 1] = src; - emit(buf, op->size); -} - - -void -reg16_reg16(Op *op, Node **args) -{ - int src, dst; - char buf[op->size]; - - src = reg16toint(args[0]); - dst = reg16toint(args[1]); - memcpy(buf, op->bytes, op->size - 1); - buf[op->size - 1] = addrbyte(REG_MODE, src, dst); - emit(buf, op->size); -} - - -void -reg32_reg32(Op *op, Node **args) -{ - int src, dst; - char buf[op->size]; - - src = reg32toint(args[0]); - dst = reg32toint(args[1]); - memcpy(buf, op->bytes, op->size - 1); - buf[op->size - 1] = addrbyte(REG_MODE, src, dst); - emit(buf, op->size); -} diff --git a/src/cmd/scc-as/target/x80/.gitignore b/src/cmd/scc-as/x80/.gitignore diff --git a/src/cmd/scc-as/x80/ins.c b/src/cmd/scc-as/x80/ins.c @@ -0,0 +1,604 @@ +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "proc.h" + +/* + * This implementation is based in: + * - Zilog Z80 CPU Specifications by Sean Young + * - Decoding Z80 opcodes - of use to disassembler and emulator + * writers - by Cristian Dinu. + */ + +static int +getclass(Node *np) +{ + if (np->addr != AREG) + return 0; + + switch (np->sym->value) { + case AREG_C: + return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; + case AREG_A: + case AREG_B: + case AREG_D: + case AREG_E: + return RCLASS | PCLASS | QCLASS; + case AREG_H: + case AREG_L: + return RCLASS; + case AREG_IXL: + case AREG_IXH: + return PCLASS; + case AREG_IYL: + case AREG_IYH: + return QCLASS; + case AREG_HL: + return DDCLASS | QQCLASS; + case AREG_BC: + case AREG_DE: + return DDCLASS | QQCLASS | PPCLASS | RRCLASS; + case AREG_SP: + return DDCLASS | PPCLASS | RRCLASS; + case AREG_AF: + return QQCLASS; + case AREG_IX: + return PPCLASS; + case AREG_IY: + return RRCLASS; + case AREG_PO: + case AREG_PE: + case AREG_P: + case AREG_M: + return CCCLASS; + case AREG_NZ: + case AREG_Z: + case AREG_NC: + return CCCLASS | SSCLASS; + default: + return 0; + } +} + +int +match(Op *op, Node **args) +{ + unsigned char *p; + int arg, class, rep, opt; + Node *np; + + if (!op->args) + return args == NULL; + + opt = rep = 0; + for (p = op->args; arg = *p; ++p) { + if (rep) + --p; + if ((np = *args++) == NULL) + return (rep|opt) != 0; + + switch (arg) { + case AOPT: + opt = 1; + break; + case AREP: + rep = 1; + break; + case AINDER_C: + arg = AREG_C; + goto indirect; + case AINDER_HL: + arg = AREG_HL; + goto indirect; + case AINDER_DE: + arg = AREG_DE; + goto indirect; + case AINDER_BC: + arg = AREG_BC; + goto indirect; + case AINDER_IX: + arg = AREG_IX; + goto indirect; + case AINDER_IY: + arg = AREG_IY; + goto indirect; + case AINDER_SP: + arg = AREG_SP; + indirect: + if (np->addr != AINDIR) + return 0; + np = np->left; + case AREG_A: + case AREG_I: + case AREG_R: + case AREG_F: + case AREG_HL: + case AREG_BC: + case AREG_DE: + case AREG_IY: + case AREG_IX: + case AREG_SP: + case AREG_AF: + case AREG_AF_: + if (np->addr != AREG || np->sym->value != arg) + return 0; + break; + case AREG_RCLASS: + class = RCLASS; + goto check_class; + case AREG_PCLASS: + class = PCLASS; + goto check_class; + case AREG_QCLASS: + class = QCLASS; + goto check_class; + case AREG_QQCLASS: + class = QQCLASS; + goto check_class; + case AREG_PPCLASS: + class = PPCLASS; + goto check_class; + case AREG_RRCLASS: + class = RRCLASS; + goto check_class; + case AREG_CCCLASS: + class = CCCLASS; + goto check_class; + case AREG_SSCLASS: + class = SSCLASS; + goto check_class; + case AREG_DDCLASS: + class = DDCLASS; + check_class: + if ((getclass(np) & class) == 0) + return 0; + break; + case AINDEX_IY: + arg = AREG_IY; + goto index_address; + case AINDEX_IX: + arg = AREG_IX; + index_address: + if (np->addr != AINDEX) + return 0; + np = np->left->left; + if (np->sym->value != arg) + return 0; + if (toobig(np, AIMM8)) + error("overflow in index"); + break; + case ARST: + if (np->addr != AIMM) + return 0; + if ((np->sym->value & ~0x38) != 0) + return 0; + break; + case AZERO: + if (np->addr != AIMM) + return 0; + break; + case AIMM3: + case AIMM8: + case AIMM16: + case AIMM32: + case AIMM64: + if (np->addr != AIMM) + return 0; + if (toobig(np, arg)) + error("overflow in immediate operand"); + break; + case ASYM: + if (np->op != IDEN) + return 0; + break; + case ADIRECT: + case ASTR: + if (np->addr != arg) + return 0; + break; + default: + abort(); + } + } + + return *args == NULL; +} + +/* + * (expr) -> ADIRECT + * (REG) -> AINDIR + * (REG + expr) -> AINDEX + * (REG - expr) -> AINDEX + * expr (REG) -> AINDEX + */ +Node * +moperand(void) +{ + int op; + Node *np, *dir, *off, *reg; + + dir = off = reg = NULL; + if (accept('(')) { + if (yytoken != REG) { + dir = expr(); + } else { + reg = getreg(); + switch (yytoken) { + case '+': + case '-': + off = expr(); + case ')': + break; + default: + unexpected(); + } + } + } else { + off = expr(); + expect('('); + reg = getreg(); + } + expect(')'); + + if (dir) { + op = ADIRECT; + np = dir; + } else if (off) { + np = node(AREG_OFF, reg, off); + op = AINDEX; + } else { + np = reg; + op = AINDIR; + } + np = node(op, np, NULL); + np->addr = op; + return np; +} + +static int +reg2int(Node *np) +{ + switch (np->sym->value) { + case AREG_F: + case AREG_B: return 0; + case AREG_C: return 1; + case AREG_D: return 2; + case AREG_E: return 3; + case AREG_IXH: + case AREG_IYH: + case AREG_H: return 4; + case AREG_IXL: + case AREG_IYL: + case AREG_L: return 5; + case AREG_A: return 7; + case AREG_BC: return 0; + case AREG_DE: return 1; + case AREG_HL: + case AREG_IX: + case AREG_IY: return 2; + case AREG_AF: + case AREG_SP: return 3; + default: abort(); + } +} + +static int +cc2int(Node *np) +{ + switch (np->sym->value) { + case AREG_NZ: return 0; + case AREG_Z: return 1; + case AREG_NC: return 2; + case AREG_C: return 3; + case AREG_PO: return 4; + case AREG_PE: return 5; + case AREG_P: return 6; + case AREG_M: return 7; + default: abort(); + } +} + +static int +ss2int(Node *np) +{ + switch (np->sym->value) { + case AREG_NZ: return 4; + case AREG_Z: return 5; + case AREG_NC: return 6; + case AREG_C: return 7; + default: abort(); + } +} + +void +dir(Op *op, Node **args) +{ + Node *imm; + unsigned char buf[4]; + unsigned val; + int n = op->size; + + imm = (args[1]->addr == ADIRECT) ? args[1] : args[0]; + imm = imm->left; + memcpy(buf, op->bytes, n); + val = imm->sym->value; + buf[n-1] = val >> 8; + buf[n-2] = val; + emit(buf, n); +} + +void +ld8(Op *op, Node **args) +{ + Node *par1 = args[0], *par2 = args[1]; + int n = op->size, i = n; + unsigned regval = 0; + unsigned char buf[4]; + + memcpy(buf, op->bytes, n); + + if (par1->addr == AREG) + regval |= reg2int(par1) << 3; + if (par2->addr == AREG) + regval |= reg2int(par2); + else if (par2->addr == AIMM) + buf[--i] = par2->sym->value; + + buf[--i] |= regval; + emit(buf, n); +} + +void +alu16(Op *op, Node **args) +{ + Node *par; + int n = op->size; + unsigned val; + unsigned char buf[4]; + + par = (args[1]) ? args[1] : args[0]; + val = reg2int(par); + memcpy(buf, op->bytes, n); + buf[n-1] |= val << 4; + emit(buf, n); +} + +void +ld16(Op *op, Node **args) +{ + Node *dst, *src, *tmp; + int n = op->size; + unsigned val; + unsigned char buf[4]; + + dst = args[0]; + src = args[1]; + if (!src) { + alu16(op, args); + return; + } + + if (dst->addr != AREG) { + tmp = src; + src = dst; + dst = tmp; + } + + memcpy(buf, op->bytes, n); + if (src->addr == ADIRECT) + src = src->left; + val = src->sym->value; + buf[n-1] = val >> 8; + buf[n-2] = val; + buf[n-3] |= reg2int(dst) << 4; + emit(buf, n); +} + +void +alu8(Op *op, Node **args) +{ + Node *par = args[1]; + unsigned char buf[4]; + int n = op->size, shift; + unsigned val; + + if (args[1]) { + shift = 0; + par = args[1]; + } else { + shift = 3; + par = args[0]; + } + + switch (par->addr) { + case AIMM: + val = par->sym->value; + break; + case AREG: + val = reg2int(par) << shift; + break; + case AINDEX: + val = par->left->right->sym->value; + break; + case AINDIR: + val = 0; + break; + default: + abort(); + } + + memcpy(buf, op->bytes, n); + buf[n-1] |= val; + emit(buf, n); +} + +void +idx(Op *op, Node **args) +{ + Node *tmp, *idx, *imm, *reg; + unsigned char buf[4]; + int n = op->size, i = n, shift = 0; + + imm = reg = NULL; + if (args[0]->addr != AINDEX) { + shift = 3; + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + } + idx = args[0]->left->right; + + if (args[1]->addr == AREG) + reg = args[1]; + else + imm = args[1]; + + memcpy(buf, op->bytes, n); + + if (imm) + buf[--i] = imm->sym->value; + buf[--i] = idx->sym->value; + if (reg) + buf[--i] |= reg2int(reg) << shift; + + emit(buf, n); +} + +void +inout(Op *op, Node **args) +{ + Node *port, *value; + unsigned val; + int n = op->size; + unsigned char buf[5]; + + port = args[0]; + value = args[1]; + if (port->addr != ADIRECT && port->addr != AINDIR) { + value = port; + port = args[1]; + } + + if (port->addr == ADIRECT) + val = port->left->sym->value; + else if (value->addr == AREG) + val = reg2int(value) << 3; + else + val = 0; + + memcpy(buf, op->bytes, n); + buf[n-1] |= val; + emit(buf, n); +} + +void +rot_bit(Op *op, Node **args) +{ + Node *par = args[0]; + unsigned char buf[5]; + int n = op->size; + unsigned val, npar = 0; + + memcpy(buf, op->bytes, n); + + par = args[0]; + if (par->addr == AIMM) { + buf[n-1] |= par->sym->value << 3; + par = args[npar = 1]; + } + + switch (par->addr) { + case AINDEX: + val = par->left->right->sym->value; + buf[n-2] = val; + par = args[npar+1]; + if (!par) + break; + case AREG: + val = reg2int(par); + buf[n-1] |= val; + case AINDIR: + break; + default: + abort(); + } + + emit(buf, n); +} + +void +im(Op *op, Node **args) +{ + unsigned val = args[0]->sym->value; + unsigned char buf[4]; + int n = op->size; + + if (val > 0) + ++val; + + memcpy(buf, op->bytes, n); + buf[n-1] |= val << 3; + emit(buf, n); +} + +void +branch(int relative, Op *op, Node **args) +{ + unsigned char buf[4]; + Node *flag, *imm; + int n = op->size, i = n; + unsigned val; + int (*fun)(Node *); + + flag = imm = NULL; + if (args[0]->addr == AREG) { + flag = args[0]; + imm = args[1]; + } else if (args[0]->addr == AIMM) { + imm = args[0]; + } + memcpy(buf, op->bytes, n); + + if (imm) { + val = imm->sym->value; + if (!relative) + buf[--i] = val >> 8; + else + val -= getpc() - 2; + buf[--i] = val; + + } + if (flag) { + fun = (relative) ? ss2int : cc2int; + buf[--i] |= (*fun)(flag) << 3; + } + + + emit(buf, n); +} + +void +jp(Op *op, Node **args) +{ + branch(0, op, args); +} + +void +jr(Op *op, Node **args) +{ + branch(1, op, args); +} + +void +rst(Op *op, Node **args) +{ + unsigned char buf[1]; + + buf[0] = op->bytes[0]; + buf[0] |= args[0]->sym->value; + emit(buf, 1); +} diff --git a/src/cmd/scc-as/target/x80/opers.dat b/src/cmd/scc-as/x80/opers.dat diff --git a/src/cmd/scc-as/target/x80/ops.dat b/src/cmd/scc-as/x80/ops.dat diff --git a/src/cmd/scc-as/target/x80/proc.h b/src/cmd/scc-as/x80/proc.h diff --git a/src/cmd/scc-as/x80/z80.c b/src/cmd/scc-as/x80/z80.c @@ -0,0 +1,64 @@ +#include <stdlib.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "../x80/proc.h" + +TUINT maxaddr = 0xFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "AF", AREG_AF, + "A", AREG_A, + "F", AREG_F, + + "BC", AREG_BC, + "B", AREG_B, + "C", AREG_C, + + "HL", AREG_HL, + "H", AREG_H, + "L", AREG_L, + + "DE", AREG_DE, + "D", AREG_D, + "E", AREG_E, + + "IX", AREG_IX, + "IXL", AREG_IXL, + "IXH", AREG_IXH, + + "IY", AREG_IY, + "IYL", AREG_IYL, + "IYH", AREG_IYH, + + "R", AREG_R, + "I", AREG_I, + "AF'", AREG_AF_, + "SP", AREG_SP, + + "NZ", AREG_NZ, + "Z", AREG_Z, + "NC", AREG_NC, + "PO", AREG_PO, + "PE", AREG_PE, + "P", AREG_P, + "M", AREG_M, + + NULL, + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/cmd/scc-as/x80/z80.mk b/src/cmd/scc-as/x80/z80.mk @@ -0,0 +1,12 @@ +Z80_OBJ =\ + $(OBJS)\ + x80/z80tbl.o\ + x80/z80.o\ + x80/ins.o\ + +x80/z80tbl.c: x80/ops.dat x80/opers.dat lexh + ./mktbl -f x80 -c z80 + +as-z80: $(OBJ) $(Z80_OBJ) + $(CC) $(PROJ_LDFLAGS) $(Z80_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/target/x86/.gitignore b/src/cmd/scc-as/x86/.gitignore diff --git a/src/cmd/scc-as/x86/amd64.c b/src/cmd/scc-as/x86/amd64.c @@ -0,0 +1,12 @@ +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" + +TUINT maxaddr = 0xFFFFFFFFFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ +} diff --git a/src/cmd/scc-as/x86/amd64.mk b/src/cmd/scc-as/x86/amd64.mk @@ -0,0 +1,12 @@ +AMD64_OBJ =\ + $(OBJS)\ + x86/amd64tbl.o\ + x86/amd64.o\ + x86/ins.o\ + +x86/amd64tbl.c: x86/ops.dat x86/opers.dat lexh + ./mktbl -f x86 -c amd64 + +as-amd64: $(AMD64_OBJ) + $(CC) $(PROJ_LDFLAGS) $(AMD64_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/x86/i286.c b/src/cmd/scc-as/x86/i286.c @@ -0,0 +1,53 @@ +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "../x86/proc.h" + +TUINT maxaddr = 0xFFFF; +int endian = LITTLE_ENDIAN; +int left2right = 0; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "CS", AREG_CS, + "DS", AREG_DS, + "SS", AREG_SS, + "ES", AREG_ES, + + "AX", AREG_AX, + "AL", AREG_AL, + "AH", AREG_AH, + + "BX", AREG_BX, + "BL", AREG_BL, + "BH", AREG_BH, + + "CX", AREG_CX, + "CL", AREG_CL, + "CH", AREG_CH, + + "DX", AREG_DX, + "DL", AREG_DL, + "DH", AREG_DH, + + "SI", AREG_SI, + "DI", AREG_DI, + + "SP", AREG_SP, + "BP", AREG_BP, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/cmd/scc-as/x86/i286.mk b/src/cmd/scc-as/x86/i286.mk @@ -0,0 +1,12 @@ +I286_OBJ =\ + $(OBJS)\ + x86/i286tbl.o\ + x86/i286.o\ + x86/ins.o\ + +x86/i286tbl.c: x86/ops.dat x86/opers.dat lexh + ./mktbl -f x86 -c i286 + +as-i286: $(I286_OBJ) + $(CC) $(PROJ_LDFLAGS) $(I286_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/x86/i386.c b/src/cmd/scc-as/x86/i386.c @@ -0,0 +1,100 @@ +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "../x86/proc.h" + +TUINT maxaddr = 0xFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ + static struct { + char *name; + unsigned char type; + } regs[] = { + "CS", AREG_CS, + "DS", AREG_DS, + "SS", AREG_SS, + "ES", AREG_ES, + "FS", AREG_FS, + "GS", AREG_GS, + + "AX", AREG_AX, + "AL", AREG_AL, + "AH", AREG_AH, + "EAX", AREG_EAX, + + "BC", AREG_BX, + "BL", AREG_BL, + "BH", AREG_BH, + "EBX", AREG_EBX, + + "CX", AREG_CX, + "CL", AREG_CL, + "CH", AREG_CH, + "ECX", AREG_ECX, + + "DX", AREG_DX, + "DL", AREG_DL, + "DH", AREG_DH, + "EDX", AREG_EDX, + + "SI", AREG_SI, + "ESI", AREG_ESI, + "DI", AREG_DI, + "EDI", AREG_EDI, + + "SP", AREG_SP, + "ESP", AREG_ESP, + + "BP", AREG_BP, + "EBP", AREG_EBP, + + "R0", AREG_R0, + "MM0", AREG_MM0, + "R1", AREG_R1, + "MM1", AREG_MM1, + "R2", AREG_R2, + "MM2", AREG_MM2, + "R3", AREG_R3, + "MM3", AREG_MM3, + "R4", AREG_R4, + "MM4", AREG_MM4, + "R5", AREG_R5, + "MM5", AREG_MM5, + "R6", AREG_R6, + "MM6", AREG_MM6, + "R7", AREG_R7, + "MM7", AREG_MM7, + + "XMM0", AREG_XMM0, + "XMM1", AREG_XMM1, + "XMM2", AREG_XMM2, + "XMM3", AREG_XMM3, + "XMM4", AREG_XMM4, + "XMM5", AREG_XMM5, + "XMM6", AREG_XMM6, + "XMM7", AREG_XMM7, + + "YMM0", AREG_YMM0, + "YMM1", AREG_YMM1, + "YMM2", AREG_YMM2, + "YMM3", AREG_YMM3, + "YMM4", AREG_YMM4, + "YMM5", AREG_YMM5, + "YMM6", AREG_YMM6, + "YMM7", AREG_YMM7, + + "MXCSR", AREG_MXCSR, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/cmd/scc-as/x86/i386.mk b/src/cmd/scc-as/x86/i386.mk @@ -0,0 +1,12 @@ +I386_OBJ =\ + $(OBJS)\ + x86/i386tbl.o\ + x86/i386.o\ + x86/ins.o\ + +x86/i386tbl.c: x86/ops.dat x86/opers.dat lexh + ./mktbl -f x86 -c i386 + +as-i386: $(I386_OBJ) + $(CC) $(PROJ_LDFLAGS) $(I386_OBJ) $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-as/x86/ins.c b/src/cmd/scc-as/x86/ins.c @@ -0,0 +1,354 @@ +#include <stdlib.h> +#include <string.h> + +#include <scc/mach.h> +#include <scc/scc.h> + +#include "../as.h" +#include "proc.h" + +#define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm)) + +/* + * This implementation is based in: + * - x86 Opcode Structure and Instruction Overview - Fraunhofer-Institut + * fÜr kommunikation, informationsverarbeitung und ergonomie fkie. + * - Intel® 64 and IA-32 Architectures Software Developer’s Manual. + * - Encoding Real x86 Instructions - CIS-77 lectures. + */ +enum addr_mode { + MEM_MODE = 0, + MEM8_MODE = 1, + MEM16_MODE = 2, + REG_MODE = 3, +}; + +static int +getclass(Node *np) +{ + if (np->addr != AREG) + return 0; + + switch (np->sym->value) { + case AREG_AL: + case AREG_AH: + case AREG_BL: + case AREG_BH: + case AREG_CL: + case AREG_CH: + case AREG_DL: + case AREG_DH: + return R8CLASS; + + case AREG_AX: + case AREG_BX: + case AREG_CX: + case AREG_DX: + case AREG_DI: + case AREG_SI: + case AREG_SP: + case AREG_BP: + return R16CLASS; + + case AREG_CS: + case AREG_DS: + case AREG_SS: + case AREG_ES: + case AREG_FS: + case AREG_GS: + + case AREG_EFLAGS: + case AREG_CF: + case AREG_PF: + case AREG_AF: + case AREG_ZF: + case AREG_SF: + case AREG_TF: + case AREG_IF: + case AREG_DF: + case AREG_OF: + case AREG_IOPL: + case AREG_NT: + case AREG_RF: + case AREG_VM: + case AREG_AC: + case AREG_VIF: + case AREG_VIP: + case AREG_ID: + + case AREG_EAX: + case AREG_RAX: + + case AREG_EBX: + case AREG_RBX: + + case AREG_ECX: + case AREG_RCX: + + case AREG_EDX: + case AREG_RDX: + + case AREG_SIL: + case AREG_ESI: + case AREG_RSI: + case AREG_DIL: + case AREG_EDI: + case AREG_RDI: + + case AREG_SPL: + case AREG_ESP: + case AREG_RSP: + + case AREG_BPL: + case AREG_EBP: + case AREG_RBP: + + case AREG_R0: + case AREG_MM0: + case AREG_R1: + case AREG_MM1: + case AREG_R2: + case AREG_MM2: + case AREG_R3: + case AREG_MM3: + case AREG_R4: + case AREG_MM4: + case AREG_R5: + case AREG_MM5: + case AREG_R6: + case AREG_MM6: + case AREG_R7: + case AREG_MM7: + + case AREG_R8: + case AREG_R8L: + case AREG_R8W: + case AREG_R9: + case AREG_R9L: + case AREG_R9W: + case AREG_R10: + case AREG_R10L: + case AREG_R10W: + case AREG_R11: + case AREG_R11L: + case AREG_R11W: + case AREG_R12: + case AREG_R12L: + case AREG_R12W: + case AREG_R13: + case AREG_R13L: + case AREG_R13W: + case AREG_R14: + case AREG_R14L: + case AREG_R14W: + case AREG_R15: + case AREG_R15L: + case AREG_R15W: + + case AREG_XMM0: + case AREG_XMM1: + case AREG_XMM2: + case AREG_XMM3: + case AREG_XMM4: + case AREG_XMM5: + case AREG_XMM6: + case AREG_XMM7: + case AREG_XMM8: + case AREG_XMM9: + case AREG_XMM10: + case AREG_XMM11: + case AREG_XMM12: + case AREG_XMM13: + case AREG_XMM14: + case AREG_XMM15: + + case AREG_YMM0: + case AREG_YMM1: + case AREG_YMM2: + case AREG_YMM3: + case AREG_YMM4: + case AREG_YMM5: + case AREG_YMM6: + case AREG_YMM7: + case AREG_YMM8: + case AREG_YMM9: + case AREG_YMM10: + case AREG_YMM11: + case AREG_YMM12: + case AREG_YMM13: + case AREG_YMM14: + case AREG_YMM15: + + case AREG_MXCSR: + return 0; + default: + abort(); + } +} + +int +match(Op *op, Node **args) +{ + unsigned char *p; + int arg, class, rep, opt; + Node *np; + + if (!op->args) + return args == NULL; + + opt = rep = 0; + for (p = op->args; arg = *p; ++p) { + if (rep) + --p; + if ((np = *args++) == NULL) + return (rep|opt) != 0; + + switch (arg) { + case AOPT: + opt = 1; + break; + case AREP: + rep = 1; + break; + case AREG_R8CLASS: + class = R8CLASS; + goto check_class; + case AREG_R16CLASS: + class = R16CLASS; + check_class: + if ((getclass(np) & class) == 0) + return 0; + break; + case AIMM8: + case AIMM16: + case AIMM32: + case AIMM64: + if (np->addr != AIMM) + return 0; + if (toobig(np, arg)) + error("overflow in immediate operand"); + break; + case ASYM: + if (np->op != IDEN) + return 0; + break; + case ADIRECT: + case ASTR: + if (np->addr != arg) + return 0; + break; + default: + abort(); + } + } + + return *args == NULL; +} + +Node * +moperand(void) +{ +} + +static int +reg8toint(Node *np) +{ + switch (np->sym->value) { + case AREG_AL: return 0; + case AREG_CL: return 1; + case AREG_DL: return 2; + case AREG_BL: return 3; + case AREG_AH: return 4; + case AREG_CH: return 5; + case AREG_DH: return 6; + case AREG_BH: return 7; + default: abort(); + } +} + +static int +reg16toint(Node *np) +{ + switch (np->sym->value) { + case AREG_AX: return 0; + case AREG_CX: return 1; + case AREG_DX: return 2; + case AREG_BX: return 3; + case AREG_SP: return 4; + case AREG_BP: return 5; + case AREG_SI: return 6; + case AREG_DI: return 7; + default: abort(); + } +} + +static int +reg32toint(Node *np) +{ + switch (np->sym->value) { + case AREG_EAX: return 0; + case AREG_ECX: return 1; + case AREG_EDX: return 2; + case AREG_EBX: return 3; + case AREG_ESP: return 4; + case AREG_EBP: return 5; + case AREG_ESI: return 6; + case AREG_EDI: return 7; + default: abort(); + } +} + +void +reg8_reg8(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = reg8toint(args[0]); + dst = reg8toint(args[1]); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); +} + +void +imm8_reg8(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = (*args)->sym->value; + dst = reg8toint(args[1]); + memcpy(buf, op->bytes, op->size - 2); + buf[op->size - 2] = addrbyte(REG_MODE, 0, dst); + buf[op->size - 1] = src; + emit(buf, op->size); +} + + +void +reg16_reg16(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = reg16toint(args[0]); + dst = reg16toint(args[1]); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); +} + + +void +reg32_reg32(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = reg32toint(args[0]); + dst = reg32toint(args[1]); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); +} diff --git a/src/cmd/scc-as/target/x86/nasm.dat b/src/cmd/scc-as/x86/nasm.dat diff --git a/src/cmd/scc-as/target/x86/opers.dat b/src/cmd/scc-as/x86/opers.dat diff --git a/src/cmd/scc-as/target/x86/ops.dat b/src/cmd/scc-as/x86/ops.dat diff --git a/src/cmd/scc-as/target/x86/proc.h b/src/cmd/scc-as/x86/proc.h