scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit e3f7a65bec715d1b15a6a31139d5938a1bb83f7c
parent 0342a78f39b5b3f4a4004f76821732dd9d8f5dd4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 29 Dec 2017 15:48:03 +0000

[as-z80] Add relative jumps

These jumps are relative to the pc. These instructions
need further test, because the current tests are very
basic.

Diffstat:
Mas/target/x80/ins.c | 51++++++++++++++++++++++++++++++++++++++++++---------
Mas/target/x80/proc.h | 5+++--
Mas/target/x80/x80.dat | 24++++++++++++------------
Mas/target/z80/proc.c | 3+++
Mas/target/z80/test.s | 12++++++------
5 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -22,7 +22,7 @@ getclass(Node *np) switch (np->sym->value) { case AREG_C: - return RCLASS | PCLASS | QCLASS | CCCLASS; + return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; case AREG_A: case AREG_B: case AREG_D: @@ -50,14 +50,15 @@ getclass(Node *np) return PPCLASS; case AREG_IY: return RRCLASS; - case AREG_NZ: - case AREG_Z: - case AREG_NC: 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; } @@ -91,7 +92,7 @@ reg2int(Node *np) } static int -flag2int(Node *np) +cc2int(Node *np) { switch (np->sym->value) { case AREG_NZ: return 0; @@ -106,6 +107,18 @@ flag2int(Node *np) } } +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) { @@ -338,12 +351,13 @@ im(Op *op, Node **args) } void -branch(Op *op, Node **args) +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) { @@ -356,16 +370,35 @@ branch(Op *op, Node **args) if (imm) { val = imm->sym->value; - buf[--i] = val >> 8; + if (!relative) { + fun = cc2int; + buf[--i] = val >> 8; + } else { + fun = ss2int; + val -= cursec->curpc - 2; + } buf[--i] = val; + + if (flag) + buf[--i] |= (*fun)(flag) << 3; } - if (flag) - buf[--i] |= flag2int(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]; diff --git a/as/target/x80/proc.h b/as/target/x80/proc.h @@ -44,8 +44,8 @@ enum args { AREG_QQCLASS, /* register class for BC, DE, HL and AF */ AREG_PPCLASS, /* register class for BC, DE, IX and SP */ AREG_RRCLASS, /* register class for BC, DE, IY and SP */ - AREG_SSCLASS, /* flag class for NZ, Z, NC, C, PO, PE, P, M */ - AREG_CCCLASS, /* flag class for C, NC, Z, NZ */ + AREG_SSCLASS, /* flag class for C, NC, Z, NZ */ + AREG_CCCLASS, /* flag class for NZ, Z, NC, C, PO, PE, P, M */ AINDEX_IX, /* (IX+d) */ AINDEX_IY, /* (IX+d) */ @@ -72,6 +72,7 @@ enum { PPCLASS = 1 << 5, RRCLASS = 1 << 6, CCCLASS = 1 << 7, + SSCLASS = 1 << 8, }; extern int getclass(Node *np); diff --git a/as/target/x80/x80.dat b/as/target/x80/x80.dat @@ -1,4 +1,4 @@ -# Tab 16, tabs 16, :set ts=16 +# Tab 18, tabs 16, :set ts=18 # op args size bytes format cpu .SECTION sym,string? 0 none section Z80,R800,GB80 .TEXT none 0 none text Z80,R800,GB80 @@ -332,20 +332,20 @@ OUTD none 2 0xed,0xab noargs Z80,R800 OTDR none 2 0xed,0xbb noargs Z80,R800 # Jump group -JP imm16 3 0xc3 branch Z80,R800,GB80 -JP cc,imm16 3 0xc2 branch Z80,R800,GB80 -JR imm8 2 0x18 branch Z80,R800,GB80 -JR ss,imm8 2 0x00 branch Z80,R800,GB80 -JP (HL) 1 0xe9 branch Z80,R800,GB80 -JP (IX) 2 0xdd,0xe9 branch Z80,R800 -JP (IY) 2 0xfd,0xe9 branch Z80,R800 -DJNZ imm8 2 0x10 branch Z80,R800,GB80 +JP imm16 3 0xc3 jp Z80,R800,GB80 +JP cc,imm16 3 0xc2 jp Z80,R800,GB80 +JR imm16 2 0x18 jr Z80,R800,GB80 +JR ss,imm16 2 0x00 jr Z80,R800,GB80 +JP (HL) 1 0xe9 jp Z80,R800,GB80 +JP (IX) 2 0xdd,0xe9 jp Z80,R800 +JP (IY) 2 0xfd,0xe9 jp Z80,R800 +DJNZ imm16 2 0x10 jr Z80,R800,GB80 # Call and return group -CALL imm16 3 0xcd branch Z80,R800,GB80 -CALL cc,imm16 3 0xc4 branch Z80,R800 +CALL imm16 3 0xcd jp Z80,R800,GB80 +CALL cc,imm16 3 0xc4 jp Z80,R800 RET none 1 0xc9 noargs Z80,R800,GB80 -RET cc 1 0xc0 branch Z80,R800 +RET cc 1 0xc0 jp Z80,R800 RETI none 2 0xed,0x4d noargs Z80,R800 RETN none 2 0xed,0x45 noargs Z80,R800 RST rst 1 0xc7 rst Z80,R800,GB80 diff --git a/as/target/z80/proc.c b/as/target/z80/proc.c @@ -138,6 +138,9 @@ match(Op *op, Node **args) case AREG_CCCLASS: class = CCCLASS; goto check_class; + case AREG_SSCLASS: + class = SSCLASS; + goto check_class; case AREG_DDCLASS: class = DDCLASS; check_class: diff --git a/as/target/z80/test.s b/as/target/z80/test.s @@ -14,7 +14,7 @@ DEC %C / 0D LD %C,64 / 0E 40 RRCA / 0F -/10 n DJNZ PC + n +L1: DJNZ L1 / 10 02 LD %DE,32 / 11 20 00 LD (%DE),%A / 12 INC %DE / 13 @@ -22,7 +22,7 @@ DEC %D / 15 LD %D,64 / 16 40 RLA / 17 -/18 n JR PC + n +L2: JR L2 / 18 02 ADD %HL,%DE / 19 LD %A,(%DE) / 1A DEC %DE / 1B @@ -30,7 +30,7 @@ DEC %E / 1D LD %E,64 / 1E 40 RRA / 1F -/20 n JR NZ, PC + n +L3: JR %NZ,L3 / 20 02 LD %HL,32 / 21 20 00 LD (32768),%HL / 22 00 80 INC %HL / 23 @@ -38,7 +38,7 @@ DEC %H / 25 LD %H,64 / 26 40 DAA / 27 -/28 n JR Z, PC + n +L4: JR %Z,L4 / 28 02 ADD %HL,%HL / 29 LD %HL, (16384) / 2A 00 40 DEC %HL / 2B @@ -46,7 +46,7 @@ DEC %L / 2D LD %L,32 / 2E 20 CPL / 2F -/30 n JR NC, PC + n +L5: JR %NC,L5 / 30 02 LD %SP,64 / 31 40 00 LD (32768),%A / 32 00 80 INC %SP / 33 @@ -54,7 +54,7 @@ DEC (%HL) / 35 LD (%HL),32 / 36 20 SCF / 37 -/38 n JR C, PC + n +L6: JR %C,L6 / 38 02 ADD %HL,%SP / 39 LD %A,(16384) / 3A 00 40 DEC %SP / 3B