Mercurial > hg-old > index.cgi
diff src/insn_gen.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_gen.c Fri Oct 03 02:44:20 2008 +0000 @@ -0,0 +1,154 @@ +/* + * insn_gen.c + * + * 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); +}