Mercurial > hg-old > index.cgi
diff lwasm/os9.c @ 236:a58f49a77441
Added os9 target, pragma to control whether $ localizes a symbol, and fixed some condition nesting bugs
author | lost |
---|---|
date | Fri, 14 Aug 2009 03:22:26 +0000 |
parents | |
children | a9a14e6b4bc8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/os9.c Fri Aug 14 03:22:26 2009 +0000 @@ -0,0 +1,177 @@ +/* +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 <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "lwasm.h" +#include "instab.h" +#include "expr.h" +#include "util.h" + +OPFUNC(pseudo_os9) +{ + int r, rval; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "os9 directive only valid for OS9 target"); + return; + } + + // fetch immediate value + r = lwasm_expr_result2(as, l, p, 0, &rval, 0); + if (r != 0) + rval = 0; + if (r == 1 && as -> passnum == 2) + register_error(as, l, 2, "Illegal external or intersegment reference"); + + // SWI2; FCB ... + lwasm_emit(as, l, 0x10); + lwasm_emit(as, l, 0x3f); + lwasm_emit(as, l, rval); +} + +OPFUNC(pseudo_mod) +{ + int modvals[6]; + int r, v, i; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "mod directive only valid for OS9 target"); + return; + } + + if (as -> inmod) + { + register_error(as, l, 1, "Already in a module!"); + return; + } + + // parse 6 expressions... + for (i = 0; i < 5; i++) + { + r = lwasm_expr_result2(as, l, p, 0, &v, -1); + if (r < 0) + return; + if (r > 0) + { + register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)"); + v = 0; + } + else + { + modvals[i] = v; + } + if (**p != ',') + { + register_error(as, l, 1, "Bad operand"); + return; + } + (*p)++; + } + r = lwasm_expr_result2(as, l, p, 0, &v, -1); + if (r < 0) + return; + if (r > 0) + { + register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)"); + v = 0; + } + else + { + modvals[5] = v; + } + + l -> inmod = 1; + + // we have an implicit ORG 0 with "mod" + l -> codeaddr = 0; + l -> addrset = 1; + as -> addr = 0; + + // init crc + as -> crc = 0xffffff; + as -> inmod = 1; + + // sync bytes + lwasm_emit(as, l, 0x87); + lwasm_emit(as, l, 0xcd); + + // mod length + lwasm_emit(as, l, modvals[0] >> 8); + lwasm_emit(as, l, modvals[0] & 0xff); + + // name offset + lwasm_emit(as, l, modvals[1] >> 8); + lwasm_emit(as, l, modvals[1] & 0xff); + + // type + lwasm_emit(as, l, modvals[2]); + + // flags/rev + lwasm_emit(as, l, modvals[3]); + + // header check + lwasm_emit(as, l, ~(0x87 ^ 0xCD ^ (modvals[0] >> 8) ^ (modvals[0] & 0xff) + ^ (modvals[1] >> 8) ^ (modvals[1] & 0xff) + ^ modvals[2] ^ modvals[3])); + + // 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_emit(as, l, modvals[4] >> 8); + lwasm_emit(as, l, modvals[4] & 0xff); + + // data size or drvr name offset + lwasm_emit(as, l, modvals[5] >> 8); + lwasm_emit(as, l, modvals[5] & 0xff); +} + +OPFUNC(pseudo_emod) +{ + unsigned long tcrc; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "emod directive only valid for OS9 target"); + return; + } + + if (!(as -> inmod)) + { + register_error(as, l, 1, "not in a module!"); + return; + } + + // don't mess with CRC! + tcrc = as -> crc; + lwasm_emit(as, l, tcrc >> 16); + lwasm_emit(as, l, tcrc >> 8); + lwasm_emit(as, l, tcrc); + as -> inmod = 0; +}