2011-12-16 22:04:51 +00:00
|
|
|
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
|
|
|
|
*
|
2024-03-19 08:32:45 +00:00
|
|
|
|
* Copyright (C) 1989-1997 Andr<EFBFBD> Fachat (a.fachat@physik.tu-chemnitz.de)
|
2011-12-16 22:04:51 +00:00
|
|
|
|
*
|
|
|
|
|
* Preprocessing arithmetic module
|
|
|
|
|
*
|
|
|
|
|
* This program 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 2 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, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
#include "xah.h"
|
|
|
|
|
|
|
|
|
|
#include "xad.h"
|
|
|
|
|
#include "xar.h"
|
|
|
|
|
#include "xa.h"
|
|
|
|
|
#include "xal.h"
|
|
|
|
|
#include "xaa.h"
|
|
|
|
|
#include "xat.h"
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
static int pr[] = { P_START, P_ADD, P_ADD, P_MULT, P_MULT, P_SHIFT, P_SHIFT,
|
|
|
|
|
P_CMP,
|
|
|
|
|
P_CMP, P_EQU, P_CMP, P_CMP, P_EQU, P_AND, P_XOR, P_OR,
|
|
|
|
|
P_LAND, P_LOR, P_EQU, P_START };
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
static int pp, pcc;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
static int fundef;
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
static int ag_term(signed char*, int, int*, int*, int*);
|
|
|
|
|
static int get_op(signed char*, int*);
|
|
|
|
|
static int do_op(int*, int, int);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
|
|
|
|
/* s = string, v = variable */
|
2024-03-19 08:32:45 +00:00
|
|
|
|
int a_term(signed char *s, int *v, int *l, int xpc, int *pfl, int *label, int f) {
|
|
|
|
|
int er = E_OK;
|
|
|
|
|
int afl = 0, bfl;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
*pfl = 0;
|
|
|
|
|
fundef = f;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
pp = 0;
|
|
|
|
|
pcc = xpc;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
if (s[0] == '<') {
|
|
|
|
|
pp++;
|
|
|
|
|
er = ag_term(s, P_START, v, &afl, label);
|
|
|
|
|
bfl = afl & (A_MASK >> 8);
|
|
|
|
|
if (bfl && (bfl != (A_ADR >> 8)) && (bfl != (A_LOW >> 8))) {
|
|
|
|
|
/*fprintf(stderr,"low byte relocation for a high byte - won't work!\n");*/
|
|
|
|
|
errout(W_LOWACC);
|
|
|
|
|
}
|
|
|
|
|
if (afl)
|
|
|
|
|
*pfl = A_LOW | ((afl << 8) & A_FMASK);
|
|
|
|
|
*v = *v & 255;
|
|
|
|
|
} else if (s[pp] == '>') {
|
|
|
|
|
pp++;
|
|
|
|
|
er = ag_term(s, P_START, v, &afl, label);
|
|
|
|
|
bfl = afl & (A_MASK >> 8);
|
|
|
|
|
if (bfl && (bfl != (A_ADR >> 8)) && (bfl != (A_HIGH >> 8))) {
|
|
|
|
|
/*fprintf(stderr,"high byte relocation for a low byte - won't work!\n");*/
|
|
|
|
|
errout(W_HIGHACC);
|
|
|
|
|
}
|
|
|
|
|
if (afl)
|
|
|
|
|
*pfl = A_HIGH | ((afl << 8) & A_FMASK) | (*v & 255);
|
|
|
|
|
*v = (*v >> 8) & 255;
|
|
|
|
|
} else if (s[pp] != T_END) {
|
|
|
|
|
er = ag_term(s, P_START, v, &afl, label);
|
|
|
|
|
bfl = afl & (A_MASK >> 8);
|
|
|
|
|
if (bfl && (bfl != (A_ADR >> 8))) {
|
|
|
|
|
/*fprintf(stderr,"address relocation for a low or high byte - won't work!\n");*/
|
|
|
|
|
errout(W_ADDRACC);
|
|
|
|
|
}
|
|
|
|
|
if (afl)
|
|
|
|
|
*pfl = A_ADR | ((afl << 8) & A_FMASK);
|
|
|
|
|
} else {
|
|
|
|
|
er = E_SYNTAX;
|
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
*l = pp;
|
2023-11-19 20:24:38 +00:00
|
|
|
|
//fprintf(stderr, "a_term: nolink=%d, noundef=%d ->er=%d; l=%d, pp=%d, afl->%04x *pfl=%04x, (pc=%04x)\n",nolink, noundef ,er, *l, pp, afl,*pfl, xpc);
|
2024-03-19 08:32:45 +00:00
|
|
|
|
return (er);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
static int ag_term(signed char *s, int p, int *v, int *nafl, int *label) {
|
|
|
|
|
int er = E_OK, o, w, mf = 1, afl;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
afl = 0;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2023-11-19 20:24:38 +00:00
|
|
|
|
//fprintf(stderr, "ag_term(%02x %02x %02x %02x %02x %02x\n",s[0],s[1],s[2],s[3],s[4],s[5]);
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
while (s[pp] == '-') {
|
|
|
|
|
pp++;
|
|
|
|
|
mf = -mf;
|
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2023-11-19 20:24:38 +00:00
|
|
|
|
#if(0) /* NYI: this is hacked into .assert for now */
|
|
|
|
|
if(s[pp]==18) /* logical not */
|
|
|
|
|
{
|
|
|
|
|
pp++;
|
|
|
|
|
if(!(er=ag_term(s,P_START,v,&afl,label)))
|
|
|
|
|
{
|
|
|
|
|
if(s[pp]!=')')
|
|
|
|
|
er=E_SYNTAX;
|
|
|
|
|
else
|
|
|
|
|
pp++;
|
|
|
|
|
}
|
|
|
|
|
*v = !(*v);
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
2024-03-19 08:32:45 +00:00
|
|
|
|
if (s[pp] == '(') {
|
|
|
|
|
pp++;
|
|
|
|
|
if (!(er = ag_term(s, P_START, v, &afl, label))) {
|
|
|
|
|
if (s[pp] != ')')
|
|
|
|
|
er = E_SYNTAX;
|
|
|
|
|
else
|
|
|
|
|
pp++;
|
|
|
|
|
}
|
|
|
|
|
} else if (s[pp] == T_LABEL) {
|
|
|
|
|
er = l_get(cval(s + pp + 1), v, &afl);
|
2023-11-19 20:24:38 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
/*
|
|
|
|
|
printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
|
|
|
|
er, segment, afl, nolink, fundef);
|
|
|
|
|
*/
|
|
|
|
|
if (er == E_NODEF && segment != SEG_ABS && fundef) {
|
|
|
|
|
if (nolink || ((afl == SEG_UNDEF) || (afl == SEG_UNDEFZP))) {
|
|
|
|
|
er = E_OK;
|
|
|
|
|
*v = 0;
|
|
|
|
|
if (afl != SEG_UNDEFZP) {
|
|
|
|
|
afl = SEG_UNDEF;
|
|
|
|
|
}
|
|
|
|
|
*label = cval(s + pp + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pp += 3;
|
|
|
|
|
} else if (s[pp] == T_VALUE || s[pp] == T_CAST) {
|
|
|
|
|
while (s[pp] == T_CAST) {
|
|
|
|
|
pp += 2;
|
|
|
|
|
}
|
|
|
|
|
*v = lval(s + pp + 1);
|
|
|
|
|
pp += 5;
|
|
|
|
|
/*
|
|
|
|
|
printf("value: v=%04x\n",*v);
|
|
|
|
|
*/
|
|
|
|
|
} else if (s[pp] == T_POINTER) {
|
|
|
|
|
afl = s[pp + 1];
|
|
|
|
|
*v = cval(s + pp + 2);
|
|
|
|
|
pp += 6;
|
|
|
|
|
/*
|
|
|
|
|
printf("pointer: v=%04x, afl=%04x\n",*v,afl);
|
|
|
|
|
*/
|
|
|
|
|
} else if (s[pp] == '*') {
|
|
|
|
|
*v = pcc;
|
|
|
|
|
pp++;
|
|
|
|
|
afl = segment;
|
|
|
|
|
} else {
|
|
|
|
|
er = E_SYNTAX;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
*v *= mf;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
while (!er && s[pp] != ')' && s[pp] != ']' && s[pp] != ',' && s[pp] != T_END
|
|
|
|
|
&& s[pp] != T_COMMENT) {
|
2023-11-19 20:24:38 +00:00
|
|
|
|
//fprintf(stderr, "ag_term while: s[pp=%d]=%02x\n", pp, s[pp]);
|
2024-03-19 08:32:45 +00:00
|
|
|
|
er = get_op(s, &o);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
if (!er && pr[o] > p) {
|
|
|
|
|
pp += 1;
|
|
|
|
|
if (!(er = ag_term(s, pr[o], &w, nafl, label))) {
|
|
|
|
|
if (afl || *nafl) { /* check pointer arithmetic */
|
|
|
|
|
if ((afl == *nafl) && (afl != SEG_UNDEFZP)
|
|
|
|
|
&& (afl != SEG_UNDEF) && o == 2) {
|
|
|
|
|
afl = 0; /* subtract two pointers */
|
|
|
|
|
} else if (((afl && !*nafl) || (*nafl && !afl)) && o == 1) {
|
|
|
|
|
afl = (afl | *nafl); /* add constant to pointer */
|
|
|
|
|
} else if ((afl && !*nafl) && o == 2) {
|
|
|
|
|
afl = (afl | *nafl); /* subtract constant from pointer */
|
|
|
|
|
} else {
|
|
|
|
|
if ((!afl && *nafl) && o == 2) {
|
|
|
|
|
/* subtract pointer from constant */
|
|
|
|
|
errout(W_SUBTRACT);
|
|
|
|
|
}
|
|
|
|
|
/* allow math in the same segment */
|
|
|
|
|
if (segment != SEG_ABS && segment != afl) {
|
|
|
|
|
if (!dsb_len) {
|
|
|
|
|
/*printf("ILLPOINTER=dsb_len=%d,segment=%d\n",dsb_len, segment);*/
|
|
|
|
|
/* e.g. adding two pointers, adding two undefined values */
|
|
|
|
|
er = E_ILLSEGMENT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
afl = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!er)
|
|
|
|
|
er = do_op(v, w, o);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
2024-03-19 08:32:45 +00:00
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*nafl = afl;
|
|
|
|
|
return (er);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
static int get_op(signed char *s, int *o) {
|
|
|
|
|
int er;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
*o = s[pp];
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
if (*o < 1 || *o > 17) {
|
|
|
|
|
/*
|
|
|
|
|
printf("*o=%d, pp=%d, s=%s\n", *o, pp, s);
|
|
|
|
|
for (int i=0; i< 10; i++) {
|
|
|
|
|
printf(" %02x", s[i]);
|
|
|
|
|
}
|
|
|
|
|
printf("\n");
|
|
|
|
|
*/
|
|
|
|
|
er = E_SYNTAX;
|
|
|
|
|
} else {
|
|
|
|
|
er = E_OK;
|
2023-11-19 20:24:38 +00:00
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
2024-03-19 08:32:45 +00:00
|
|
|
|
return (er);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
2024-03-19 08:32:45 +00:00
|
|
|
|
|
|
|
|
|
static int do_op(int *w, int w2, int o) {
|
|
|
|
|
int er = E_OK;
|
|
|
|
|
switch (o) {
|
|
|
|
|
case 1:
|
|
|
|
|
*w += w2;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
*w -= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
*w *= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if (w2 != 0)
|
|
|
|
|
*w /= w2;
|
|
|
|
|
else
|
|
|
|
|
er = E_DIV;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
*w >>= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
*w <<= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
*w = *w < w2;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
*w = *w > w2;
|
|
|
|
|
break;
|
|
|
|
|
case 9:
|
|
|
|
|
*w = *w == w2;
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
*w = *w <= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
*w = *w >= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 12:
|
|
|
|
|
*w = *w != w2;
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
*w &= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 14:
|
|
|
|
|
*w ^= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 15:
|
|
|
|
|
*w |= w2;
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
*w = *w && w2;
|
|
|
|
|
break;
|
|
|
|
|
case 17:
|
|
|
|
|
*w = *w || w2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return (er);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|