scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit e9a7fd1da92555cd65a50bb8f5a6b0be231cb517
parent 073b2d83295eb468f340016b8d2a66e06a88f098
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun,  1 Oct 2017 11:57:35 +0200

[as-z80] Add (HL) addressing mode

Diffstat:
as/as.h | 4++++
as/expr.c | 30+++++++++++++++++++++++++++++-
as/target/gen.awk | 2++
as/target/x80/ins.c | 33++++++++++++++++++++++++++++++++-
as/target/x80/proc.h | 2++
as/target/x80/x80.dat | 14++++++++++----
as/target/z80/proc.c | 6++++++
7 files changed, 85 insertions(+), 6 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -39,6 +39,10 @@ enum common_args { AIMM16, AIMM32, AIMM64, + AINDIR, + AINDEX, + ADIRECT, + AREG_OFF, AMAX, AREP = 128 }; diff --git a/as/expr.c b/as/expr.c @@ -145,6 +145,8 @@ binary(int op, Node *l, Node *r) return fold(op, l, r); if (l->addr == AIMM && r->addr == AIMM) addr = AIMM; + else if (l->addr == AREG && r->addr == AIMM) + addr = AREG_OFF; else error("incorrect operand"); np = node(op, l, r); @@ -327,6 +329,26 @@ expect(int token) next(); } +Node * +content(Node *np) +{ + int op; + + switch (np->addr) { + case AREG: + op = AINDIR; + goto new_node; + case AREG_OFF: + op = AINDEX; + goto new_node; + case AIMM: + op = ADIRECT; + new_node: + return node(op, np, NULL); + } + return np; +} + /*************************************************************************/ /* grammar functions */ /*************************************************************************/ @@ -336,7 +358,7 @@ static Node *or(void); static Node * primary(void) { - int addr; + int addr, op; Node *np; switch (yytoken) { @@ -355,6 +377,12 @@ primary(void) np->addr = addr; next(); break; + case '(': + next(); + np = or(); + expect(')'); + np = content(np); + break; default: unexpected(); } diff --git a/as/target/gen.awk b/as/target/gen.awk @@ -83,6 +83,8 @@ function str2args(s, args, i, out, n) out = out "AREG_RCLASS" } else if (match(a, /^regA/)) { out = out "AREG_A" + } else if (match(a, /^indir_HL/)) { + out = out "AINDER_HL" } else { print "wrong arg", a exit 1 diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -123,7 +123,7 @@ r8_r8(Op *op, Node **args) } void -r8(Op *op, Node **args) +xx_r8_2(Op *op, Node **args) { Node *par1, *par2; unsigned char buf[3]; @@ -131,7 +131,38 @@ r8(Op *op, Node **args) par1 = args[0]; par2 = args[1]; + memcpy(buf, op->bytes, n); buf[n-1] |= reg2int(par2->sym->argtype); emit(cursec, buf, n); } + +void +r8_xx_2(Op *op, Node **args) +{ + Node *par1, *par2; + unsigned char buf[3]; + int n = op->size; + + par1 = args[0]; + par2 = args[1]; + + memcpy(buf, op->bytes, n); + buf[n-1] |= reg2int(par2->sym->argtype) << 3; + emit(cursec, buf, n); +} + +void +r8_xx_1(Op *op, Node **args) +{ + Node *par1, *par2; + unsigned char buf[3]; + int n = op->size; + + par1 = args[0]; + par2 = args[1]; + + memcpy(buf, op->bytes, n); + buf[n-1] |= reg2int(par1->sym->argtype) << 3; + emit(cursec, buf, n); +} diff --git a/as/target/x80/proc.h b/as/target/x80/proc.h @@ -31,6 +31,8 @@ enum args { AREG_RCLASS, /* register class for B, C, D, E, H, L and A */ AREG_PCLASS, /* register class for B, C, D, E, IXH, IXL and A */ AREG_QCLASS, /* register class for B, C, D, E, IYH, IYL and A */ + + AINDER_HL, /* (HL) */ }; extern int rclass(int reg); diff --git a/as/target/x80/x80.dat b/as/target/x80/x80.dat @@ -59,11 +59,17 @@ OTDR none 2 0xed,0xbb noargs Z80,R800 LD reg_r,imm8 2 0x06 r8_imm8 Z80,R800,GB80 LD reg_p,imm8 3 0xdd,0x06 r8_imm8 Z80,R800 LD reg_q,imm8 3 0xfd,0x06 r8_imm8 Z80,R800 +LD indir_HL,imm8 2 0x36 imm8 Z80,R800,GB80 + LD reg_r,reg_r 1 0x40 r8_r8 Z80,R800,GB80 LD reg_p,reg_p 2 0xdd,0x40 r8_r8 Z80,R800 LD reg_q,reg_q 2 0xfd,0x40 r8_r8 Z80,R800 +LD indir_HL,reg_r 1 0x70 xx_r8_2 Z80,R800,GB80 +LD reg_r,indir_HL 1 0x46 r8_xx_1 Z80,R800,GB80 + +ADD regA,reg_r 1 0x80 xx_r8_2 Z80,R800,GB80 +ADD regA,reg_p 2 0xdd,0x80 xx_r8_2 Z80,R800 +ADD regA,reg_q 2 0xfd,0x80 xx_r8_2 Z80,R800 +ADD regA,imm8 2 0xc6 imm8 Z80,R800,GB80 -ADD regA,reg_r 1 0x80 r8 Z80,R800,GB80 -ADD regA,reg_p 2 0xdd,0x80 r8 Z80,R800 -ADD regA,reg_q 2 0xfd,0x80 r8 Z80,R800 -ADD regA,imm8 2 0xc6 imm8 Z80,R800 +ADD regA,indir_HL 1 0x86 noargs Z80,R800,GB80 diff --git a/as/target/z80/proc.c b/as/target/z80/proc.c @@ -65,6 +65,12 @@ match(Op *op, Node **args) --p; np = *args++; switch (arg & ~AREP) { + case AINDER_HL: + if (np->op != AINDIR) + return 0; + if (np->left->sym->argtype != AREG_HL) + return 0; + break; case AREG_A: if (np->op != AREG || np->sym->argtype != AREG_A) return 0;