2011-12-16 22:04:51 +00:00
|
|
|
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 1989-1997 Andr<EFBFBD> Fachat (a.fachat@physik.tu-chemnitz.de)
|
|
|
|
|
*
|
|
|
|
|
* 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"
|
|
|
|
|
|
|
|
|
|
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,
|
2023-10-25 09:42:14 +00:00
|
|
|
|
P_LAND,P_LOR,P_EQU,P_START };
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
|
|
|
|
static int pp,pcc;
|
|
|
|
|
static int fundef;
|
|
|
|
|
|
|
|
|
|
static int ag_term(signed char*,int,int*,int*,int*);
|
|
|
|
|
static int get_op(signed char*,int*);
|
|
|
|
|
static int do_op(int*,int,int);
|
|
|
|
|
|
|
|
|
|
/* s = string, v = variable */
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
*pfl = 0;
|
|
|
|
|
fundef = f;
|
|
|
|
|
|
|
|
|
|
pp=0;
|
|
|
|
|
pcc=xpc;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2023-10-25 09:42:14 +00:00
|
|
|
|
else
|
|
|
|
|
if(s[pp]!=T_END) {
|
2011-12-16 22:04:51 +00:00
|
|
|
|
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);
|
2023-10-25 09:42:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
er = E_SYNTAX;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*l=pp;
|
2023-10-25 09:42:14 +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);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
return(er);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|
|
|
|
{
|
|
|
|
|
int er=E_OK,o,w,mf=1,afl;
|
|
|
|
|
|
|
|
|
|
afl = 0;
|
|
|
|
|
|
2023-10-25 09:42:14 +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]);
|
|
|
|
|
|
2011-12-16 22:04:51 +00:00
|
|
|
|
while(s[pp]=='-')
|
|
|
|
|
{
|
|
|
|
|
pp++;
|
|
|
|
|
mf=-mf;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 09:42:14 +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
|
2011-12-16 22:04:51 +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-10-25 09:42:14 +00:00
|
|
|
|
|
2020-05-15 17:20:17 +00:00
|
|
|
|
/*
|
|
|
|
|
printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
|
|
|
|
er, segment, afl, nolink, fundef);
|
|
|
|
|
*/
|
2011-12-16 22:04:51 +00:00
|
|
|
|
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
2023-10-25 09:42:14 +00:00
|
|
|
|
if( nolink || ((afl==SEG_UNDEF) || (afl==SEG_UNDEFZP))) {
|
2011-12-16 22:04:51 +00:00
|
|
|
|
er = E_OK;
|
|
|
|
|
*v = 0;
|
2023-10-25 09:42:14 +00:00
|
|
|
|
if(afl!=SEG_UNDEFZP) {
|
|
|
|
|
afl = SEG_UNDEF;
|
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
*label = cval(s+pp+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pp+=3;
|
|
|
|
|
}
|
|
|
|
|
else
|
2023-10-25 09:42:14 +00:00
|
|
|
|
if(s[pp]==T_VALUE || s[pp] == T_CAST)
|
2011-12-16 22:04:51 +00:00
|
|
|
|
{
|
2023-10-25 09:42:14 +00:00
|
|
|
|
while (s[pp] == T_CAST) {
|
|
|
|
|
pp+=2;
|
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
*v=lval(s+pp+1);
|
2023-10-25 09:42:14 +00:00
|
|
|
|
pp+=5;
|
2020-05-15 17:20:17 +00:00
|
|
|
|
/*
|
|
|
|
|
printf("value: v=%04x\n",*v);
|
|
|
|
|
*/
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(s[pp]==T_POINTER)
|
|
|
|
|
{
|
|
|
|
|
afl = s[pp+1];
|
|
|
|
|
*v=cval(s+pp+2);
|
2023-10-25 09:42:14 +00:00
|
|
|
|
pp+=6;
|
2020-05-15 17:20:17 +00:00
|
|
|
|
/*
|
|
|
|
|
printf("pointer: v=%04x, afl=%04x\n",*v,afl);
|
|
|
|
|
*/
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(s[pp]=='*')
|
|
|
|
|
{
|
|
|
|
|
*v=pcc;
|
|
|
|
|
pp++;
|
|
|
|
|
afl = segment;
|
2023-10-25 09:42:14 +00:00
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
else {
|
|
|
|
|
er=E_SYNTAX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*v *= mf;
|
|
|
|
|
|
2023-10-25 09:42:14 +00:00
|
|
|
|
while(!er && s[pp]!=')' && s[pp]!=']' && s[pp]!=',' && s[pp]!=T_END && s[pp]!=T_COMMENT)
|
2011-12-16 22:04:51 +00:00
|
|
|
|
{
|
2023-10-25 09:42:14 +00:00
|
|
|
|
//fprintf(stderr, "ag_term while: s[pp=%d]=%02x\n", pp, s[pp]);
|
2011-12-16 22:04:51 +00:00
|
|
|
|
er=get_op(s,&o);
|
|
|
|
|
|
|
|
|
|
if(!er && pr[o]>p)
|
|
|
|
|
{
|
|
|
|
|
pp+=1;
|
|
|
|
|
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
|
|
|
|
{
|
|
|
|
|
if(afl || *nafl) { /* check pointer arithmetic */
|
2023-10-25 09:42:14 +00:00
|
|
|
|
if((afl == *nafl) && (afl!=SEG_UNDEFZP) && (afl!=SEG_UNDEF) && o==2) {
|
2023-10-27 13:00:50 +00:00
|
|
|
|
afl = 0; /* subtract two pointers */
|
2011-12-16 22:04:51 +00:00
|
|
|
|
} else
|
|
|
|
|
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
|
|
|
|
afl=(afl | *nafl); /* add constant to pointer */
|
|
|
|
|
} else
|
|
|
|
|
if((afl && !*nafl) && o==2) {
|
2023-10-27 13:00:50 +00:00
|
|
|
|
afl=(afl | *nafl); /* subtract constant from pointer */
|
2011-12-16 22:04:51 +00:00
|
|
|
|
} else {
|
2023-10-27 13:00:50 +00:00
|
|
|
|
if((!afl && *nafl) && o==2) {
|
|
|
|
|
/* subtract pointer from constant */
|
|
|
|
|
errout(W_SUBTRACT);
|
|
|
|
|
}
|
|
|
|
|
/* allow math in the same segment */
|
2020-05-15 17:20:17 +00:00
|
|
|
|
if(segment!=SEG_ABS && segment != afl) {
|
2011-12-16 22:04:51 +00:00
|
|
|
|
if(!dsb_len) {
|
2023-10-25 09:42:14 +00:00
|
|
|
|
/*printf("ILLPOINTER=dsb_len=%d,segment=%d\n",dsb_len, segment);*/
|
|
|
|
|
/* e.g. adding two pointers, adding two undefined values */
|
2020-05-15 17:20:17 +00:00
|
|
|
|
er=E_ILLSEGMENT;
|
2011-12-16 22:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
afl=0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!er) er=do_op(v,w,o);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*nafl = afl;
|
|
|
|
|
return(er);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_op(signed char *s, int *o)
|
|
|
|
|
{
|
|
|
|
|
int er;
|
|
|
|
|
|
|
|
|
|
*o=s[pp];
|
|
|
|
|
|
2023-10-25 09:42:14 +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");
|
|
|
|
|
*/
|
2011-12-16 22:04:51 +00:00
|
|
|
|
er=E_SYNTAX;
|
2023-10-25 09:42:14 +00:00
|
|
|
|
} else {
|
2011-12-16 22:04:51 +00:00
|
|
|
|
er=E_OK;
|
2023-10-25 09:42:14 +00:00
|
|
|
|
}
|
2011-12-16 22:04:51 +00:00
|
|
|
|
|
|
|
|
|
return(er);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:
|
2020-05-15 17:20:17 +00:00
|
|
|
|
if (w2!=0)
|
2011-12-16 22:04:51 +00:00
|
|
|
|
*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);
|
|
|
|
|
}
|
|
|
|
|
|