home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
332.lha
/
DAsm_v2.12
/
src
/
exp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-27
|
13KB
|
769 lines
/*
* EXP.C
*
* (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*
* Handle expression evaluation and addressing mode decode.
*
* NOTE! If you use the string field in an expression you must clear
* the SYM_MACRO and SYM_STRING bits in the flags before calling
* freesymbollist()!
*/
#include "asm.h"
/*
* evaluate an expression. Figure out the addressing mode:
*
* implied
* #val immediate
* val zero page or absolute
* val,x zero,x or absolute,x
* val,y zero,y or absolute,y
* (val) indirect
* (val,x) zero indirect x
* (val),y zero indirect y
*
* exp, exp,.. LIST of expressions
*
* an absolute may be returned as zero page
* a relative may be returned as zero page or absolute
*
* unary: - ~ ! < >
* binary: (^)(* / %)(+ -)(>> <<)(& |)(`)(&& ||)(== != < > <= >=)
*
* values: symbol, octal, decimal, $hex, %binary, 'c "str"
*
*/
#define MAXOPS 32
#define MAXARGS 64
ubyte Argflags[MAXARGS];
long Argstack[MAXARGS];
ubyte *Argstring[MAXARGS];
short Oppri[MAXOPS];
void (*Opdis[MAXOPS]) ARGS((long, long, long, long));
uword Argi, Opi, Lastwasop;
uword Argibase, Opibase;
SYMBOL *
eval(str)
register char *str;
{
register SYMBOL *base, *cur;
uword oldargibase = Argibase;
uword oldopibase = Opibase;
uword scr;
Argibase = Argi;
Opibase = Opi;
Lastwasop = 1;
base = cur = allocsymbol();
while (*str) {
if (Xdebug)
printf("char '%c'\n", *str);
switch(*str) {
case ' ':
case '\n':
++str;
break;
case '~':
if (Lastwasop)
doop(op_invert, 128);
else
asmerr(0,0);
++str;
break;
case '*':
doop(op_mult, 20);
++str;
break;
case '/':
doop(op_div, 20);
++str;
break;
case '%':
if (Lastwasop) {
str = (char *)pushbin(str+1);
} else {
doop(op_mod, 20);
++str;
}
break;
case '?': /* 10 */
doop(op_question, 10);
++str;
break;
case '+': /* 19 */
doop(op_add, 19);
++str;
break;
case '-': /* 19: - (or - unary) */
if (Lastwasop) {
doop(op_negate, 128);
} else {
doop(op_sub, 19);
}
++str;
break;
case '>': /* 18: >> << 17: > >= <= < */
if (Lastwasop) {
doop(op_takemsb, 128);
++str;
break;
}
if (str[1] == '>') {
doop(op_shiftright, 18);
++str;
} else if (str[1] == '=') {
doop(op_greatereq, 17);
++str;
} else {
doop(op_greater, 17);
}
++str;
break;
case '<':
if (Lastwasop) {
doop(op_takelsb, 128);
++str;
break;
}
if (str[1] == '<') {
doop(op_shiftleft, 18);
++str;
} else if (str[1] == '=') {
doop(op_smallereq, 17);
++str;
} else {
doop(op_smaller, 17);
}
++str;
break;
case '=': /* 16: == (= same as ==) */
if (str[1] == '=')
++str;
doop(op_eqeq, 16);
++str;
break;
case '!': /* 16: != */
if (Lastwasop) {
doop(op_not, 128);
} else {
doop(op_noteq, 16);
++str;
}
++str;
break;
case '&': /* 15: & 12: && */
if (str[1] == '&') {
doop(op_andand, 12);
++str;
} else {
doop(op_and, 15);
}
++str;
break;
case '^': /* 14: ^ */
doop(op_xor, 14);
++str;
break;
case '|': /* 13: | 11: || */
if (str[1] == '|') {
doop(op_oror, 11);
++str;
} else {
doop(op_or, 13);
}
++str;
break;
case '[': /* eventually an argument */
if (Opi == MAXOPS)
puts("too many ops");
else
Oppri[Opi++] = 0;
++str;
break;
case ']':
while(Opi != Opibase && Oppri[Opi-1])
evaltop();
if (Opi != Opibase)
--Opi;
++str;
if (Argi == Argibase) {
puts("']' error, no arg on stack");
break;
}
if (*str == 'd') { /* STRING CONVERSION */
char buf[32];
++str;
if (Argflags[Argi-1] == 0) {
sprintf(buf,"%ld",Argstack[Argi-1]);
Argstring[Argi-1] = (ubyte *)strcpy(malloc(strlen(buf)+1),buf);
}
}
break;
case '#':
cur->addrmode = AM_IMM8;
++str;
break;
case '(':
cur->addrmode = AM_INDWORD;
++str;
break;
case ')':
if (cur->addrmode == AM_INDWORD && str[1] == ',' && (str[2]|0x20) == 'y') {
cur->addrmode = AM_INDBYTEY;
str += 2;
}
++str;
break;
case ',':
while(Opi != Opibase)
evaltop();
Lastwasop = 1;
scr = str[1]|0x20; /* to lower case */
if (cur->addrmode == AM_INDWORD && scr == 'x' && !alphanum(str[2])) {
cur->addrmode = AM_INDBYTEX;
++str;
} else if (scr == 'x' && !alphanum(str[2])) {
cur->addrmode = AM_0X;
++str;
} else if (scr == 'y' && !alphanum(str[2])) {
cur->addrmode = AM_0Y;
++str;
} else {
register SYMBOL *new = allocsymbol();
cur->next = new;
--Argi;
if (Argi < Argibase)
asmerr(0,0);
if (Argi > Argibase)
asmerr(0,0);
cur->value = Argstack[Argi];
cur->flags = Argflags[Argi];
if (cur->string= (ubyte *)Argstring[Argi]) {
cur->flags |= SYM_STRING;
if (Xdebug)
printf("STRING: %s\n", cur->string);
}
cur = new;
}
++str;
break;
case '$':
str = (char *)pushhex(str+1);
break;
case '\'':
str = (char *)pushchar(str+1);
break;
case '\"':
str = (char *)pushstr(str+1);
break;
default:
if (*str == '0')
str = (char *)pushoct(str);
else {
if (*str > '0' && *str <= '9')
str = (char *)pushdec(str);
else
str = (char *)pushsymbol(str);
}
break;
}
}
while(Opi != Opibase)
evaltop();
if (Argi != Argibase) {
--Argi;
cur->value = Argstack[Argi];
cur->flags = Argflags[Argi];
if (cur->string= (ubyte *)Argstring[Argi]) {
cur->flags |= SYM_STRING;
if (Xdebug)
printf("STRING: %s\n", cur->string);
}
if (base->addrmode == 0)
base->addrmode = AM_BYTEADR;
}
if (Argi != Argibase || Opi != Opibase)
asmerr(0,0);
Argi = Argibase;
Opi = Opibase;
Argibase = oldargibase;
Opibase = oldopibase;
return(base);
}
int
alphanum(c)
int c;
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'));
}
void
evaltop()
{
if (Xdebug)
printf("evaltop @(A,O) %d %d\n", Argi, Opi);
if (Opi <= Opibase) {
asmerr(0,0);
Opi = Opibase;
return;
}
--Opi;
if (Oppri[Opi] == 128) {
if (Argi < Argibase + 1) {
asmerr(0,0);
Argi = Argibase;
return;
}
--Argi;
(*Opdis[Opi])(Argstack[Argi], Argflags[Argi], 0, 0);
} else {
if (Argi < Argibase + 2) {
asmerr(0,0);
Argi = Argibase;
return;
}
Argi -= 2;
(*Opdis[Opi])(Argstack[Argi], Argstack[Argi+1], Argflags[Argi], Argflags[Argi+1]);
}
}
void
stackarg(val, flags, ptr1)
long val;
int flags;
ubyte *ptr1;
{
ubyte *str = NULL;
if (Xdebug)
printf("stackarg %ld (@%d)\n", val, Argi);
Lastwasop = 0;
if (flags & SYM_STRING) {
register ubyte *ptr = ptr1;
register ubyte *new;
register uword len;
val = len = 0;
while (*ptr && *ptr != '\"') {
val = (val << 8) | *ptr;
++ptr;
++len;
}
new = malloc(len + 1);
BMov(ptr1, new, len);
new[len] = 0;
flags &= ~SYM_STRING;
str = new;
}
Argstack[Argi] = val;
Argstring[Argi] = str;
Argflags[Argi] = flags;
if (++Argi == MAXARGS) {
puts("stackarg: maxargs stacked");
Argi = Argibase;
}
while (Opi != Opibase && Oppri[Opi-1] == 128)
evaltop();
}
void
doop(func, pri)
void (*func) ARGS((long, long, long, long));
int pri;
{
if (Xdebug)
puts("doop");
Lastwasop = 1;
if (Opi == Opibase || pri == 128) {
if (Xdebug)
printf("doop @ %d unary\n", Opi);
Opdis[Opi] = func;
Oppri[Opi] = pri;
++Opi;
return;
}
while (Opi != Opibase && Oppri[Opi-1] && pri <= Oppri[Opi-1])
evaltop();
if (Xdebug)
printf("doop @ %d\n", Opi);
Opdis[Opi] = func;
Oppri[Opi] = pri;
++Opi;
if (Opi == MAXOPS) {
puts("doop: too many operators");
Opi = Opibase;
}
return;
}
void
op_takelsb(v1, f1, x1, x2)
long v1;
long f1;
long x1, x2;
{
stackarg(v1 & 0xFFL, f1, NULL);
}
void
op_takemsb(v1, f1, x1, x2)
long v1;
long f1;
long x1, x2;
{
stackarg((v1 >> 8) & 0xFF, f1, NULL);
}
void
op_negate(v1, f1, x1, x2)
long v1;
long f1;
long x1, x2;
{
stackarg(-v1, f1, NULL);
}
void
op_invert(v1, f1, x1, x2)
long v1;
long f1;
long x1, x2;
{
stackarg(~v1, f1, NULL);
}
void
op_not(v1, f1, x1, x2)
long v1;
long f1;
long x1, x2;
{
stackarg((long)!v1, f1, NULL);
}
void
op_mult(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1 * v2, f1|f2, NULL);
}
void
op_div(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if (f1|f2) {
stackarg(0L, f1|f2, NULL);
return;
}
if (v2 == 0) {
puts("division by zero");
stackarg(0L, 0, NULL);
} else {
stackarg(v1 / v2, 0, NULL);
}
}
void
op_mod(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if (f1|f2) {
stackarg(0L, f1|f2, NULL);
return;
}
if (v2 == 0)
stackarg(v1, 0, NULL);
else
stackarg(v1 % v2, 0, NULL);
}
void
op_question(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if (f1)
stackarg(0L, f1, NULL);
else
stackarg((long)((v1) ? v2 : 0), ((v1) ? f2 : 0), NULL);
}
void
op_add(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1 + v2, f1|f2, NULL);
}
void
op_sub(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1 - v2, f1|f2, NULL);
}
void
op_shiftright(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if (f1|f2)
stackarg(0L, f1|f2, NULL);
else
stackarg((long)(v1 >> v2), 0, NULL);
}
void
op_shiftleft(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if (f1|f2)
stackarg(0L, f1|f2, NULL);
else
stackarg((long)(v1 << v2), 0, NULL);
}
void
op_greater(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 > v2), f1|f2, NULL);
}
void
op_greatereq(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 >= v2), f1|f2, NULL);
}
void
op_smaller(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 < v2), f1|f2, NULL);
}
void
op_smallereq(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 <= v2), f1|f2, NULL);
}
void
op_eqeq(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 == v2), f1|f2, NULL);
}
void
op_noteq(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg((long)(v1 != v2), f1|f2, NULL);
}
void
op_andand(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if ((!f1 && !v1) || (!f2 && !v2)) {
stackarg(0L, 0, NULL);
return;
}
stackarg(1L, f1|f2, NULL);
}
void
op_oror(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
if ((!f1 && v1) || (!f2 && v2)) {
stackarg(1L, 0, NULL);
return;
}
stackarg(0L, f1|f2, NULL);
}
void
op_xor(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1^v2, f1|f2, NULL);
}
void
op_and(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1&v2, f1|f2, NULL);
}
void
op_or(v1, v2, f1, f2)
long v1, v2;
long f1, f2;
{
stackarg(v1|v2, f1|f2, NULL);
}
ubyte *
pushchar(str)
ubyte *str;
{
if (*str) {
stackarg((long)*str, 0, NULL);
++str;
} else {
stackarg((long)' ', 0, NULL);
}
return((ubyte *)str);
}
ubyte *
pushhex(str)
ubyte *str;
{
register long val = 0;
for (;; ++str) {
if (*str >= '0' && *str <= '9') {
val = (val << 4) + (*str - '0');
continue;
}
if ((*str >= 'a' && *str <= 'f') || (*str >= 'A' && *str <= 'F')) {
val = (val << 4) + ((*str&0x1F) + 9);
continue;
}
break;
}
stackarg(val, 0, NULL);
return((ubyte *)str);
}
ubyte *
pushoct(str)
ubyte *str;
{
register long val = 0;
while (*str >= '0' && *str <= '7') {
val = (val << 3) + (*str - '0');
++str;
}
stackarg(val, 0, NULL);
return((ubyte *)str);
}
ubyte *
pushdec(str)
ubyte *str;
{
register long val = 0;
while (*str >= '0' && *str <= '9') {
val = (val * 10) + (*str - '0');
++str;
}
stackarg(val, 0, NULL);
return((ubyte *)str);
}
ubyte *
pushbin(str)
ubyte *str;
{
register long val = 0;
while (*str == '0' || *str == '1') {
val = (val << 1) | (*str - '0');
++str;
}
stackarg(val, 0, NULL);
return((ubyte *)str);
}
ubyte *
pushstr(str)
ubyte *str;
{
stackarg(0L, SYM_STRING, str);
while (*str && *str != '\"')
++str;
if (*str == '\"')
++str;
return((ubyte *)str);
}
ubyte *
pushsymbol(str)
ubyte *str;
{
register SYMBOL *sym;
register ubyte *ptr;
ubyte macro = 0;
for (ptr = str;
*ptr == '_' ||
*ptr == '.' ||
(*ptr >= 'a' && *ptr <= 'z') ||
(*ptr >= 'A' && *ptr <= 'Z') ||
(*ptr >= '0' && *ptr <= '9');
++ptr
);
if (ptr == str) {
asmerr(9,0);
printf("char = '%c' %d (-1: %d)\n", *str, *str, *(str-1));
if (F_listfile)
fprintf(FI_listfile, "char = '%c' code %d\n", *str, *str);
return((ubyte *)str+1);
}
if (sym = findsymbol(str, ptr - str)) {
if (sym->flags & SYM_UNKNOWN)
++Redo_eval;
if (sym->flags & SYM_MACRO) {
macro = 1;
sym = eval(sym->string);
}
if (sym->flags & SYM_STRING)
stackarg(0L, SYM_STRING, sym->string);
else
stackarg(sym->value, sym->flags & SYM_UNKNOWN, NULL);
sym->flags |= SYM_REF|SYM_MASREF;
if (macro)
freesymbollist(sym);
} else {
stackarg(0L, SYM_UNKNOWN, NULL);
sym = createsymbol(str, ptr - str);
sym->flags = SYM_REF|SYM_MASREF|SYM_UNKNOWN;
++Redo_eval;
}
return(ptr);
}