Mercurial > hg-old > index.cgi
diff src/insn_misc.c @ 0:57495da01900
Initial checking of LWASM
author | lost |
---|---|
date | Fri, 03 Oct 2008 02:44:20 +0000 |
parents | |
children | 34568fab6058 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/insn_misc.c Fri Oct 03 02:44:20 2008 +0000 @@ -0,0 +1,315 @@ +/* + * insn_misc.c + * + * parsing miscelaneous addressing modes + */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include "lwasm.h" +#include "instab.h" + +extern void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op); + +void insn_inh(asmstate_t *as, sourceline_t *cl, char **optr) +{ + cl -> addrmode = OPER_INH; + emitop(instab[cl -> opcode].ops[0]); +} + +void insn_rtor(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int r0, r1; + static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F "; + + cl -> addrmode = OPER_RTOR; + emitop(instab[cl -> opcode].ops[0]); + // register to register (r0,r1) + // registers are in order: + // D,X,Y,U,S,PC,W,V + // A,B,CC,DP,0,0,E,F + r0 = lookupreg(regs, optr); + if (r0 < 0 || *(*optr)++ != ',') + { + errorp1(ERR_BADOPER); + r0 = r1 = 0; + } + else + { + r1 = lookupreg(regs, optr); + if (r1 < 0) + { + errorp1(ERR_BADOPER); + r0=r1=0; + } + } + emit((r0 << 4) | r1); +} + +void insn_rlist(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int rb = 0; + int rn; + static const char *regs = "CCA B DPX Y U PCD S "; + + emitop(instab[cl -> opcode].ops[0]); + cl -> addrmode = OPER_RLIST; + while (**optr && !isspace(**optr)) + { + rn = lookupreg(regs, optr); + if (rn < 0) + { + printf("Bad reg (%s)\n", *optr); + errorp1(ERR_BADOPER); + emit(0); + return; + } + if (**optr && **optr != ',' && !isspace(**optr)) + { + printf("Bad char (%c)\n", **optr); + errorp1(ERR_BADOPER); + emit(0); + return; + } + if (**optr == ',') + (*optr)++; + if (rn == 8) + rn = 6; + else if (rn == 9) + rn = 0x40; + else + rn = 1 << rn; + rb |= rn; + } + emit(rb); +} + +// for aim, oim, eim, tim +void insn_logicmem(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int rval, v1; + int b1, b2, b3, op; + + if (**optr == '#') + (*optr)++; + + rval = eval_expr(as, cl, optr, &v1); + if (rval < 0) + return; + + if (v1 < -128 || v1 > 255) + { + errorp2(ERR_OVERFLOW); + v1 = 0; + } + + if (**optr != ',' && **optr != ';') + { + errorp1(ERR_BADOPER); + return; + } + + (*optr)++; + + // now we have a general addressing mode - call for it + insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op); + + emitop(op); + emit(v1 & 0xff); + if (b1 != -1) + { + emit(b1); + } + if (b2 != -1) + { + emit(b2); + } + if (b3 != -1) + { + emit(b3); + } +} + +void insn_tfm(asmstate_t *as, sourceline_t *cl, char **optr) +{ + static const char *reglist = "DXYUS AB 00EF"; + int r0, r1; + char *c; + int tfm = 0; + + cl -> addrmode = OPER_TFM; + + c = strchr(reglist, toupper(*(*optr)++)); + if (!c) + { + errorp1(ERR_BADOPER); + return; + } + r0 = c - reglist; + if (**optr == '+') + { + (*optr)++; + tfm = 1; + } + else if (**optr == '-') + { + (*optr)++; + tfm = 2; + } + if (*(*optr)++ != ',') + { + errorp1(ERR_BADOPER); + return; + } + c = strchr(reglist, toupper(*(*optr)++)); + if (!c) + { + errorp1(ERR_BADOPER); + return; + } + r1 = c - reglist; + + if (**optr == '+') + { + (*optr)++; + tfm |= 4; + } + else if (**optr == '-') + { + (*optr)++; + tfm |= 8; + } + + if (**optr && !isspace(**optr)) + { + errorp1(ERR_BADOPER); + return; + } + + // valid values of tfm here are: + // 1: r0+,r1 (2) + // 4: r0,r1+ (3) + // 5: r0+,r1+ (0) + // 10: r0-,r1- (1) + switch (tfm) + { + case 5: //r0+,r1+ + emitop(instab[cl -> opcode].ops[0]); + break; + case 10: //r0-,r1- + emitop(instab[cl -> opcode].ops[1]); + break; + case 1: // r0+,r1 + emitop(instab[cl -> opcode].ops[2]); + break; + case 4: // r0,r1+ + emitop(instab[cl -> opcode].ops[3]); + break; + default: + errorp1(ERR_BADOPER); + return; + } + emit((r0 << 4) | r1); +} + +void insn_bitbit(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int r; + int rval; + int v1; + int tv; + + emitop(instab[cl -> opcode].ops[0]); + + cl -> addrmode = OPER_BITBIT; + + r = toupper(*(*optr)++); + if (r == 'A') + r = 1; + else if (r == 'B') + r = 2; + else if (r == 'C' && toupper(**optr) == 'C') + { + r = 0; + (*optr)++; + } + else + { + errorp1(ERR_BADREG); + return; + } + if (*(*optr)++ != ',') + { + errorp1(ERR_BADOPER); + return; + } + rval = eval_expr(as, cl, optr, &v1); + if (v1 < 0 || v1 > 7) + { + errorp2(ERR_OVERFLOW3); + v1 = 0; + } + if (*(*optr)++ != ',') + { + errorp1(ERR_BADOPER); + return; + } + r = (r << 6) | (v1 << 3); + rval = eval_expr(as, cl, optr, &v1); + if (v1 < 0 || v1 > 7) + { + errorp2(ERR_OVERFLOW3); + v1 = 0; + } + if (*(*optr)++ != ',') + { + errorp1(ERR_BADOPER); + return; + } + r |= v1; + + emit(r); + + // ignore base page address modifier + if (**optr == '<') + optr++; + + rval = eval_expr(as, cl, optr, &v1); + v1 &= 0xFFFF; + tv = v1 - ((cl -> dpval) << 8); + if (tv > 0xFF || tv < 0) + errorp2(ERR_OVERFLOW); + emit(tv & 0xff); +} + +void insn_rel8(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int v1, rval; + + emitop(instab[cl -> opcode].ops[0]); + cl -> addrmode = OPER_REL8; + rval = eval_expr(as, cl, optr, &v1); + v1 &= 0xFFFF; + v1 -= cl -> addr + 2; + if (v1 < -128 || v1 > 127) + errorp2(ERR_OVERFLOW); + v1 &= 0xFFFF; + emit(v1 & 0xff); +} + +void insn_rel16(asmstate_t *as, sourceline_t *cl, char **optr) +{ + int v1, rval; + + emitop(instab[cl -> opcode].ops[0]); + cl -> addrmode = OPER_REL16; + rval = eval_expr(as, cl, optr, &v1); + v1 &= 0xFFFF; + v1 -= cl -> addr + 3; + if (instab[cl -> opcode].ops[0] > 0xff) + v1 -= 1; + v1 &= 0xFFFF; + emit(v1 >> 8); + emit(v1 & 0xff); +}