Mercurial > hg-old > index.cgi
view src/insn_misc.c @ 8:f1df096aa76f 1.1
Tagged 1.1 bugfix release
author | lost |
---|---|
date | Sun, 04 Jan 2009 05:46:07 +0000 |
parents | 34568fab6058 |
children | f736579569b4 |
line wrap: on
line source
/* insn_misc.c Copyright © 2008 William Astle This file is part of LWASM. LWASM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Contains code for 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); }