318 lines
7.2 KiB
C
318 lines
7.2 KiB
C
/*
|
|
* Z80 - Assembler
|
|
* Copyright (C) 1987-1992 by Udo Munk
|
|
*
|
|
* History:
|
|
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
|
* 28-JUN-1988 Switched to Unix System V.3
|
|
*/
|
|
|
|
/*
|
|
* Dieses Modul enthaelt die numerischen
|
|
* Rechen- und Umwandlungsfunktionen.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include "z80a.h"
|
|
#include "z80aglb.h"
|
|
|
|
#ifndef isxdigit
|
|
#define isxdigit(c) (isdigit(c) || (c>='a' && c<='f') || (c>='A' && c<='F'))
|
|
#endif
|
|
|
|
/*
|
|
* Definition Operatoren-Symbole fuer den Expression-Parser
|
|
*/
|
|
#define OPEDEC 1 /* Dezimalzahl */
|
|
#define OPEHEX 2 /* Hexzahl */
|
|
#define OPEOCT 3 /* Octalzahl */
|
|
#define OPEBIN 4 /* Binaerzahl */
|
|
#define OPESUB 5 /* arithmetisches - */
|
|
#define OPEADD 6 /* arithmetisches + */
|
|
#define OPEMUL 7 /* arithmetisches * */
|
|
#define OPEDIV 8 /* arithmetisches / */
|
|
#define OPEMOD 9 /* arithmetisches Modulo */
|
|
#define OPESHL 10 /* logisches shift left */
|
|
#define OPESHR 11 /* logisches shift right */
|
|
#define OPELOR 12 /* logisches OR */
|
|
#define OPELAN 13 /* logisches AND */
|
|
#define OPEXOR 14 /* logisches XOR */
|
|
#define OPECOM 15 /* logisches Komplement */
|
|
#define OPESYM 99 /* Symbol */
|
|
|
|
/*
|
|
* Rekursiver Expression-Parser
|
|
*
|
|
* Input: Pointer auf den restlichen Argument-String
|
|
*
|
|
* Output: berechneter Wert
|
|
*/
|
|
eval(s)
|
|
register char *s;
|
|
{
|
|
register char *p;
|
|
register int val;
|
|
char word[MAXLINE];
|
|
struct sym *sp, *get_sym();
|
|
|
|
val = 0;
|
|
while (*s) {
|
|
p = word;
|
|
if (*s == '(') {
|
|
s++;
|
|
while (*s != ')') {
|
|
if (*s == '\0') {
|
|
asmerr(E_MISPAR);
|
|
goto eval_break;
|
|
}
|
|
*p++ = *s++;
|
|
}
|
|
*p = '\0';
|
|
s++;
|
|
val = eval(word);
|
|
continue;
|
|
}
|
|
if (*s == STRSEP) {
|
|
s++;
|
|
while (*s != STRSEP) {
|
|
if (*s == '\n' || *s == '\0') {
|
|
asmerr(E_MISHYP);
|
|
goto hyp_error;
|
|
}
|
|
*p++ = *s++;
|
|
}
|
|
s++;
|
|
hyp_error:
|
|
*p = '\0';
|
|
val = strval(word);
|
|
continue;
|
|
}
|
|
if (isari(*s))
|
|
*p++ = *s++;
|
|
else
|
|
while (!isspace(*s) && !isari(*s) && (*s != '\0'))
|
|
*p++ = *s++;
|
|
*p = '\0';
|
|
switch (get_type(word)) {
|
|
case OPESYM: /* Symbol */
|
|
if (strcmp(word, "$") == 0) {
|
|
val = pc;
|
|
break;
|
|
}
|
|
if (strlen(word) > SYMSIZE)
|
|
word[SYMSIZE] = '\0';
|
|
if ((sp = get_sym(word)) != NULL)
|
|
val = sp->sym_wert;
|
|
else
|
|
asmerr(E_UNDSYM);
|
|
break;
|
|
case OPEDEC: /* Dezimalzahl */
|
|
val = atoi(word);
|
|
break;
|
|
case OPEHEX: /* Hexzahl */
|
|
val = axtoi(word);
|
|
break;
|
|
case OPEBIN: /* Binaerzahl */
|
|
val = abtoi(word);
|
|
break;
|
|
case OPEOCT: /* Oktalzahl */
|
|
val = aotoi(word);
|
|
break;
|
|
case OPESUB: /* arithmetisches - */
|
|
val -= eval(s);
|
|
goto eval_break;
|
|
case OPEADD: /* arithmetisches + */
|
|
val += eval(s);
|
|
goto eval_break;
|
|
case OPEMUL: /* arithmetisches * */
|
|
val *= eval(s);
|
|
goto eval_break;
|
|
case OPEDIV: /* arithmetisches / */
|
|
val /= eval(s);
|
|
goto eval_break;
|
|
case OPEMOD: /* arithmetisches Modulo */
|
|
val %= eval(s);
|
|
goto eval_break;
|
|
case OPESHL: /* logisches shift left */
|
|
val <<= eval(s);
|
|
goto eval_break;
|
|
case OPESHR: /* logisches shift right */
|
|
val >>= eval(s);
|
|
goto eval_break;
|
|
case OPELOR: /* logisches OR */
|
|
val |= eval(s);
|
|
goto eval_break;
|
|
case OPELAN: /* logisches AND */
|
|
val &= eval(s);
|
|
goto eval_break;
|
|
case OPEXOR: /* logisches XOR */
|
|
val ^= eval(s);
|
|
goto eval_break;
|
|
case OPECOM: /* logisches Komplement */
|
|
val = ~(eval(s));
|
|
goto eval_break;
|
|
}
|
|
}
|
|
eval_break:
|
|
return(val);
|
|
}
|
|
|
|
/*
|
|
* Operanden Typ-Bestimmung
|
|
*
|
|
* Input: Pointer auf zu bestimmenden String
|
|
*
|
|
* Output: Operanden Typ
|
|
*/
|
|
get_type(s)
|
|
char *s;
|
|
{
|
|
if (isdigit(*s)) { /* numerischer Operand */
|
|
if (isdigit(*(s + strlen(s) - 1))) /* Dezimalzahl */
|
|
return(OPEDEC);
|
|
else if (*(s + strlen(s) - 1) == 'H') /* Hexzahl */
|
|
return(OPEHEX);
|
|
else if (*(s + strlen(s) - 1) == 'B') /* Binaerzahl */
|
|
return(OPEBIN);
|
|
else if (*(s + strlen(s) - 1) == 'O') /* Oktalzahl */
|
|
return(OPEOCT);
|
|
} else if (*s == '-') /* arithmetischer Operand - */
|
|
return(OPESUB);
|
|
else if (*s == '+') /* arithmetischer Operand + */
|
|
return(OPEADD);
|
|
else if (*s == '*') /* arithmetischer Operand * */
|
|
return(OPEMUL);
|
|
else if (*s == '/') /* arithmetischer Operand / */
|
|
return(OPEDIV);
|
|
else if (*s == '%') /* arithmetisches Modulo */
|
|
return(OPEMOD);
|
|
else if (*s == '<') /* logisches shift left */
|
|
return(OPESHL);
|
|
else if (*s == '>') /* logisches shift rigth */
|
|
return(OPESHR);
|
|
else if (*s == '|') /* logisches OR */
|
|
return(OPELOR);
|
|
else if (*s == '&') /* logisches AND */
|
|
return(OPELAN);
|
|
else if (*s == '^') /* logisches XOR */
|
|
return(OPEXOR);
|
|
else if (*s == '~') /* logisches Komplement */
|
|
return(OPECOM);
|
|
return(OPESYM); /* Operand ist ein Symbol */
|
|
}
|
|
|
|
/*
|
|
* Die Funktion prueft einen Character auf die arithmetischen
|
|
* Operatoren +, -, *, /, %, <, >, |, &, ~ und ^.
|
|
*/
|
|
isari(c)
|
|
register int c;
|
|
{
|
|
return((c) == '+' || (c) == '-' || (c) == '*' ||
|
|
(c) == '/' || (c) == '%' || (c) == '<' ||
|
|
(c) == '>' || (c) == '|' || (c) == '&' ||
|
|
(c) == '~' || (c) == '^');
|
|
}
|
|
|
|
/*
|
|
* Umwandlung eines ASCII-Strings mit einer Hexzahl in
|
|
* einen Integer.
|
|
* Format: nnnnH oder 0nnnnH wenn 1.Ziffer > 9
|
|
*/
|
|
axtoi(str)
|
|
register char *str;
|
|
{
|
|
register int num;
|
|
|
|
num = 0;
|
|
while (isxdigit(*str)) {
|
|
num *= 16;
|
|
num += *str - ((*str <= '9') ? '0' : '7');
|
|
str++;
|
|
}
|
|
return(num);
|
|
}
|
|
|
|
/*
|
|
* Umwandlung eines ASCII-Strings mit einer Oktalzahl in
|
|
* einen Integer.
|
|
* Format: nnnnO
|
|
*/
|
|
aotoi(str)
|
|
register char *str;
|
|
{
|
|
register int num;
|
|
|
|
num = 0;
|
|
while ('0' <= *str && *str <= '7') {
|
|
num *= 8;
|
|
num += (*str++) - '0';
|
|
}
|
|
return(num);
|
|
}
|
|
|
|
/*
|
|
* Umwandlung eines ASCII-Strings mit einer Binaerzahl in
|
|
* einen Integer.
|
|
* Format: nnnnnnnnnnnnnnnnB
|
|
*/
|
|
abtoi(str)
|
|
register char *str;
|
|
{
|
|
register int num;
|
|
|
|
num = 0;
|
|
while ('0' <= *str && *str <= '1') {
|
|
num *= 2;
|
|
num += (*str++) - '0';
|
|
}
|
|
return(num);
|
|
}
|
|
|
|
/*
|
|
* Umwandlung eines ASCII-Strings in einen Integer.
|
|
*/
|
|
strval(str)
|
|
register char *str;
|
|
{
|
|
register int num;
|
|
|
|
num = 0;
|
|
while (*str) {
|
|
num <<= 8;
|
|
num += (int) *str++;
|
|
}
|
|
return(num);
|
|
}
|
|
|
|
/*
|
|
* Die Funktion prueft einen Wert auf -256 < Wert < 256
|
|
* Output: Wert wenn im Bereich, sonst 0 und Fehlermeldung
|
|
*/
|
|
chk_v1(i)
|
|
register int i;
|
|
{
|
|
if (i >= -255 && i <= 255)
|
|
return(i);
|
|
else {
|
|
asmerr(E_VALOUT);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Die Funktion prueft einen Wert auf -128 < Wert < 128
|
|
* Output: Wert wenn im Bereich, sonst 0 und Fehlermeldung
|
|
*/
|
|
chk_v2(i)
|
|
register int i;
|
|
{
|
|
if (i >= -127 && i <= 127)
|
|
return(i);
|
|
else {
|
|
asmerr(E_VALOUT);
|
|
return(0);
|
|
}
|
|
}
|