Mercurial > hg > index.cgi
diff lwasm/os9.c @ 0:2c24602be78f
Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author | lost@l-w.ca |
---|---|
date | Wed, 19 Jan 2011 22:27:17 -0700 |
parents | |
children | 3fc568436721 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/os9.c Wed Jan 19 22:27:17 2011 -0700 @@ -0,0 +1,191 @@ +/* +os9.c +Copyright © 2009 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/>. + + +This file implements the various pseudo operations related to OS9 target +*/ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <lw_expr.h> + +#include "lwasm.h" +#include "instab.h" + + +// OS9 syscall +PARSEFUNC(pseudo_parse_os9) +{ + lw_expr_t e; + + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "os9 directive only valid for OS9 target"); + return; + } + + // fetch immediate value + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + lwasm_save_expr(l, 0, e); + l -> len = 3; +} + +EMITFUNC(pseudo_emit_os9) +{ + lw_expr_t e; + + e = lwasm_fetch_expr(l, 0); + + lwasm_emitop(l, 0x103f); + lwasm_emitexpr(l, e, 1); +} + +PARSEFUNC(pseudo_parse_mod) +{ + lw_expr_t e; + int i; + + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "mod directive only valid for OS9 target"); + return; + } + + if (as -> inmod) + { + lwasm_register_error(as, l, "Already in a module!"); + return; + } + + // parse 6 expressions... + for (i = 0; i < 5; i++) + { + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + + lwasm_save_expr(l, i, e); + + if (**p != ',') + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + (*p)++; + } + + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + lwasm_save_expr(l, 5, e); + + l -> inmod = 1; + + // we have an implicit ORG 0 with "mod" + lw_expr_destroy(l -> addr); + l -> addr = lw_expr_build(lw_expr_type_int, 0); + + // init crc + as -> inmod = 1; +} + +EMITFUNC(pseudo_emit_mod) +{ + lw_expr_t e1, e2, e3, e4; + int csum; + + as -> crc[0] = 0xff; + as -> crc[1] = 0xff; + as -> crc[2] = 0xff; + + // sync bytes + lwasm_emit(l, 0x87); + lwasm_emit(l, 0xcd); + + // mod length + lwasm_emitexpr(l, e1 = lwasm_fetch_expr(l, 0), 2); + + // name offset + lwasm_emitexpr(l, e2 = lwasm_fetch_expr(l, 1), 2); + + // type + lwasm_emitexpr(l, e3 = lwasm_fetch_expr(l, 2), 1); + + // flags/rev + lwasm_emitexpr(l, e4 = lwasm_fetch_expr(l, 3), 1); + + // header check + csum = ~(0x87 ^ 0xCD ^(lw_expr_intval(e1) >> 8) ^ (lw_expr_intval(e1) & 0xff) + ^ (lw_expr_intval(e2) >> 8) ^ (lw_expr_intval(e2) & 0xff) + ^ lw_expr_intval(e3) ^ lw_expr_intval(e4)); + lwasm_emit(l, csum); + + // module type specific output + // note that these are handled the same for all so + // there need not be any special casing + + // exec offset or fmgr name offset + lwasm_emitexpr(l, lwasm_fetch_expr(l, 4), 2); + + // data size or drvr name offset + lwasm_emitexpr(l, lwasm_fetch_expr(l, 5), 2); +} + +PARSEFUNC(pseudo_parse_emod) +{ + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "emod directive only valid for OS9 target"); + return; + } + + if (!(as -> inmod)) + { + lwasm_register_error(as, l, "not in a module!"); + return; + } + + as -> inmod = 0; +} + +EMITFUNC(pseudo_emit_emod) +{ + unsigned char tcrc[3]; + + // don't mess with CRC! + tcrc[0] = as -> crc[0] ^ 0xff; + tcrc[1] = as -> crc[1] ^ 0xff; + tcrc[2] = as -> crc[2] ^ 0xff; + lwasm_emit(l, tcrc[0]); + lwasm_emit(l, tcrc[1]); + lwasm_emit(l, tcrc[2]); +}