ref: 8db36cf9b7f61d5dcd4af5324a1cc1c68dc7ed30
dir: /as/target/x80/ins.c/
static char sccsid[] = "@(#) ./as/target/z80/ins.c"; #include <stdlib.h> #include <string.h> #include "../../../inc/scc.h" #include "../../as.h" #include "proc.h" int getclass(Node *np) { if (np->addr != AREG) return 0; switch (np->sym->value) { case AREG_C: return RCLASS | PCLASS | QCLASS | CCCLASS; 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_NZ: case AREG_Z: case AREG_NC: case AREG_PO: case AREG_PE: case AREG_P: case AREG_M: return CCCLASS; default: return 0; } } 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 flag2int(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(); } } 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; break; 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(Op *op, Node **args) { unsigned char buf[4]; Node *flag, *imm; int n = op->size, i = n; unsigned val; 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; buf[--i] = val >> 8; buf[--i] = val; } if (flag) buf[--i] |= flag2int(flag) << 3; emit(buf, n); } void rst(Op *op, Node **args) { unsigned char buf[1]; buf[0] = op->bytes[0]; buf[0] |= args[0]->sym->value; emit(buf, 1); }