1
0
mirror of https://github.com/fachat/xa65.git synced 2025-01-01 10:29:19 +00:00

added ca65 compatibiltiy patch

This commit is contained in:
Andre Fachat 2011-12-16 23:22:32 +01:00
parent ac0f09ba77
commit f28af4a917
10 changed files with 303 additions and 59 deletions

View File

@ -19,6 +19,9 @@ further in this manual page.
.SH OPTIONS
.TP
.B \-E
Do not stop after 20 errors, but show all errors.
.TP
.B \-v
Verbose output.
.TP
@ -67,9 +70,18 @@ to reconstruct source.
Add cross-reference list to labellist (requires
.BR \-l ).
.TP
.B \-Xcompatset
Enables compatibility settings to become more (not fully!) compatible with other 6502 assemblers.
Currently supported are compatibility set "MASM" and "CA65".
"MASM" allows colons to appear in comments. This does not affect colon interpretation elsewhere.
"CA65" allows the ":=" label definition (instead of "="), and also the "cheap local labels" using
the "@" character. This, however, disables the "@" 24-bit enforcement.
.TP
.B \-M
Allow colons to appear in comments; for MASM compatibility. This does
not affect colon interpretation elsewhere.
not affect colon interpretation elsewhere. This option is deprecated. Use
.BR -X
instead.
.TP
.B \-R
Start assembler in relocating mode.
@ -339,7 +351,7 @@ for those opcodes that support it (i.e., keep as 16 bit word)
.B @
render as 24-bit quantity for 65816 (must specify
.B \-w
command-line option).
command-line option, must not specify the CA65 compatibility).
.B This is required to specify any
.B 24-bit quantity!
.TP
@ -538,6 +550,9 @@ space for allocation and .zero being uninitialized zero page space for
allocation. In .bss and .zero, only labels are evaluated. These pseudo-ops
are valid in relative and absolute modes.
.TP
.B .code
For CA65 compatibility this is currently mapped to ".text".
.TP
.B .align value
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
.B

View File

@ -1,4 +1,4 @@
OBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o
OBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o
#CFLAGS=-W -Wall -pedantic -ansi #-g
#CFLAGS=-W -Wall -ansi -O2

View File

@ -61,7 +61,10 @@
/* exported globals */
int ncmos, cmosfl, w65816, n65816;
int masm = 0;
/* compatibility flags */
int masm = 0; /* MASM */
int ca65 = 0; /* CA65 */
int nolink = 0;
int romable = 0;
int romaddr = 0;
@ -71,10 +74,12 @@ int crossref = 0;
char altppchar;
/* local variables */
static char out[MAXLINE];
static time_t tim1, tim2;
static FILE *fpout, *fperr, *fplab;
static int ner = 0;
static int ner_max = 20;
static int align = 1;
@ -91,6 +96,7 @@ static int getline(char *);
static void lineout(void);
static long ga_p1(void);
static long gm_p1(void);
static int set_compat(char *compat_name);
/* text */
int memode,xmode;
@ -191,6 +197,9 @@ int main(int argc,char *argv[])
while(i<argc) {
if(argv[i][0]=='-') {
switch(argv[i][1]) {
case 'E':
ner_max = 0;
break;
case 'p':
/* intentionally not allowing an argument to follow with a
space to avoid - being seen as the alternate
@ -210,6 +219,19 @@ int main(int argc,char *argv[])
case 'M':
masm = 1; /* MASM compatibility mode */
break;
case 'X': /* compatibility across assemblers... */
{
char *name = NULL;
if (argv[i][2] == 0) {
name = argv[++i];
} else {
name = argv[i]+2;
}
if (set_compat(name) < 0) {
fprintf(stderr, "Compatibility set '%s' unknown - ignoring! (check case?)\n", name);
}
}
break;
case 'O': /* output charset */
{
char *name = NULL;
@ -500,7 +522,12 @@ int main(int argc,char *argv[])
if(ner || er)
{
if (ner_max > 0) {
fprintf(stderr, "Break after %d error%c\n",ner,ner?'s':0);
} else {
/* ner_max==0, i.e. show all errors */
fprintf(stderr, "End after %d error%c\n",ner,ner?'s':0);
}
/*unlink();*/
if(ofile) {
unlink(ofile);
@ -615,7 +642,7 @@ static int pass2(void)
filep=&datei;
afile->mn.tmpe=0L;
while(ner<20 && afile->mn.tmpe<afile->mn.tmpz)
while((ner_max==0 || ner<ner_max) && afile->mn.tmpe<afile->mn.tmpz)
{
l=afile->mn.tmp[afile->mn.tmpe++];
ll=l;
@ -827,6 +854,7 @@ static void usage(int default816, FILE *fp)
programname);
fprintf(fp,
" -v verbose output\n"
" -E do not break after 20 errors, but show all\n"
" -x old filename behaviour (overrides `-o', `-e', `-l')\n"
" This is deprecated and may disappear in future versions!\n"
" -C no CMOS-opcodes\n"
@ -844,6 +872,8 @@ static void usage(int default816, FILE *fp)
" -l filename sets labellist filename, default is none\n"
" -r adds crossreference list to labellist (if `-l' given)\n"
" -M allow ``:'' to appear in comments for MASM compatibility\n"
" -Xcompatset set compatibility flags for other assemblers, known values are:\n"
" MASM, CA65\n"
" -R start assembler in relocating mode\n");
fprintf(fp,
" -Llabel defines `label' as absolute, undefined label even when linking\n"
@ -900,7 +930,7 @@ static char *ertxt[] = {
"NewFile",
"CMOS-Befehl",
"pp:Wrong parameter count",
"Illegal pointer arithmetic",
"Illegal pointer arithmetic (-26)",
"Illegal segment",
"File header option too long",
"File option not at file start (when ROM-able)",
@ -939,11 +969,10 @@ static char *ertxt[] = {
"",
"",
"",
"",
/* warnings */
"Cutting word relocation in byte value",
"Byte relocation in word value",
"Illegal pointer arithmetic",
"Illegal pointer arithmetic (-66)",
"Address access to low or high byte pointer",
"High byte access to low byte pointer",
"Low byte access to high byte pointer",
@ -1062,9 +1091,20 @@ static int getline(char *s)
comcom = 1;
if (c=='\0')
break; /* hkfl = comcom = 0 */
if (c==':' && !hkfl && (!comcom || !masm)) {
gl=1;
break;
if (c==':' && !hkfl) {
/* if the next char is a "=" - so that we have a ":=" - and we
we have ca65 compatibility, we ignore the colon */
if (l[i]!='=' || !ca65 || comcom) {
/* but otherwise we check if it is in a comment and we have
MASM or CA65 compatibility, then we ignore the colon as well */
if(!comcom || !(masm || ca65)) {
/* we found a colon, so we keep the current line in memory
but return the part before the colon, and next time the part
after the colon, so we can parse C64 BASIC text assembler... */
gl=1;
break;
}
}
}
j++;
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
@ -1072,7 +1112,9 @@ static int getline(char *s)
s[j]='\0';
} else
s[0]='\0';
#if 0
printf("got line: %s\n", s);
#endif
return(ec);
}
@ -1092,8 +1134,8 @@ static void lineout(void)
void errout(int er)
{
if (er<-ANZERR || er>-1) {
if(er>=-(ANZERR+ANZWARN) && er < -ANZERR) {
if (er<=-ANZERR || er>-1) {
if(er>=-(ANZERR+ANZWARN) && er <= -ANZERR) {
sprintf(out,"%s:line %d: %04x: Warning - %s\n",
filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]);
} else {
@ -1129,3 +1171,30 @@ void logout(char *s)
fprintf(fperr,"%s",s);
}
/*****************************************************************/
typedef struct {
char *name;
int *flag;
} compat_set;
static compat_set compat_sets[] = {
{ "MASM", &masm },
{ "CA65", &ca65 },
{ NULL, NULL }
};
int set_compat(char *compat_name) {
int i = 0;
while (compat_sets[i].name != NULL) {
if (strcmp(compat_sets[i].name, compat_name) == 0) {
/* set appropriate compatibility flag */
(*compat_sets[i].flag) = 1;
return 0;
}
i++;
}
return -1;
}

View File

@ -22,7 +22,7 @@
#include "xah.h" /* For SEG_MAX */
extern int ncmos, cmosfl, w65816, n65816;
extern int masm, nolink;
extern int masm, ca65, nolink;
extern int noglob;
extern int showblk;
extern int relmode;

View File

@ -180,6 +180,8 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
} else {
if(segment!=SEG_ABS) {
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_ILLPOINTER;
}
}

View File

@ -20,15 +20,22 @@
#ifndef __XA65_XAH_H__
#define __XA65_XAH_H__
#define ANZLAB 5000 /* mal 14 -> Byte */
/*
* Note: the computations to get the number of bytes necessary to allocate are
* a historic remnant of the Atari ST (the original platform) not being able to efficiently allocate small chunks
* of memory so I had to allocate a large chunk myself and manage the tables myself.
* This has changed and some parts of xa65 are modified to just do a malloc() now.
* These fixed numbers should actually go away. AF 20110623
*/
#define ANZLAB 5000 /* multiplied by sizeof(Labtab) -> Byte */
#define LABMEM 40000L
#define MAXLAB 32
#define MAXBLK 16
#define MAXFILE 7
#define MAXLINE 2048
#define MAXPP 40000L
#define ANZDEF 2340 /* mal 14 -> Byte, ANZDEF * 14 < 32768 */
#define TMPMEM 200000L /* Zwischenspeicher von Pass1 nach Pass 2 */
#define ANZDEF 2340 /* multiplied by sizeof(List) -> Byte, ANZDEF * 20 < 32768 */
#define TMPMEM 200000L /* temporary memory buffer from Pass1 to Pass 2 */
typedef struct LabOcc {
struct LabOcc *next;

View File

@ -50,6 +50,12 @@ static int b_get(int*);
static int b_test(int);
static int ll_def(char *s, int *n, int b);
static int b_new(void);
static void cll_init();
static int cll_get();
static void cll_clear();
static int cll_getcur();
/* local variables */
/*
@ -69,6 +75,7 @@ static Labtab *ltp;
int l_init(void)
{
cll_init();
return 0;
#if 0
int er;
@ -139,10 +146,49 @@ FILE *fp;
}
}
/**********************************************************************************
* cheap local labels
*/
static int cll_current = 0; /* the current cheap local labels block */
/**
* init the cheap local labels
*/
void cll_init() {
cll_current = 0;
}
/**
* get the block number for a new cheap local label block
*/
int cll_get() {
if (cll_current == 0) {
cll_current = b_new();
}
return cll_current;
}
/**
* clear the local labels
*/
void cll_clear() {
cll_current = 0;
}
int cll_getcur() {
return cll_current;
}
/**********************************************************************************/
/**
* define a global label
*/
int lg_set(char *s ) {
int n, er;
er = ll_search(s,&n);
er = ll_search(s,&n, 0);
if(er==E_OK) {
fprintf(stderr,"Warning: global label doubly defined!\n");
@ -156,52 +202,73 @@ int lg_set(char *s ) {
return er;
}
/**********************************************************************************/
int l_def(char *s, int *l, int *x, int *f)
{
int n,er,b,i=0;
int cll_fl;
*f=0;
b=0;
n=0;
*f=0; /* flag (given as param) that the label is to be re-defined and the
"label defined error" is to be skipped */
b=0; /* block level on block stack, resp. block number */
n=0; /* flag, when set, b is absolute block number and not being translated */
cll_fl=0; /* when set, clear the cheap local label block */
if(s[0]=='-')
{
*f+=1;
*f+=1; /* label is being redefined */
i++;
} else
if(s[0]=='@')
{
i++;
n++; /* block number b is absolute */
b=cll_get(); /* current (possibly newly allocated) cheap label block */
cll_fl=1; /* do not clear the cll block again... */
} else
if(s[0]=='+')
{
i++;
n++;
b=0;
n++; /* block number b is absolute */
b=0; /* global block number */
}
while(s[i]=='&')
{
n=0;
if (n) b=0; /* reset block number */
n=0; /* block number is relative */
i++;
b++;
b++; /* one (more) level up the block stack */
}
if(!n)
if(!n) {
/* translate from block stack level to absolute block number */
b_fget(&b,b);
}
if(!cll_fl) {
/* clear cheap local labels */
cll_clear();
}
if(!isalpha(s[i]) && s[i]!='_')
if(!isalpha(s[i]) && s[i]!='_' && !(ca65 && isdigit(s[i]) ) )
er=E_SYNTAX;
else
{
er=ll_search(s+i,&n);
er=ll_search(s+i,&n, cll_fl);
if(er==E_OK)
{
/* we actually found an existing label in the same scope */
ltp=afile->la.lt+n;
if(*f)
{
/* redefinition of label */
*l=ltp->len+i;
} else
if(ltp->fl==0)
{
/* label has not been defined yet, (e.g. pass1 forward ref), so we try to set it. */
*l=ltp->len+i;
if(b_ltest(ltp->blk,b))
er=E_LABDEF;
@ -213,7 +280,7 @@ int l_def(char *s, int *l, int *x, int *f)
} else
if(er==E_NODEF)
{
if(!(er=ll_def(s+i,&n,b))) /* ll_def(...,*f) */
if(!(er=ll_def(s+i,&n,b))) /* store the label in the table of labels */
{
ltp=afile->la.lt+n;
*l=ltp->len+i;
@ -229,15 +296,23 @@ int l_def(char *s, int *l, int *x, int *f)
int l_search(char *s, int *l, int *x, int *v, int *afl)
{
int n,er,b;
int cll_fl;
*afl=0;
er=ll_search(s,&n);
/*printf("l_search: lab=%s(l=%d), afl=%d, er=%d, n=%d\n",s,*l, *afl,er,n);*/
/* check cheap local label */
cll_fl=0;
if (s[0]=='@') {
cll_fl=1; /* also used as offset to the label length, so must be 1 */
s++;
}
er=ll_search(s,&n, cll_fl);
/*printf("l_search: lab=%s(l=%d, afl=%d, er=%d, n=%d, cll_fl=%d, cll_cur=%d)\n",s,*l, *afl,er,n, cll_fl, cll_getcur());*/
if(er==E_OK)
{
ltp=afile->la.lt+n;
*l=ltp->len;
*l=ltp->len + cll_fl;
if(ltp->fl == 1)
{
l_get(n,v,afl);/* *v=lt[n].val;*/
@ -251,12 +326,17 @@ int l_search(char *s, int *l, int *x, int *v, int *afl)
}
else
{
b_get(&b);
if(cll_fl) {
b=cll_get();
} else {
b_get(&b);
}
er=ll_def(s,x,b); /* ll_def(...,*v); */
ltp=afile->la.lt+(*x);
*l=ltp->len;
*l=ltp->len + cll_fl;
if(!er)
{
@ -401,8 +481,14 @@ static int ll_def(char *s, int *n, int b) /* definiert naechstes Label
return(er);
}
int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
/**
* search a label name in the label table. Return the label number
* in "n". Finds only labels that are in a block that is in the current
* set of blocks (in the block stack)
*
* If cll_fl is set, the label is also searched in the local cheap label scope
*/
int ll_search(char *s, int *n, int cll_fl) /* search Label in Tabelle ,nr->n */
{
int i,j=0,k,er=E_NODEF,hash;
@ -411,7 +497,6 @@ int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
hash=hashcode(s,j);
i=afile->la.hashindex[hash];
/*printf("search?\n");*/
if(i>=afile->la.ltm) return E_NODEF;
do
@ -422,11 +507,21 @@ int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
{
for (k=0;(k<j)&&(ltp->n[k]==s[k]);k++);
if((j==k)&&(!b_test(ltp->blk)))
{
er=E_OK;
break;
}
if (cll_fl) {
if (ltp->blk == cll_getcur()) {
er=E_OK;
break;
}
} else {
/* check if the found label is in any of the blocks in the
current block stack */
if((j==k)&&(!b_test(ltp->blk)))
{
/* ok, label found and it is reachable (its block nr is in the current block stack */
er=E_OK;
break;
}
}
}
if(!i)
@ -451,7 +546,7 @@ int ll_pdef(char *t)
{
int n;
if(ll_search(t,&n)==E_OK)
if(ll_search(t,&n, 0)==E_OK)
{
ltp=afile->la.lt+n;
if(ltp->fl)
@ -496,9 +591,22 @@ int l_write(FILE *fp)
return 0;
}
static int bt[MAXBLK];
static int blk;
static int bi;
/*******************************************************************************************
* block management code. Here the ".(" and ".)" blocks are maintained.
*
* Blocks are numbered uniquely, every time a new block is opened, the "blk" variable
* is increased and its number used as block number.
*
* The currently open blocks are maintained in a stack (bt[]). The lowest entry is the outermost
* block number, adding block numbers as blocks are opened. When a block is closed,
* the block stack is shortened again (bi has the length of the block stack)
*
* Methods exist to open new blocks, close a block, and do some checks, e.g. whether
* a specific block number is contained in the current block stack.
*/
static int bt[MAXBLK]; /* block stack */
static int bi; /* length of the block stack (minus 1, i.e. bi[bi] has the innermost block) */
static int blk; /* current block number for allocation */
int b_init(void)
{
@ -509,6 +617,11 @@ int b_init(void)
return(E_OK);
}
int b_new(void)
{
return ++blk;
}
int b_depth(void)
{
return bi;
@ -519,19 +632,25 @@ int ga_blk(void)
return(blk);
}
/**
* open a new block scope
*/
int b_open(void)
{
int er=E_BLKOVR;
if(bi<MAXBLK-1)
{
bt[++bi]=++blk;
bt[++bi]=b_new();
er=E_OK;
}
return(er);
}
/**
* close a block scope
*/
int b_close(void)
{
@ -546,6 +665,9 @@ int b_close(void)
return(E_OK);
}
/**
* get the block number of the current innermost block
*/
static int b_get(int *n)
{
*n=bt[bi];
@ -553,6 +675,9 @@ static int b_get(int *n)
return(E_OK);
}
/**
* returns the block number of the block "i" levels up in the current block stack
*/
static int b_fget(int *n, int i)
{
if((bi-i)>=0)
@ -562,6 +687,10 @@ static int b_fget(int *n, int i)
return(E_OK);
}
/**
* tests whether the given block number n is in the current stack of
* current block numbers bt[]
*/
static int b_test(int n)
{
int i=bi;
@ -572,6 +701,9 @@ static int b_test(int n)
return( i+1 ? E_OK : E_NOBLK );
}
/**
* tests whether the given block number "a" is in the
*/
static int b_ltest(int a, int b) /* testet ob bt^-1(b) in intervall [0,bt^-1(a)] */
{
int i=0,er=E_OK;

View File

@ -42,7 +42,7 @@ int l_search(char *s, int *l, int *x, int *v, int *afl);
void l_set(int n, int v, int afl);
int l_get(int n, int *v, int *afl);
int l_vget(int n, int *v, char **s);
int ll_search(char *s, int *n);
int ll_search(char *s, int *n, int cll_fl);
int ll_pdef(char *t);
int b_open(void);

View File

@ -130,7 +130,7 @@ int pp_ifldef(char *t)
int pp_iflused(char *t)
{
int n;
loopfl=(loopfl<<1)+( ll_search(t,&n) ? 1 : 0 );
loopfl=(loopfl<<1)+( ll_search(t,&n,0) ? 1 : 0 );
return(0);
}

View File

@ -75,7 +75,7 @@ static char *kt[] ={
".byt",".word",".asc",".dsb", ".(", ".)", "*=", ".text",".data",".bss",
".zero",".fopt", ".byte", ".end", ".list", ".xlist", ".dupb", ".blkb", ".db", ".dw",
".align",".block", ".bend",".al",".as",".xl",".xs", ".bin", ".aasc"
".align",".block", ".bend",".al",".as",".xl",".xs", ".bin", ".aasc", ".code"
};
@ -85,7 +85,7 @@ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2 };
/* last valid mnemonic */
#define Lastbef 93
/* last valid token+1 */
#define Anzkey 123
#define Anzkey 124
#define Kbyt Lastbef+1
#define Kword Lastbef+2
@ -119,6 +119,8 @@ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2 };
#define Kbin Lastbef+28
#define Kaasc Lastbef+29
#define Kcode Lastbef+30 /* gets remapped to Ktext */
#define Kreloc Anzkey /* *= (relocation mode) */
#define Ksegment Anzkey+1
@ -349,6 +351,7 @@ fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
printf("\n");
*/
/* if text/data produced, then no more fopt allowed in romable mode */
/* TODO: need to check, Kbyte is being remapped to Kbyt. What is the effect here? */
if((romable>1) && (t[0]<Kopen || t[0]==Kbyte || t[0]==Kpcdef)) {
afile->base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length();
romable=1;
@ -1536,7 +1539,8 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
static int v,f;
static int operand,o;
int fl,afl;
int p,q,ud,n,ll,mk,er;
int p,q,ud,ll,mk,er;
int n; /* label number to be passed between l_def (definition) and l_set (set the value) */
int m, uz, byte;
static unsigned char cast;
@ -1586,6 +1590,7 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
if(s[p]=='=')
{
/*printf("Found = @%s\n",s+p);*/
t[q++]=T_OP;
t[q++]=n&255;
t[q++]=(n>>8)&255;
@ -1594,6 +1599,17 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
ll=n=0;
break;
} else
if(s[p]==':' && s[p+1]=='=') /* support := label assignments (ca65 compatibility) */
{
/*printf("Found := @%s\n", s+p);*/
t[q++]=T_OP;
t[q++]=n&255;
t[q++]=(n>>8)&255;
t[q++]='=';
p+=2;
ll=n=0;
break;
} else
if(f && s[p]!='\0' && s[p+1]=='=')
{
t[q++]=T_OP;
@ -1674,8 +1690,10 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
if(operand)
{
/* are we forcing the operand into a particular
addressing mode? !, @, ` operators */
if(s[p]=='!' || s[p]=='@' || s[p]=='`')
addressing mode? !, @, ` operators
Note these are not available in ca65, but we only
switch off "@" which are used for cheap local labels*/
if(s[p]=='!' || (s[p]=='@' && !ca65) || s[p]=='`')
{
cast=s[p];
operand= -operand+1;
@ -1691,12 +1709,12 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
{
t[q++]=s[p++];
} else
/* maybe it's a label */
if(isalpha(s[p]) || s[p]=='_')
/* maybe it's a label
Note that for ca65 cheap local labels, we check for "@" */
if(isalpha(s[p]) || s[p]=='_' || (s[p]=='@' && ca65))
{
m=n;
er=l_search((char*)s+p,&ll,&n,&v,&afl);
/*
if(m==Kglobl || m==Kextzero) {
if(er==E_NODEF) {
@ -1961,6 +1979,7 @@ static int t_keyword(signed char *s, int *l, int *n)
if(i==Kdw) i=Kword;
if(i==Kblock) i=Kopen;
if(i==Kbend) i=Kclose;
if(i==Kcode) i=Ktext;
*l=j;