Mercurial > hg-old > index.cgi
view src/insn_gen.c @ 8:f1df096aa76f 1.1
Tagged 1.1 bugfix release
author | lost |
---|---|
date | Sun, 04 Jan 2009 05:46:07 +0000 |
parents | 34568fab6058 |
children | 74a3fef7c8d0 |
line wrap: on
line source
/* insn_gen.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 general addressing modes (IMM+DIR+EXT+IND) */ #include <ctype.h> #include "lwasm.h" #include "instab.h" extern void insn_indexed_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3); void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op) { *b1 = *b2 = *b3 = -1; char *optr2; int v1, tv, rval; optr2 = *optr; while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++ ; if (*optr2 != ',' && **optr != '[') { // not indexed if (**optr == '<') { (*optr)++; rval = eval_expr(as, cl, optr, &v1); v1 = v1 & 0xffff; tv = v1 - ((cl -> dpval) << 8); if (tv < 0 || tv > 0xff) { errorp2(ERR_OVERFLOW); } v1 = v1 & 0xff; goto ins_gen_dir; } else if (**optr == '>') { // extended mode (*optr)++; rval = eval_expr(as, cl, optr, &v1); goto ins_gen_ext; } else { // eval expr and see how big it is rval = eval_expr(as, cl, optr, &v1); v1 = v1 & 0xFFFF; if (cl -> undef && as -> passnum == 1) { cl -> p1f16 = 1; goto ins_gen_ext; } tv = v1 - (cl -> dpval << 8); if (tv < 0 || tv > 0xff || cl -> p1f16) goto ins_gen_ext; else { v1 = v1 & 0xff; goto ins_gen_dir; } } return; } *op = instab[cl -> opcode].ops[1]; insn_indexed_aux(as, cl, optr, b1, b2, b3); return; ins_gen_dir: *op = instab[cl -> opcode].ops[0]; // cl -> code_operlen = 1; cl -> addrmode = OPER_DIR; if ((v1 & 0xFFFF) > 0xff) errorp2(ERR_OVERFLOW); *b1 = (v1); return; ins_gen_ext: *op = instab[cl -> opcode].ops[2]; // cl -> code_operlen = 2; cl -> addrmode = OPER_EXT; *b1 = (v1 >> 8); *b2 = (v1 & 0xff); return; } void insn_gen(asmstate_t *as, sourceline_t *cl, char **optr) { int rval; int v1; int b1, b2, b3, op; if (**optr == '#') { // immediate mode has perterbations on instruction size (*optr)++; emitop(instab[cl -> opcode].ops[3]); rval = eval_expr(as, cl, optr, &v1); switch (instab[cl -> opcode].instype) { case INSTYPE_GEN8: case INSTYPE_IMM8: cl -> addrmode = OPER_IMM8; // cl -> code_operlen = 1; emit(v1 & 0xff); if (v1 < -128 || v1 > 255) errorp2(ERR_OVERFLOW); return; case INSTYPE_GEN: cl -> addrmode = OPER_IMM16; // cl -> code_operlen = 2; emit(v1 >> 8); emit(v1 & 0xff); return; case INSTYPE_GEN32: cl -> addrmode = OPER_IMM32; // cl -> code_operlen = 4; emit(v1 >> 24); emit((v1 >> 16) & 0xff); emit((v1 >> 8) & 0xff); emit(v1 & 0xff); return; default: errorp1(ERR_BADOPER); return; } return; } if (instab[cl -> opcode].instype == INSTYPE_IMM8) { errorp1(ERR_BADOPER); return; } insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op); emitop(op); if (b1 != -1) emit(b1); if (b2 != -1) emit(b2); if (b3 != -1) emit(b3); }