mirror of
https://github.com/fachat/xa65.git
synced 2025-08-19 01:27:27 +00:00
added ca65 compatibiltiy patch
This commit is contained in:
19
xa/man/xa.1
19
xa/man/xa.1
@@ -19,6 +19,9 @@ further in this manual page.
|
|||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
.B \-E
|
||||||
|
Do not stop after 20 errors, but show all errors.
|
||||||
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Verbose output.
|
Verbose output.
|
||||||
.TP
|
.TP
|
||||||
@@ -67,9 +70,18 @@ to reconstruct source.
|
|||||||
Add cross-reference list to labellist (requires
|
Add cross-reference list to labellist (requires
|
||||||
.BR \-l ).
|
.BR \-l ).
|
||||||
.TP
|
.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
|
.B \-M
|
||||||
Allow colons to appear in comments; for MASM compatibility. This does
|
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
|
.TP
|
||||||
.B \-R
|
.B \-R
|
||||||
Start assembler in relocating mode.
|
Start assembler in relocating mode.
|
||||||
@@ -339,7 +351,7 @@ for those opcodes that support it (i.e., keep as 16 bit word)
|
|||||||
.B @
|
.B @
|
||||||
render as 24-bit quantity for 65816 (must specify
|
render as 24-bit quantity for 65816 (must specify
|
||||||
.B \-w
|
.B \-w
|
||||||
command-line option).
|
command-line option, must not specify the CA65 compatibility).
|
||||||
.B This is required to specify any
|
.B This is required to specify any
|
||||||
.B 24-bit quantity!
|
.B 24-bit quantity!
|
||||||
.TP
|
.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
|
allocation. In .bss and .zero, only labels are evaluated. These pseudo-ops
|
||||||
are valid in relative and absolute modes.
|
are valid in relative and absolute modes.
|
||||||
.TP
|
.TP
|
||||||
|
.B .code
|
||||||
|
For CA65 compatibility this is currently mapped to ".text".
|
||||||
|
.TP
|
||||||
.B .align value
|
.B .align value
|
||||||
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
|
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
|
||||||
.B
|
.B
|
||||||
|
91
xa/src/xa.c
91
xa/src/xa.c
@@ -61,7 +61,10 @@
|
|||||||
|
|
||||||
/* exported globals */
|
/* exported globals */
|
||||||
int ncmos, cmosfl, w65816, n65816;
|
int ncmos, cmosfl, w65816, n65816;
|
||||||
int masm = 0;
|
/* compatibility flags */
|
||||||
|
int masm = 0; /* MASM */
|
||||||
|
int ca65 = 0; /* CA65 */
|
||||||
|
|
||||||
int nolink = 0;
|
int nolink = 0;
|
||||||
int romable = 0;
|
int romable = 0;
|
||||||
int romaddr = 0;
|
int romaddr = 0;
|
||||||
@@ -71,10 +74,12 @@ int crossref = 0;
|
|||||||
char altppchar;
|
char altppchar;
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
|
|
||||||
static char out[MAXLINE];
|
static char out[MAXLINE];
|
||||||
static time_t tim1, tim2;
|
static time_t tim1, tim2;
|
||||||
static FILE *fpout, *fperr, *fplab;
|
static FILE *fpout, *fperr, *fplab;
|
||||||
static int ner = 0;
|
static int ner = 0;
|
||||||
|
static int ner_max = 20;
|
||||||
|
|
||||||
static int align = 1;
|
static int align = 1;
|
||||||
|
|
||||||
@@ -91,6 +96,7 @@ static int getline(char *);
|
|||||||
static void lineout(void);
|
static void lineout(void);
|
||||||
static long ga_p1(void);
|
static long ga_p1(void);
|
||||||
static long gm_p1(void);
|
static long gm_p1(void);
|
||||||
|
static int set_compat(char *compat_name);
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
int memode,xmode;
|
int memode,xmode;
|
||||||
@@ -191,6 +197,9 @@ int main(int argc,char *argv[])
|
|||||||
while(i<argc) {
|
while(i<argc) {
|
||||||
if(argv[i][0]=='-') {
|
if(argv[i][0]=='-') {
|
||||||
switch(argv[i][1]) {
|
switch(argv[i][1]) {
|
||||||
|
case 'E':
|
||||||
|
ner_max = 0;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* intentionally not allowing an argument to follow with a
|
/* intentionally not allowing an argument to follow with a
|
||||||
space to avoid - being seen as the alternate
|
space to avoid - being seen as the alternate
|
||||||
@@ -210,6 +219,19 @@ int main(int argc,char *argv[])
|
|||||||
case 'M':
|
case 'M':
|
||||||
masm = 1; /* MASM compatibility mode */
|
masm = 1; /* MASM compatibility mode */
|
||||||
break;
|
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 */
|
case 'O': /* output charset */
|
||||||
{
|
{
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
@@ -500,7 +522,12 @@ int main(int argc,char *argv[])
|
|||||||
|
|
||||||
if(ner || er)
|
if(ner || er)
|
||||||
{
|
{
|
||||||
|
if (ner_max > 0) {
|
||||||
fprintf(stderr, "Break after %d error%c\n",ner,ner?'s':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();*/
|
/*unlink();*/
|
||||||
if(ofile) {
|
if(ofile) {
|
||||||
unlink(ofile);
|
unlink(ofile);
|
||||||
@@ -615,7 +642,7 @@ static int pass2(void)
|
|||||||
filep=&datei;
|
filep=&datei;
|
||||||
afile->mn.tmpe=0L;
|
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++];
|
l=afile->mn.tmp[afile->mn.tmpe++];
|
||||||
ll=l;
|
ll=l;
|
||||||
@@ -827,6 +854,7 @@ static void usage(int default816, FILE *fp)
|
|||||||
programname);
|
programname);
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
" -v verbose output\n"
|
" -v verbose output\n"
|
||||||
|
" -E do not break after 20 errors, but show all\n"
|
||||||
" -x old filename behaviour (overrides `-o', `-e', `-l')\n"
|
" -x old filename behaviour (overrides `-o', `-e', `-l')\n"
|
||||||
" This is deprecated and may disappear in future versions!\n"
|
" This is deprecated and may disappear in future versions!\n"
|
||||||
" -C no CMOS-opcodes\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"
|
" -l filename sets labellist filename, default is none\n"
|
||||||
" -r adds crossreference list to labellist (if `-l' given)\n"
|
" -r adds crossreference list to labellist (if `-l' given)\n"
|
||||||
" -M allow ``:'' to appear in comments for MASM compatibility\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");
|
" -R start assembler in relocating mode\n");
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
" -Llabel defines `label' as absolute, undefined label even when linking\n"
|
" -Llabel defines `label' as absolute, undefined label even when linking\n"
|
||||||
@@ -900,7 +930,7 @@ static char *ertxt[] = {
|
|||||||
"NewFile",
|
"NewFile",
|
||||||
"CMOS-Befehl",
|
"CMOS-Befehl",
|
||||||
"pp:Wrong parameter count",
|
"pp:Wrong parameter count",
|
||||||
"Illegal pointer arithmetic",
|
"Illegal pointer arithmetic (-26)",
|
||||||
"Illegal segment",
|
"Illegal segment",
|
||||||
"File header option too long",
|
"File header option too long",
|
||||||
"File option not at file start (when ROM-able)",
|
"File option not at file start (when ROM-able)",
|
||||||
@@ -939,11 +969,10 @@ static char *ertxt[] = {
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
|
||||||
/* warnings */
|
/* warnings */
|
||||||
"Cutting word relocation in byte value",
|
"Cutting word relocation in byte value",
|
||||||
"Byte relocation in word value",
|
"Byte relocation in word value",
|
||||||
"Illegal pointer arithmetic",
|
"Illegal pointer arithmetic (-66)",
|
||||||
"Address access to low or high byte pointer",
|
"Address access to low or high byte pointer",
|
||||||
"High byte access to low byte pointer",
|
"High byte access to low byte pointer",
|
||||||
"Low byte access to high byte pointer",
|
"Low byte access to high byte pointer",
|
||||||
@@ -1062,9 +1091,20 @@ static int getline(char *s)
|
|||||||
comcom = 1;
|
comcom = 1;
|
||||||
if (c=='\0')
|
if (c=='\0')
|
||||||
break; /* hkfl = comcom = 0 */
|
break; /* hkfl = comcom = 0 */
|
||||||
if (c==':' && !hkfl && (!comcom || !masm)) {
|
if (c==':' && !hkfl) {
|
||||||
gl=1;
|
/* if the next char is a "=" - so that we have a ":=" - and we
|
||||||
break;
|
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++;
|
j++;
|
||||||
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
||||||
@@ -1072,7 +1112,9 @@ static int getline(char *s)
|
|||||||
s[j]='\0';
|
s[j]='\0';
|
||||||
} else
|
} else
|
||||||
s[0]='\0';
|
s[0]='\0';
|
||||||
|
#if 0
|
||||||
|
printf("got line: %s\n", s);
|
||||||
|
#endif
|
||||||
return(ec);
|
return(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1092,8 +1134,8 @@ static void lineout(void)
|
|||||||
|
|
||||||
void errout(int er)
|
void errout(int er)
|
||||||
{
|
{
|
||||||
if (er<-ANZERR || er>-1) {
|
if (er<=-ANZERR || er>-1) {
|
||||||
if(er>=-(ANZERR+ANZWARN) && er < -ANZERR) {
|
if(er>=-(ANZERR+ANZWARN) && er <= -ANZERR) {
|
||||||
sprintf(out,"%s:line %d: %04x: Warning - %s\n",
|
sprintf(out,"%s:line %d: %04x: Warning - %s\n",
|
||||||
filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]);
|
filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]);
|
||||||
} else {
|
} else {
|
||||||
@@ -1129,3 +1171,30 @@ void logout(char *s)
|
|||||||
fprintf(fperr,"%s",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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
#include "xah.h" /* For SEG_MAX */
|
#include "xah.h" /* For SEG_MAX */
|
||||||
|
|
||||||
extern int ncmos, cmosfl, w65816, n65816;
|
extern int ncmos, cmosfl, w65816, n65816;
|
||||||
extern int masm, nolink;
|
extern int masm, ca65, nolink;
|
||||||
extern int noglob;
|
extern int noglob;
|
||||||
extern int showblk;
|
extern int showblk;
|
||||||
extern int relmode;
|
extern int relmode;
|
||||||
|
@@ -180,6 +180,8 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
} else {
|
} else {
|
||||||
if(segment!=SEG_ABS) {
|
if(segment!=SEG_ABS) {
|
||||||
if(!dsb_len) {
|
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;
|
er=E_ILLPOINTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
xa/src/xah.h
13
xa/src/xah.h
@@ -20,15 +20,22 @@
|
|||||||
#ifndef __XA65_XAH_H__
|
#ifndef __XA65_XAH_H__
|
||||||
#define __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 LABMEM 40000L
|
||||||
#define MAXLAB 32
|
#define MAXLAB 32
|
||||||
#define MAXBLK 16
|
#define MAXBLK 16
|
||||||
#define MAXFILE 7
|
#define MAXFILE 7
|
||||||
#define MAXLINE 2048
|
#define MAXLINE 2048
|
||||||
#define MAXPP 40000L
|
#define MAXPP 40000L
|
||||||
#define ANZDEF 2340 /* mal 14 -> Byte, ANZDEF * 14 < 32768 */
|
#define ANZDEF 2340 /* multiplied by sizeof(List) -> Byte, ANZDEF * 20 < 32768 */
|
||||||
#define TMPMEM 200000L /* Zwischenspeicher von Pass1 nach Pass 2 */
|
#define TMPMEM 200000L /* temporary memory buffer from Pass1 to Pass 2 */
|
||||||
|
|
||||||
typedef struct LabOcc {
|
typedef struct LabOcc {
|
||||||
struct LabOcc *next;
|
struct LabOcc *next;
|
||||||
|
194
xa/src/xal.c
194
xa/src/xal.c
@@ -50,6 +50,12 @@ static int b_get(int*);
|
|||||||
static int b_test(int);
|
static int b_test(int);
|
||||||
static int ll_def(char *s, int *n, int b);
|
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 */
|
/* local variables */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -69,6 +75,7 @@ static Labtab *ltp;
|
|||||||
|
|
||||||
int l_init(void)
|
int l_init(void)
|
||||||
{
|
{
|
||||||
|
cll_init();
|
||||||
return 0;
|
return 0;
|
||||||
#if 0
|
#if 0
|
||||||
int er;
|
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 lg_set(char *s ) {
|
||||||
int n, er;
|
int n, er;
|
||||||
|
|
||||||
er = ll_search(s,&n);
|
er = ll_search(s,&n, 0);
|
||||||
|
|
||||||
if(er==E_OK) {
|
if(er==E_OK) {
|
||||||
fprintf(stderr,"Warning: global label doubly defined!\n");
|
fprintf(stderr,"Warning: global label doubly defined!\n");
|
||||||
@@ -156,52 +202,73 @@ int lg_set(char *s ) {
|
|||||||
return er;
|
return er;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
int l_def(char *s, int *l, int *x, int *f)
|
int l_def(char *s, int *l, int *x, int *f)
|
||||||
{
|
{
|
||||||
int n,er,b,i=0;
|
int n,er,b,i=0;
|
||||||
|
int cll_fl;
|
||||||
|
|
||||||
*f=0;
|
*f=0; /* flag (given as param) that the label is to be re-defined and the
|
||||||
b=0;
|
"label defined error" is to be skipped */
|
||||||
n=0;
|
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]=='-')
|
if(s[0]=='-')
|
||||||
{
|
{
|
||||||
*f+=1;
|
*f+=1; /* label is being redefined */
|
||||||
i++;
|
i++;
|
||||||
} else
|
} 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]=='+')
|
if(s[0]=='+')
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
n++;
|
n++; /* block number b is absolute */
|
||||||
b=0;
|
b=0; /* global block number */
|
||||||
}
|
}
|
||||||
while(s[i]=='&')
|
while(s[i]=='&')
|
||||||
{
|
{
|
||||||
n=0;
|
if (n) b=0; /* reset block number */
|
||||||
|
n=0; /* block number is relative */
|
||||||
i++;
|
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);
|
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;
|
er=E_SYNTAX;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
er=ll_search(s+i,&n);
|
er=ll_search(s+i,&n, cll_fl);
|
||||||
|
|
||||||
if(er==E_OK)
|
if(er==E_OK)
|
||||||
{
|
{
|
||||||
|
/* we actually found an existing label in the same scope */
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
|
|
||||||
if(*f)
|
if(*f)
|
||||||
{
|
{
|
||||||
|
/* redefinition of label */
|
||||||
*l=ltp->len+i;
|
*l=ltp->len+i;
|
||||||
} else
|
} else
|
||||||
if(ltp->fl==0)
|
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;
|
*l=ltp->len+i;
|
||||||
if(b_ltest(ltp->blk,b))
|
if(b_ltest(ltp->blk,b))
|
||||||
er=E_LABDEF;
|
er=E_LABDEF;
|
||||||
@@ -213,7 +280,7 @@ int l_def(char *s, int *l, int *x, int *f)
|
|||||||
} else
|
} else
|
||||||
if(er==E_NODEF)
|
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;
|
ltp=afile->la.lt+n;
|
||||||
*l=ltp->len+i;
|
*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 l_search(char *s, int *l, int *x, int *v, int *afl)
|
||||||
{
|
{
|
||||||
int n,er,b;
|
int n,er,b;
|
||||||
|
int cll_fl;
|
||||||
|
|
||||||
*afl=0;
|
*afl=0;
|
||||||
|
|
||||||
er=ll_search(s,&n);
|
/* check cheap local label */
|
||||||
/*printf("l_search: lab=%s(l=%d), afl=%d, er=%d, n=%d\n",s,*l, *afl,er,n);*/
|
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)
|
if(er==E_OK)
|
||||||
{
|
{
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
*l=ltp->len;
|
*l=ltp->len + cll_fl;
|
||||||
if(ltp->fl == 1)
|
if(ltp->fl == 1)
|
||||||
{
|
{
|
||||||
l_get(n,v,afl);/* *v=lt[n].val;*/
|
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
|
else
|
||||||
{
|
{
|
||||||
b_get(&b);
|
if(cll_fl) {
|
||||||
|
b=cll_get();
|
||||||
|
} else {
|
||||||
|
b_get(&b);
|
||||||
|
}
|
||||||
|
|
||||||
er=ll_def(s,x,b); /* ll_def(...,*v); */
|
er=ll_def(s,x,b); /* ll_def(...,*v); */
|
||||||
|
|
||||||
ltp=afile->la.lt+(*x);
|
ltp=afile->la.lt+(*x);
|
||||||
|
|
||||||
*l=ltp->len;
|
*l=ltp->len + cll_fl;
|
||||||
|
|
||||||
if(!er)
|
if(!er)
|
||||||
{
|
{
|
||||||
@@ -401,8 +481,14 @@ static int ll_def(char *s, int *n, int b) /* definiert naechstes Label
|
|||||||
return(er);
|
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;
|
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);
|
hash=hashcode(s,j);
|
||||||
i=afile->la.hashindex[hash];
|
i=afile->la.hashindex[hash];
|
||||||
|
|
||||||
/*printf("search?\n");*/
|
|
||||||
if(i>=afile->la.ltm) return E_NODEF;
|
if(i>=afile->la.ltm) return E_NODEF;
|
||||||
|
|
||||||
do
|
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++);
|
for (k=0;(k<j)&&(ltp->n[k]==s[k]);k++);
|
||||||
|
|
||||||
if((j==k)&&(!b_test(ltp->blk)))
|
if (cll_fl) {
|
||||||
{
|
if (ltp->blk == cll_getcur()) {
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
break;
|
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)
|
if(!i)
|
||||||
@@ -451,7 +546,7 @@ int ll_pdef(char *t)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if(ll_search(t,&n)==E_OK)
|
if(ll_search(t,&n, 0)==E_OK)
|
||||||
{
|
{
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
if(ltp->fl)
|
if(ltp->fl)
|
||||||
@@ -496,9 +591,22 @@ int l_write(FILE *fp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bt[MAXBLK];
|
/*******************************************************************************************
|
||||||
static int blk;
|
* block management code. Here the ".(" and ".)" blocks are maintained.
|
||||||
static int bi;
|
*
|
||||||
|
* 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)
|
int b_init(void)
|
||||||
{
|
{
|
||||||
@@ -509,6 +617,11 @@ int b_init(void)
|
|||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int b_new(void)
|
||||||
|
{
|
||||||
|
return ++blk;
|
||||||
|
}
|
||||||
|
|
||||||
int b_depth(void)
|
int b_depth(void)
|
||||||
{
|
{
|
||||||
return bi;
|
return bi;
|
||||||
@@ -519,19 +632,25 @@ int ga_blk(void)
|
|||||||
return(blk);
|
return(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* open a new block scope
|
||||||
|
*/
|
||||||
int b_open(void)
|
int b_open(void)
|
||||||
{
|
{
|
||||||
int er=E_BLKOVR;
|
int er=E_BLKOVR;
|
||||||
|
|
||||||
if(bi<MAXBLK-1)
|
if(bi<MAXBLK-1)
|
||||||
{
|
{
|
||||||
bt[++bi]=++blk;
|
bt[++bi]=b_new();
|
||||||
|
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
}
|
}
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close a block scope
|
||||||
|
*/
|
||||||
int b_close(void)
|
int b_close(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -546,6 +665,9 @@ int b_close(void)
|
|||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the block number of the current innermost block
|
||||||
|
*/
|
||||||
static int b_get(int *n)
|
static int b_get(int *n)
|
||||||
{
|
{
|
||||||
*n=bt[bi];
|
*n=bt[bi];
|
||||||
@@ -553,6 +675,9 @@ static int b_get(int *n)
|
|||||||
return(E_OK);
|
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)
|
static int b_fget(int *n, int i)
|
||||||
{
|
{
|
||||||
if((bi-i)>=0)
|
if((bi-i)>=0)
|
||||||
@@ -562,6 +687,10 @@ static int b_fget(int *n, int i)
|
|||||||
return(E_OK);
|
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)
|
static int b_test(int n)
|
||||||
{
|
{
|
||||||
int i=bi;
|
int i=bi;
|
||||||
@@ -572,6 +701,9 @@ static int b_test(int n)
|
|||||||
return( i+1 ? E_OK : E_NOBLK );
|
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)] */
|
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;
|
int i=0,er=E_OK;
|
||||||
|
@@ -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);
|
void l_set(int n, int v, int afl);
|
||||||
int l_get(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 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 ll_pdef(char *t);
|
||||||
|
|
||||||
int b_open(void);
|
int b_open(void);
|
||||||
|
@@ -130,7 +130,7 @@ int pp_ifldef(char *t)
|
|||||||
int pp_iflused(char *t)
|
int pp_iflused(char *t)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
loopfl=(loopfl<<1)+( ll_search(t,&n) ? 1 : 0 );
|
loopfl=(loopfl<<1)+( ll_search(t,&n,0) ? 1 : 0 );
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
xa/src/xat.c
35
xa/src/xat.c
@@ -75,7 +75,7 @@ static char *kt[] ={
|
|||||||
|
|
||||||
".byt",".word",".asc",".dsb", ".(", ".)", "*=", ".text",".data",".bss",
|
".byt",".word",".asc",".dsb", ".(", ".)", "*=", ".text",".data",".bss",
|
||||||
".zero",".fopt", ".byte", ".end", ".list", ".xlist", ".dupb", ".blkb", ".db", ".dw",
|
".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 */
|
/* last valid mnemonic */
|
||||||
#define Lastbef 93
|
#define Lastbef 93
|
||||||
/* last valid token+1 */
|
/* last valid token+1 */
|
||||||
#define Anzkey 123
|
#define Anzkey 124
|
||||||
|
|
||||||
#define Kbyt Lastbef+1
|
#define Kbyt Lastbef+1
|
||||||
#define Kword Lastbef+2
|
#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 Kbin Lastbef+28
|
||||||
#define Kaasc Lastbef+29
|
#define Kaasc Lastbef+29
|
||||||
|
|
||||||
|
#define Kcode Lastbef+30 /* gets remapped to Ktext */
|
||||||
|
|
||||||
#define Kreloc Anzkey /* *= (relocation mode) */
|
#define Kreloc Anzkey /* *= (relocation mode) */
|
||||||
#define Ksegment Anzkey+1
|
#define Ksegment Anzkey+1
|
||||||
|
|
||||||
@@ -349,6 +351,7 @@ fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
*/
|
*/
|
||||||
/* if text/data produced, then no more fopt allowed in romable mode */
|
/* 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)) {
|
if((romable>1) && (t[0]<Kopen || t[0]==Kbyte || t[0]==Kpcdef)) {
|
||||||
afile->base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length();
|
afile->base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length();
|
||||||
romable=1;
|
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 v,f;
|
||||||
static int operand,o;
|
static int operand,o;
|
||||||
int fl,afl;
|
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;
|
int m, uz, byte;
|
||||||
static unsigned char cast;
|
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]=='=')
|
if(s[p]=='=')
|
||||||
{
|
{
|
||||||
|
/*printf("Found = @%s\n",s+p);*/
|
||||||
t[q++]=T_OP;
|
t[q++]=T_OP;
|
||||||
t[q++]=n&255;
|
t[q++]=n&255;
|
||||||
t[q++]=(n>>8)&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;
|
ll=n=0;
|
||||||
break;
|
break;
|
||||||
} else
|
} 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]=='=')
|
if(f && s[p]!='\0' && s[p+1]=='=')
|
||||||
{
|
{
|
||||||
t[q++]=T_OP;
|
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)
|
if(operand)
|
||||||
{
|
{
|
||||||
/* are we forcing the operand into a particular
|
/* are we forcing the operand into a particular
|
||||||
addressing mode? !, @, ` operators */
|
addressing mode? !, @, ` operators
|
||||||
if(s[p]=='!' || s[p]=='@' || s[p]=='`')
|
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];
|
cast=s[p];
|
||||||
operand= -operand+1;
|
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++];
|
t[q++]=s[p++];
|
||||||
} else
|
} else
|
||||||
/* maybe it's a label */
|
/* maybe it's a label
|
||||||
if(isalpha(s[p]) || s[p]=='_')
|
Note that for ca65 cheap local labels, we check for "@" */
|
||||||
|
if(isalpha(s[p]) || s[p]=='_' || (s[p]=='@' && ca65))
|
||||||
{
|
{
|
||||||
m=n;
|
m=n;
|
||||||
er=l_search((char*)s+p,&ll,&n,&v,&afl);
|
er=l_search((char*)s+p,&ll,&n,&v,&afl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(m==Kglobl || m==Kextzero) {
|
if(m==Kglobl || m==Kextzero) {
|
||||||
if(er==E_NODEF) {
|
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==Kdw) i=Kword;
|
||||||
if(i==Kblock) i=Kopen;
|
if(i==Kblock) i=Kopen;
|
||||||
if(i==Kbend) i=Kclose;
|
if(i==Kbend) i=Kclose;
|
||||||
|
if(i==Kcode) i=Ktext;
|
||||||
|
|
||||||
|
|
||||||
*l=j;
|
*l=j;
|
||||||
|
Reference in New Issue
Block a user