mirror of
https://github.com/fachat/xa65.git
synced 2024-07-02 02:29:41 +00:00
Compare commits
3 Commits
master
...
xa-2.3.5+c
Author | SHA1 | Date | |
---|---|---|---|
|
1691f5fb46 | ||
|
eae097c73a | ||
|
f28af4a917 |
16
xa/ChangeLog
16
xa/ChangeLog
|
@ -295,3 +295,19 @@ xa-2.3.5
|
||||||
* Documentation updated.
|
* Documentation updated.
|
||||||
|
|
||||||
-- Cameron Kaiser <ckaiser@floodgap.com> 7 February, 2009
|
-- Cameron Kaiser <ckaiser@floodgap.com> 7 February, 2009
|
||||||
|
|
||||||
|
xa-2.x.x
|
||||||
|
|
||||||
|
* Add -E commandline option to not stop after 20 errors, but show all
|
||||||
|
of them
|
||||||
|
* Introduce -X compatibility set commandline option, to distinguish
|
||||||
|
between MASM and CA65 compatibility options
|
||||||
|
* Implement CA65 "cheap local labels", ":=" label definitions,
|
||||||
|
and various pseudo opcodes (.include, .import, .importzp,
|
||||||
|
.zeropage, .proc (anonymous only), .endproc, .code, .org, .reloc)
|
||||||
|
* some bugfixes around error/warning logs
|
||||||
|
* some more comments
|
||||||
|
* Stuff is mostly untested...
|
||||||
|
|
||||||
|
-- André Fachat <afachat@gmx.de> 25 June, 2011
|
||||||
|
|
||||||
|
|
59
xa/man/xa.1
59
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
|
||||||
|
@ -54,6 +57,11 @@ use the special filename
|
||||||
.BR \-
|
.BR \-
|
||||||
to output to standard output.
|
to output to standard output.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-P filename
|
||||||
|
Set listing filename, default is none. use the special filename
|
||||||
|
.BR \-
|
||||||
|
to print the listing to standard output.
|
||||||
|
.TP
|
||||||
.B \-e filename
|
.B \-e filename
|
||||||
Set errorlog filename, default is none.
|
Set errorlog filename, default is none.
|
||||||
.TP
|
.TP
|
||||||
|
@ -67,9 +75,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 +356,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
|
||||||
|
@ -441,7 +458,7 @@ and
|
||||||
are synonymous, so you can mix things such as
|
are synonymous, so you can mix things such as
|
||||||
.B .byt $43, 22, """a character string"""
|
.B .byt $43, 22, """a character string"""
|
||||||
and get the expected result. The string is subject to the current character
|
and get the expected result. The string is subject to the current character
|
||||||
set, but the remaining bytes are inserted wtihout modification.
|
set, but the remaining bytes are inserted without modification.
|
||||||
.TP
|
.TP
|
||||||
.B .aasc """text1""","text2",...
|
.B .aasc """text1""","text2",...
|
||||||
Specifies a character string that is
|
Specifies a character string that is
|
||||||
|
@ -492,9 +509,20 @@ or precede it with
|
||||||
.B &
|
.B &
|
||||||
to declare it within the previous level only (or globally if you are only
|
to declare it within the previous level only (or globally if you are only
|
||||||
one level deep). Sixteen levels of scoping are permitted.
|
one level deep). Sixteen levels of scoping are permitted.
|
||||||
|
.B \&.)
|
||||||
|
is equivalent to
|
||||||
|
.B .block
|
||||||
|
or
|
||||||
|
.B .proc
|
||||||
|
. The latter is similar to the ca65 pseudo-opcode, but only anonymous blocks
|
||||||
|
are supported.
|
||||||
.TP
|
.TP
|
||||||
.B \&.)
|
.B \&.)
|
||||||
Closes a block.
|
Closes a block. This is equivalent to
|
||||||
|
.B .bend
|
||||||
|
or
|
||||||
|
.B .endproc
|
||||||
|
.
|
||||||
.TP
|
.TP
|
||||||
.B \.as \.al \.xs \.xl
|
.B \.as \.al \.xs \.xl
|
||||||
Only relevant in 65816 mode (with the
|
Only relevant in 65816 mode (with the
|
||||||
|
@ -521,6 +549,11 @@ and
|
||||||
generate errors if
|
generate errors if
|
||||||
.B \-w
|
.B \-w
|
||||||
is not specified.
|
is not specified.
|
||||||
|
.TP
|
||||||
|
.B .include "filename"
|
||||||
|
Includes another file in place of the pseudo opcode. Same as the preprocessor
|
||||||
|
.B #include
|
||||||
|
|
||||||
.LP
|
.LP
|
||||||
The following pseudo-ops apply primarily to relocatable .o65 objects.
|
The following pseudo-ops apply primarily to relocatable .o65 objects.
|
||||||
A full discussion of the relocatable format is beyond the
|
A full discussion of the relocatable format is beyond the
|
||||||
|
@ -538,6 +571,11 @@ 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".
|
||||||
|
.B .zeropage
|
||||||
|
For CA65 compatibility this is currently mapped to ".zero".
|
||||||
|
.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
|
||||||
|
@ -555,6 +593,17 @@ is used to specify the file option being referenced. A table of these options
|
||||||
is in the relocatable o65 file format description. The remainder of the options
|
is in the relocatable o65 file format description. The remainder of the options
|
||||||
are interpreted as values to insert. Any number of values may be specified,
|
are interpreted as values to insert. Any number of values may be specified,
|
||||||
and may also be strings.
|
and may also be strings.
|
||||||
|
.TP
|
||||||
|
.B .import label1, label2, label3, ...
|
||||||
|
Defines the given labels as global labels which are imported and resolved during
|
||||||
|
the link stage. Similar to the
|
||||||
|
.B -L
|
||||||
|
command line parameter
|
||||||
|
.TP
|
||||||
|
.B .importzp label1, label2, label3, ...
|
||||||
|
Similar to
|
||||||
|
.B .import
|
||||||
|
only it imports zeropage labels (i.e. byte values)
|
||||||
|
|
||||||
.SH PREPROCESSOR
|
.SH PREPROCESSOR
|
||||||
|
|
||||||
|
@ -830,7 +879,7 @@ This manual page was written by David Weinehall <tao@acc.umu.se>,
|
||||||
Andre Fachat <fachat@web.de>
|
Andre Fachat <fachat@web.de>
|
||||||
and Cameron Kaiser <ckaiser@floodgap.com>.
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
(C)1989-2009 Andre Fachat, Jolse Maginnis, David Weinehall,
|
(C)1989-2011 Andre Fachat, Jolse Maginnis, David Weinehall,
|
||||||
Cameron Kaiser. The official maintainer is Cameron Kaiser.
|
Cameron Kaiser. The official maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
.SH WEBSITE
|
.SH WEBSITE
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
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 -pedantic -ansi -g
|
||||||
#CFLAGS=-W -Wall -ansi -O2
|
#CFLAGS=-W -Wall -ansi -O2
|
||||||
|
CFLAGS=-g
|
||||||
#LD = ${CC}
|
#LD = ${CC}
|
||||||
#LDFLAGS = "-lc"
|
#LDFLAGS = "-lc"
|
||||||
|
|
||||||
|
|
120
xa/src/xa.c
120
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, *fplist;
|
||||||
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;
|
||||||
|
@ -117,9 +123,10 @@ int main(int argc,char *argv[])
|
||||||
int no_link = 0;
|
int no_link = 0;
|
||||||
|
|
||||||
char **ifiles;
|
char **ifiles;
|
||||||
char *ofile;
|
char *printfile; /* print listing to this file */
|
||||||
char *efile;
|
char *ofile; /* output file */
|
||||||
char *lfile;
|
char *efile; /* error listing goes there */
|
||||||
|
char *lfile; /* labels go here */
|
||||||
char *ifile;
|
char *ifile;
|
||||||
|
|
||||||
char old_e[MAXLINE];
|
char old_e[MAXLINE];
|
||||||
|
@ -173,6 +180,7 @@ int main(int argc,char *argv[])
|
||||||
ofile="a.o65";
|
ofile="a.o65";
|
||||||
efile=NULL;
|
efile=NULL;
|
||||||
lfile=NULL;
|
lfile=NULL;
|
||||||
|
printfile=NULL;
|
||||||
|
|
||||||
if(pp_init()) {
|
if(pp_init()) {
|
||||||
logout("fatal: pp: no memory!");
|
logout("fatal: pp: no memory!");
|
||||||
|
@ -191,6 +199,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 +221,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;
|
||||||
|
@ -276,6 +300,13 @@ int main(int argc,char *argv[])
|
||||||
reg_include(argv[i]+2);
|
reg_include(argv[i]+2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
if(argv[i][2]==0) {
|
||||||
|
printfile=argv[++i];
|
||||||
|
} else {
|
||||||
|
printfile=argv[i]+2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if(argv[i][2]==0) {
|
if(argv[i][2]==0) {
|
||||||
ofile=argv[++i];
|
ofile=argv[++i];
|
||||||
|
@ -356,6 +387,12 @@ int main(int argc,char *argv[])
|
||||||
if(setfext(old_l,".lab")==0) lfile = old_l;
|
if(setfext(old_l,".lab")==0) lfile = old_l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (printfile!=NULL && !strcmp(printfile, "-")) {
|
||||||
|
printfile=NULL;
|
||||||
|
fplist = stdout;
|
||||||
|
} else {
|
||||||
|
fplist= printfile ? xfopen(printfile,"w") : NULL;
|
||||||
|
}
|
||||||
fplab= lfile ? xfopen(lfile,"w") : NULL;
|
fplab= lfile ? xfopen(lfile,"w") : NULL;
|
||||||
fperr= efile ? xfopen(efile,"w") : NULL;
|
fperr= efile ? xfopen(efile,"w") : NULL;
|
||||||
if(!strcmp(ofile,"-")) {
|
if(!strcmp(ofile,"-")) {
|
||||||
|
@ -371,6 +408,7 @@ int main(int argc,char *argv[])
|
||||||
|
|
||||||
if(verbose) fprintf(stderr, "%s\n",copyright);
|
if(verbose) fprintf(stderr, "%s\n",copyright);
|
||||||
|
|
||||||
|
|
||||||
if(1 /*!m_init()*/)
|
if(1 /*!m_init()*/)
|
||||||
{
|
{
|
||||||
if(1 /*!b_init()*/)
|
if(1 /*!b_init()*/)
|
||||||
|
@ -384,6 +422,8 @@ int main(int argc,char *argv[])
|
||||||
if(fperr) fprintf(fperr,"%s\n",copyright);
|
if(fperr) fprintf(fperr,"%s\n",copyright);
|
||||||
if(verbose) logout(ctime(&tim1));
|
if(verbose) logout(ctime(&tim1));
|
||||||
|
|
||||||
|
list_setfile(fplist);
|
||||||
|
|
||||||
/* Pass 1 */
|
/* Pass 1 */
|
||||||
|
|
||||||
pc[SEG_ABS]= 0; /* abs addressing */
|
pc[SEG_ABS]= 0; /* abs addressing */
|
||||||
|
@ -476,9 +516,10 @@ int main(int argc,char *argv[])
|
||||||
|
|
||||||
if((!er) && relmode) seg_end(fpout); /* write reloc/label info */
|
if((!er) && relmode) seg_end(fpout); /* write reloc/label info */
|
||||||
|
|
||||||
|
if(fplist && fplist!=stdout) fclose(fplist);
|
||||||
if(fperr) fclose(fperr);
|
if(fperr) fclose(fperr);
|
||||||
if(fplab) fclose(fplab);
|
if(fplab) fclose(fplab);
|
||||||
if(fpout) fclose(fpout);
|
if(fpout && fpout!=stdout) fclose(fpout);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logout("fatal: x: no memory!\n");
|
logout("fatal: x: no memory!\n");
|
||||||
|
@ -500,7 +541,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 +661,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;
|
||||||
|
@ -646,7 +692,7 @@ static int pass2(void)
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
/* do not attempt address mode optimization on pass 2 */
|
/* do not attempt address mode optimization on pass 2 */
|
||||||
er=t_p2(afile->mn.tmp+afile->mn.tmpe,&ll,1,&al);
|
er=t_p2_l(afile->mn.tmp+afile->mn.tmpe,&ll,1,&al);
|
||||||
|
|
||||||
if(er==E_NOLINE)
|
if(er==E_NOLINE)
|
||||||
{
|
{
|
||||||
|
@ -752,7 +798,7 @@ fprintf(stderr, "offset = %i length = %i fstart = %i flen = %i charo = %c\n",
|
||||||
|
|
||||||
static int pass1(void)
|
static int pass1(void)
|
||||||
{
|
{
|
||||||
signed char o[MAXLINE];
|
signed char o[2*MAXLINE]; /* doubled for token listing */
|
||||||
int l,er,temp_er,al;
|
int l,er,temp_er,al;
|
||||||
|
|
||||||
memode=0;
|
memode=0;
|
||||||
|
@ -827,6 +873,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 +891,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 +949,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 +988,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,17 +1110,30 @@ 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) {
|
||||||
|
/* 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;
|
gl=1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
j++;
|
j++;
|
||||||
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
||||||
|
|
||||||
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 +1153,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 +1190,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;
|
||||||
|
|
|
@ -122,10 +122,12 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
||||||
/* printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
/* printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
||||||
er, segment, afl, nolink, fundef); */
|
er, segment, afl, nolink, fundef); */
|
||||||
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
||||||
if( nolink || (afl==SEG_UNDEF)) {
|
if( nolink || ((afl==SEG_UNDEF) || (afl==SEG_UNDEFZP))) {
|
||||||
er = E_OK;
|
er = E_OK;
|
||||||
*v = 0;
|
*v = 0;
|
||||||
|
if(afl!=SEG_UNDEFZP) {
|
||||||
afl = SEG_UNDEF;
|
afl = SEG_UNDEF;
|
||||||
|
}
|
||||||
*label = cval(s+pp+1);
|
*label = cval(s+pp+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +171,7 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
||||||
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
||||||
{
|
{
|
||||||
if(afl || *nafl) { /* check pointer arithmetic */
|
if(afl || *nafl) { /* check pointer arithmetic */
|
||||||
if((afl == *nafl) && (afl!=SEG_UNDEF) && o==2) {
|
if((afl == *nafl) && (afl!=SEG_UNDEFZP) && (afl!=SEG_UNDEF) && o==2) {
|
||||||
afl = 0; /* substract two pointers */
|
afl = 0; /* substract two pointers */
|
||||||
} else
|
} else
|
||||||
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
||||||
|
@ -180,6 +182,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
xa/src/xah.h
45
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;
|
||||||
|
@ -42,9 +49,11 @@ typedef struct {
|
||||||
int len;
|
int len;
|
||||||
int fl; /* 0 = label value not valid/known,
|
int fl; /* 0 = label value not valid/known,
|
||||||
* 1 = label value known
|
* 1 = label value known
|
||||||
|
* 2 = label value not known, external global label (imported on link)
|
||||||
*/
|
*/
|
||||||
int afl; /* 0 = no address (no relocation), 1 = address label */
|
int afl; /* 0 = no address (no relocation), 1 = address label */
|
||||||
int nextindex;
|
int nextindex;
|
||||||
|
int is_cll; /* 0 is normal label, 1 is cheap local label (used for listing) */
|
||||||
char *n;
|
char *n;
|
||||||
struct LabOcc *occlist;
|
struct LabOcc *occlist;
|
||||||
} Labtab;
|
} Labtab;
|
||||||
|
@ -126,18 +135,24 @@ typedef struct {
|
||||||
#define W_OVER16M -73 /* included binary over 16M in 65816 mode */
|
#define W_OVER16M -73 /* included binary over 16M in 65816 mode */
|
||||||
/* warnings 74-76 are placeholders */
|
/* warnings 74-76 are placeholders */
|
||||||
|
|
||||||
#define T_VALUE -1
|
/* Meta-values for the token list. Note must not overlap with the
|
||||||
#define T_LABEL -2
|
* K* definitions in xat.c, which have outgrown the positive numbers
|
||||||
#define T_OP -3
|
* and are now growing up from -128 ... */
|
||||||
#define T_END -4
|
#define T_VALUE -1 /* following is a 24 bit value in the token list */
|
||||||
#define T_LINE -5
|
#define T_LABEL -2 /* referring to a label, following the token is the 16bit label number */
|
||||||
#define T_FILE -6
|
#define T_OP -3 /* label oriented operation; following is the label number (16bit), plus the operation char (e.g. '+') */
|
||||||
#define T_POINTER -7
|
#define T_END -4 /* end of line marker */
|
||||||
|
#define T_LINE -5 /* new line indicator; following is the 16 bit line number */
|
||||||
|
#define T_FILE -6 /* new file indicator; following is the 16 bit line number, then the file name (zero-term) */
|
||||||
|
#define T_POINTER -7 /* ??? */
|
||||||
|
#define T_COMMENT -8 /* unused */
|
||||||
|
#define T_DEFINE -9 /* define a label; inserted at conversion and discarded in pass1, only used in listing output */
|
||||||
|
#define T_LISTING -10 /* meta token, inserted after conversion before pass1, used after pass2 to create listing */
|
||||||
|
|
||||||
#define P_START 0 /* Prioritaeten fuer Arithmetik */
|
#define P_START 0 /* arithmetic operation priorities */
|
||||||
#define P_LOR 1 /* Von zwei Operationen wird immer */
|
#define P_LOR 1 /* of any two operations, the one with */
|
||||||
#define P_LAND 2 /* die mit der hoeheren Prioritaet */
|
#define P_LAND 2 /* the higher priority will be done first */
|
||||||
#define P_OR 3 /* zuerst ausgefuehrt */
|
#define P_OR 3
|
||||||
#define P_XOR 4
|
#define P_XOR 4
|
||||||
#define P_AND 5
|
#define P_AND 5
|
||||||
#define P_EQU 6
|
#define P_EQU 6
|
||||||
|
@ -168,6 +183,8 @@ typedef struct {
|
||||||
#define SEG_ZERO 5
|
#define SEG_ZERO 5
|
||||||
#define SEG_MAX 6
|
#define SEG_MAX 6
|
||||||
|
|
||||||
|
#define SEG_UNDEFZP 7 /* is being mapped to UNDEF */
|
||||||
|
|
||||||
typedef struct Fopt {
|
typedef struct Fopt {
|
||||||
signed char *text; /* text after pass1 */
|
signed char *text; /* text after pass1 */
|
||||||
int len;
|
int len;
|
||||||
|
|
232
xa/src/xal.c
232
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,69 +146,157 @@ 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 (from the "-L" command line parameter)
|
||||||
|
*/
|
||||||
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");
|
||||||
} else {
|
} else {
|
||||||
if(!(er=ll_def(s,&n,0))) {
|
if(!(er=ll_def(s,&n,0))) {
|
||||||
ltp=afile->la.lt+n;
|
return lg_import(n);
|
||||||
ltp->fl=2;
|
|
||||||
ltp->afl=SEG_UNDEF;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return er;
|
return er;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* define a global label (from the .import pseudo opcode))
|
||||||
|
* "s" is a pointer to the first label character, end is at \0
|
||||||
|
* or at non-alphanumeric/_ char
|
||||||
|
*/
|
||||||
|
int lg_import(int n) {
|
||||||
|
int er=E_OK;
|
||||||
|
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->fl=2;
|
||||||
|
ltp->afl=SEG_UNDEF;
|
||||||
|
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* define a global zeropage label (from the .importzp pseudo opcode))
|
||||||
|
* "s" is a pointer to the first label character, end is at \0
|
||||||
|
* or at non-alphanumeric/_ char
|
||||||
|
*/
|
||||||
|
int lg_importzp(int n) {
|
||||||
|
int er=E_OK;
|
||||||
|
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->fl=2;
|
||||||
|
ltp->afl=SEG_UNDEFZP;
|
||||||
|
|
||||||
|
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,11 +308,12 @@ 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;
|
||||||
ltp->fl=0;
|
ltp->fl=0;
|
||||||
|
ltp->is_cll=cll_fl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,15 +325,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 +355,18 @@ int l_search(char *s, int *l, int *x, int *v, int *afl)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(cll_fl) {
|
||||||
|
b=cll_get();
|
||||||
|
} else {
|
||||||
b_get(&b);
|
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);
|
||||||
|
ltp->is_cll = cll_fl;
|
||||||
|
|
||||||
*l=ltp->len;
|
*l=ltp->len + cll_fl;
|
||||||
|
|
||||||
if(!er)
|
if(!er)
|
||||||
{
|
{
|
||||||
|
@ -303,6 +413,13 @@ void l_addocc(int n, int *v, int *afl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for the list functionality */
|
||||||
|
char *l_get_name(int n, int *is_cll) {
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
*is_cll = ltp->is_cll;
|
||||||
|
return ltp->n;
|
||||||
|
}
|
||||||
|
|
||||||
int l_get(int n, int *v, int *afl)
|
int l_get(int n, int *v, int *afl)
|
||||||
{
|
{
|
||||||
if(crossref) l_addocc(n,v,afl);
|
if(crossref) l_addocc(n,v,afl);
|
||||||
|
@ -387,6 +504,7 @@ static int ll_def(char *s, int *n, int b) /* definiert naechstes Label
|
||||||
ltp->blk=b;
|
ltp->blk=b;
|
||||||
ltp->fl=0;
|
ltp->fl=0;
|
||||||
ltp->afl=0;
|
ltp->afl=0;
|
||||||
|
ltp->is_cll=0;
|
||||||
ltp->occlist=NULL;
|
ltp->occlist=NULL;
|
||||||
hash=hashcode(s,j);
|
hash=hashcode(s,j);
|
||||||
ltp->nextindex=afile->la.hashindex[hash];
|
ltp->nextindex=afile->la.hashindex[hash];
|
||||||
|
@ -401,8 +519,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 +535,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 +545,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 +584,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 +629,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 +655,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 +670,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)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -542,10 +699,13 @@ int b_close(void)
|
||||||
} else {
|
} else {
|
||||||
return E_BLOCK;
|
return E_BLOCK;
|
||||||
}
|
}
|
||||||
|
cll_clear();
|
||||||
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 +713,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 +725,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 +739,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;
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
|
|
||||||
#include <stdio.h> /* for FILE */
|
#include <stdio.h> /* for FILE */
|
||||||
|
|
||||||
|
/* nasty stuff - "lz" is exported from xal.c so xa.c can print the name
|
||||||
|
* of the label that was last searched for in the error message that the
|
||||||
|
* label was not found...
|
||||||
|
*/
|
||||||
extern char *lz;
|
extern char *lz;
|
||||||
|
|
||||||
int l_init(void);
|
int l_init(void);
|
||||||
|
@ -30,6 +34,8 @@ long gm_labm(void);
|
||||||
long ga_labm(void);
|
long ga_labm(void);
|
||||||
|
|
||||||
int lg_set(char *);
|
int lg_set(char *);
|
||||||
|
int lg_import(int);
|
||||||
|
int lg_importzp(int);
|
||||||
|
|
||||||
int b_init(void);
|
int b_init(void);
|
||||||
int b_depth(void);
|
int b_depth(void);
|
||||||
|
@ -40,9 +46,10 @@ int ga_blk(void);
|
||||||
int l_def(char *s, int* l, int *x, int *f);
|
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);
|
||||||
void l_set(int n, int v, int afl);
|
void l_set(int n, int v, int afl);
|
||||||
|
char* l_get_name(int n, int *is_cll);
|
||||||
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);
|
||||||
|
|
|
@ -66,7 +66,7 @@ void o_write(FILE *fp) {
|
||||||
l=afile->fo.olist[i].len;
|
l=afile->fo.olist[i].len;
|
||||||
t=afile->fo.olist[i].text;
|
t=afile->fo.olist[i].text;
|
||||||
/* do not optimize */
|
/* do not optimize */
|
||||||
t_p2(t, &l, 1, &afl);
|
t_p2_l(t, &l, 1, &afl);
|
||||||
|
|
||||||
if(l>254) {
|
if(l>254) {
|
||||||
errout(E_OPTLEN);
|
errout(E_OPTLEN);
|
||||||
|
|
|
@ -50,7 +50,8 @@ static int pp_replace(char*,char*,int,int);
|
||||||
static int searchdef(char*);
|
static int searchdef(char*);
|
||||||
static int fgetline(char*,int len, int *rlen, FILE*);
|
static int fgetline(char*,int len, int *rlen, FILE*);
|
||||||
|
|
||||||
static int icl_open(char*),pp_ifdef(char*),pp_ifndef(char*);
|
/*static int icl_open(char*);*/
|
||||||
|
static int pp_ifdef(char*),pp_ifndef(char*);
|
||||||
static int pp_else(char*),pp_endif(char*);
|
static int pp_else(char*),pp_endif(char*);
|
||||||
static int pp_echo(char*),pp_if(char*),pp_print(char*),pp_prdef(char*);
|
static int pp_echo(char*),pp_if(char*),pp_print(char*),pp_prdef(char*);
|
||||||
static int pp_ifldef(char*),pp_iflused(char*);
|
static int pp_ifldef(char*),pp_iflused(char*);
|
||||||
|
@ -130,7 +131,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ void pp_end(void);
|
||||||
int pgetline(char *t);
|
int pgetline(char *t);
|
||||||
Datei *pp_getidat(void);
|
Datei *pp_getidat(void);
|
||||||
|
|
||||||
|
/* needed for .include pseudo opcode */
|
||||||
|
int icl_open(char*);
|
||||||
|
|
||||||
int ga_pp(void);
|
int ga_pp(void);
|
||||||
int gm_pp(void);
|
int gm_pp(void);
|
||||||
long gm_ppm(void);
|
long gm_ppm(void);
|
||||||
|
|
20
xa/src/xar.c
20
xa/src/xar.c
|
@ -34,18 +34,22 @@ File *afile = NULL;
|
||||||
|
|
||||||
int rmode = RMODE_RELOC;
|
int rmode = RMODE_RELOC;
|
||||||
|
|
||||||
|
/*
|
||||||
int r_set(int pc, int afl, int l) {
|
int r_set(int pc, int afl, int l) {
|
||||||
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d\n",pc, l, afl,segment);*/
|
|
||||||
if(segment==SEG_TEXT) return rt_set(pc,afl,l,0);
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,0);
|
||||||
if(segment==SEG_DATA) return rd_set(pc,afl,l,0);
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
int u_set(int pc, int afl, int label, int l) {
|
int u_set(int pc, int afl, int label, int l) {
|
||||||
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n",
|
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n",
|
||||||
pc, l, afl,segment, label);*/
|
pc, l, afl,segment, label);*/
|
||||||
if((afl & A_FMASK) == (SEG_UNDEF<<8))
|
if(((afl & A_FMASK) == (SEG_UNDEF<<8))
|
||||||
|
|| ((afl & A_FMASK) == (SEG_UNDEFZP<<8))
|
||||||
|
) {
|
||||||
label = u_label(label); /* set label as undefined */
|
label = u_label(label); /* set label as undefined */
|
||||||
|
}
|
||||||
if(segment==SEG_TEXT) return rt_set(pc,afl,l,label);
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,label);
|
||||||
if(segment==SEG_DATA) return rd_set(pc,afl,l,label);
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,label);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -77,7 +81,9 @@ int rt_set(int pc, int afl, int l, int lab) {
|
||||||
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
||||||
}
|
}
|
||||||
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
||||||
if((afl & A_FMASK) != (SEG_ZERO<<8)) {
|
if(((afl & A_FMASK) != (SEG_ZERO<<8))
|
||||||
|
&& ((afl & A_FMASK) != (SEG_UNDEFZP<<8))
|
||||||
|
) {
|
||||||
/*printf("afl=%04x\n",afl);*/
|
/*printf("afl=%04x\n",afl);*/
|
||||||
errout(W_ADRRELOC);
|
errout(W_ADRRELOC);
|
||||||
}
|
}
|
||||||
|
@ -147,11 +153,17 @@ int rt_write(FILE *fp, int pc) {
|
||||||
}
|
}
|
||||||
fputc(pc2-pc, fp);
|
fputc(pc2-pc, fp);
|
||||||
pc=pc2;
|
pc=pc2;
|
||||||
fputc((afl>>8)&255, fp);
|
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) {
|
||||||
|
fputc( (((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp);
|
||||||
|
fputc(afile->rt.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
||||||
|
} else {
|
||||||
|
fputc( (afl>>8)&255, fp);
|
||||||
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
||||||
fputc(afile->rt.rlist[p].lab & 255, fp);
|
fputc(afile->rt.rlist[p].lab & 255, fp);
|
||||||
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
}
|
}
|
||||||
p=afile->rt.rlist[p].next;
|
p=afile->rt.rlist[p].next;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
extern File *alloc_file(void);
|
extern File *alloc_file(void);
|
||||||
|
|
||||||
/* jumps to r[td]_set, depending on segment */
|
/* jumps to r[td]_set, depending on segment */
|
||||||
int r_set(int pc, int reloc, int len);
|
/*int r_set(int pc, int reloc, int len);*/
|
||||||
int u_set(int pc, int reloc, int label, int len);
|
int u_set(int pc, int reloc, int label, int len);
|
||||||
|
|
||||||
int rt_set(int pc, int reloc, int len, int label);
|
int rt_set(int pc, int reloc, int len, int label);
|
||||||
|
|
|
@ -111,10 +111,16 @@ int rd_write(FILE *fp, int pc) {
|
||||||
}
|
}
|
||||||
fputc(pc2-pc, fp);
|
fputc(pc2-pc, fp);
|
||||||
pc=pc2;
|
pc=pc2;
|
||||||
fputc((afl>>8)&255, fp);
|
if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) {
|
||||||
if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
fputc((((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp);
|
||||||
fputc(afile->rd.rlist[p].lab & 255, fp);
|
fputc(afile->rd.rlist[p].lab & 255, fp);
|
||||||
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
||||||
|
} else {
|
||||||
|
fputc((afl>>8)&255, fp);
|
||||||
|
if(((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8))) {
|
||||||
|
fputc(afile->rd.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
}
|
}
|
||||||
|
|
596
xa/src/xat.c
596
xa/src/xat.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "xad.h"
|
#include "xad.h"
|
||||||
#include "xah.h"
|
#include "xah.h"
|
||||||
|
@ -48,9 +49,21 @@ static void tg_dez(signed char*,int*,int*);
|
||||||
static void tg_hex(signed char*,int*,int*);
|
static void tg_hex(signed char*,int*,int*);
|
||||||
static void tg_oct(signed char*,int*,int*);
|
static void tg_oct(signed char*,int*,int*);
|
||||||
static void tg_bin(signed char*,int*,int*);
|
static void tg_bin(signed char*,int*,int*);
|
||||||
|
static int t_p2(signed char *t, int *ll, int fl, int *al);
|
||||||
|
static void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
|
||||||
|
|
||||||
/* assembly mnemonics and pseudo-op tokens */
|
/* assembly mnemonics and pseudo-op tokens */
|
||||||
/* ina and dea don't work yet */
|
/* ina and dea don't work yet */
|
||||||
|
/* Note AF 20110624: added some ca65 compatibility pseudo opcodes,
|
||||||
|
* many are still missing (and will most likely never by supported in this
|
||||||
|
* code base). Potential candidates are .hibytes, .lobytes, .asciiz,
|
||||||
|
* .addr, .charmap, .dbyt, .faraddr, .bankbytes, .segment (at least for the known ones)
|
||||||
|
* .incbin is similar to our .bin, but with parameters reversed (argh...)
|
||||||
|
* I like the .popseg/.pushseg pair;
|
||||||
|
* .global/.globalzp is equivalent to forward-defining a label in the global block
|
||||||
|
* .export/.exportzp could be implemented with a commandline switch to NOT export
|
||||||
|
* global labels, where .exported labels would still be exported in an o65 file.
|
||||||
|
*/
|
||||||
static char *kt[] ={
|
static char *kt[] ={
|
||||||
/* 1 2 3 4 5 6 7 8 9 10 */
|
/* 1 2 3 4 5 6 7 8 9 10 */
|
||||||
"adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi",
|
"adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi",
|
||||||
|
@ -75,7 +88,9 @@ 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",
|
||||||
|
".include", ".import", ".importzp", ".proc", ".endproc",
|
||||||
|
".zeropage", ".org", ".reloc"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,8 +99,6 @@ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2 };
|
||||||
/* index into token array for pseudo-ops */
|
/* index into token array for pseudo-ops */
|
||||||
/* last valid mnemonic */
|
/* last valid mnemonic */
|
||||||
#define Lastbef 93
|
#define Lastbef 93
|
||||||
/* last valid token+1 */
|
|
||||||
#define Anzkey 123
|
|
||||||
|
|
||||||
#define Kbyt Lastbef+1
|
#define Kbyt Lastbef+1
|
||||||
#define Kword Lastbef+2
|
#define Kword Lastbef+2
|
||||||
|
@ -119,8 +132,26 @@ 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 Kreloc Anzkey /* *= (relocation mode) */
|
#define Kcode Lastbef+30 /* gets remapped to Ktext */
|
||||||
#define Ksegment Anzkey+1
|
|
||||||
|
/* 93 + 30 -> 123 */
|
||||||
|
|
||||||
|
#define Kinclude Lastbef+31
|
||||||
|
#define Kimport Lastbef+32
|
||||||
|
#define Kimportzp Lastbef+33
|
||||||
|
#define Kproc Lastbef+34 /* mapped to Kopen */
|
||||||
|
/* 93 + 35 -> 128 */
|
||||||
|
#define Kendproc Lastbef+35 /* mapped to Kclose */
|
||||||
|
#define Kzeropage Lastbef+36 /* mapped to Kzero */
|
||||||
|
#define Korg Lastbef+37 /* mapped to Kpcdef - with parameter equivalent to "*=$abcd" */
|
||||||
|
#define Krelocx Lastbef+38 /* mapped to Kpcdef - without parameter equivalent to "*=" */
|
||||||
|
|
||||||
|
/* last valid token+1 */
|
||||||
|
#define Anzkey Lastbef+39 /* define last valid token number; last define above plus one */
|
||||||
|
|
||||||
|
|
||||||
|
#define Kreloc (Anzkey-256) /* *= (relocation mode) */
|
||||||
|
#define Ksegment (Anzkey+1-256) /* this actually now is above 127, which might be a problem as char is signed ... */
|
||||||
|
|
||||||
/* array used for hashing tokens (26 entries, a-z) */
|
/* array used for hashing tokens (26 entries, a-z) */
|
||||||
|
|
||||||
|
@ -319,11 +350,14 @@ static int le[] ={ 1,2,2,2,2,2,2,2,3,3,3,2,3,3,3,2,
|
||||||
static int opt[] ={ -1,-1,-1,-1,-1,-1,-1,-1,1,2,3,-1,4,5,-1,-1,
|
static int opt[] ={ -1,-1,-1,-1,-1,-1,-1,-1,1,2,3,-1,4,5,-1,-1,
|
||||||
/*new*/ -1,8,9,-1,-1,-1,-1,-1 }; /* abs -> zp */
|
/*new*/ -1,8,9,-1,-1,-1,-1,-1 }; /* abs -> zp */
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
/* pass 1 */
|
/* pass 1 */
|
||||||
int t_p1(signed char *s, signed char *t, int *ll, int *al)
|
int t_p1(signed char *s, signed char *t, int *ll, int *al)
|
||||||
{
|
{
|
||||||
static int er,l,n,v,nk,na1,na2,bl,am,sy,i,label,byte; /*,j,v2 ;*/
|
static int er,l,n,v,nk,na1,na2,bl,am,sy,i,label,byte; /*,j,v2 ;*/
|
||||||
int afl = 0;
|
int afl = 0;
|
||||||
|
int tlen; /* token listing length, to adjust length that is returned */
|
||||||
|
int inp; /* input pointer in t[] */
|
||||||
|
|
||||||
/* notes and typical conventions ... er = error code
|
/* notes and typical conventions ... er = error code
|
||||||
am = addressing mode in use
|
am = addressing mode in use
|
||||||
|
@ -338,18 +372,68 @@ int t_p1(signed char *s, signed char *t, int *ll, int *al)
|
||||||
#ifdef DEBUG_AM
|
#ifdef DEBUG_AM
|
||||||
fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
|
fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
|
||||||
#endif
|
#endif
|
||||||
er=t_conv(s,t,&l,pc[segment],&nk,&na1,&na2,0,&byte);
|
|
||||||
/* leaving our token sequence in t */
|
|
||||||
|
|
||||||
|
/* As the t_p1 code below always works through the tokens
|
||||||
|
* from t_conv in such a way that it always produces a shorter
|
||||||
|
* result, the conversion below takes place "in place".
|
||||||
|
* This, however, means that the original token sequence, which
|
||||||
|
* would be useful for some assembler listing, is overwritten.
|
||||||
|
* While the original assumption was ok for a constrained
|
||||||
|
* environment like the Atari ST, this is no longer true.
|
||||||
|
* Converting the code below to have separate input and output
|
||||||
|
* areas would be error-prone, so we do some copy-magic here
|
||||||
|
* instead...*/
|
||||||
|
/* we keep three bytes buffer for "T_LISTING" and the length of the
|
||||||
|
* token list
|
||||||
|
*/
|
||||||
|
t[0]=T_LISTING;
|
||||||
|
er=t_conv(s,t+6,&l,pc[segment],&nk,&na1,&na2,0,&byte);
|
||||||
|
tlen = l+6;
|
||||||
|
t[1]=tlen&255;
|
||||||
|
t[2]=(tlen>>8)&255;
|
||||||
|
t[3]=segment;
|
||||||
|
t[4]=pc[segment]&255;
|
||||||
|
t[5]=(pc[segment]>>8)&255;
|
||||||
|
/* now duplicate the token sequence from the T_LISTING buffer
|
||||||
|
* to the end of "t", so we can then in-place convert it
|
||||||
|
* below. Non-overlapping, size is known in advance, so
|
||||||
|
* using memcpy is fine here
|
||||||
|
*/
|
||||||
|
memcpy(t+tlen, t+6, l);
|
||||||
|
t=t+tlen;
|
||||||
|
|
||||||
|
/* the result of this is that we always have a Klisting entry in the buffer
|
||||||
|
* for each tokenization call */
|
||||||
|
/* here continue as before, except for adjusting the returne *ll length
|
||||||
|
* in the end, just before return */
|
||||||
|
|
||||||
|
inp = 0;
|
||||||
|
/* discard label definitions */
|
||||||
|
while (inp<l && t[inp]==T_DEFINE) {
|
||||||
|
inp+=3;
|
||||||
|
}
|
||||||
|
if (inp) {
|
||||||
|
/* sorry, anything else would be way to risky below */
|
||||||
|
l -= inp;
|
||||||
|
if (l != 0) {
|
||||||
|
printf("t=%p, inp=%d, l=%d\n", t, inp, l);
|
||||||
|
memmove(t, t+inp, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return length default is input length */
|
||||||
*ll=l;
|
*ll=l;
|
||||||
/*
|
|
||||||
|
#if 0
|
||||||
printf("t_conv (er=%d):",er);
|
printf("t_conv (er=%d):",er);
|
||||||
for(i=0;i<l;i++)
|
for(i=0;i<l;i++)
|
||||||
printf("%02x,",t[i]);
|
printf("%02x,",t[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
*/
|
#endif
|
||||||
|
|
||||||
/* if text/data produced, then no more fopt allowed in romable mode */
|
/* if text/data produced, then no more fopt allowed in romable mode */
|
||||||
if((romable>1) && (t[0]<Kopen || t[0]==Kbyte || t[0]==Kpcdef)) {
|
/* TODO: need to check, Kbyte is being remapped to Kbyt. What is the effect here? */
|
||||||
|
if((romable>1) && (t[inp]<Kopen || t[inp]==Kbyte || t[inp]==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;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +453,26 @@ fprintf(stderr, "- p1 %d starting -\n", pc[segment]);
|
||||||
if(n==Kend || n==Klist || n==Kxlist) {
|
if(n==Kend || n==Klist || n==Kxlist) {
|
||||||
*ll = 0; /* ignore */
|
*ll = 0; /* ignore */
|
||||||
} else
|
} else
|
||||||
|
if(n==Kinclude) {
|
||||||
|
*ll = 0; /* no output length */
|
||||||
|
i=1;
|
||||||
|
if(t[i]=='\"') {
|
||||||
|
int k,j=0;
|
||||||
|
char binfname[255];
|
||||||
|
i++;
|
||||||
|
k=t[i]+i+1;
|
||||||
|
i++;
|
||||||
|
while(i<k && !er) {
|
||||||
|
binfname[j++] = t[i++];
|
||||||
|
if (j > 255)
|
||||||
|
er = E_NOMEM; /* buffer overflow */
|
||||||
|
}
|
||||||
|
binfname[j] = '\0';
|
||||||
|
er=icl_open(binfname);
|
||||||
|
} else {
|
||||||
|
er=E_SYNTAX;
|
||||||
|
}
|
||||||
|
} else
|
||||||
if(n==Kfopt) {
|
if(n==Kfopt) {
|
||||||
if(romable==1) er=E_ROMOPT;
|
if(romable==1) er=E_ROMOPT;
|
||||||
t[0] = Kbyt;
|
t[0] = Kbyt;
|
||||||
|
@ -658,6 +761,8 @@ printf(" wrote %02x %02x %02x %02x %02x %02x\n",
|
||||||
#ifdef DEBUG_AM
|
#ifdef DEBUG_AM
|
||||||
fprintf(stderr, "E_OK ... t_p2 xat.c\n");
|
fprintf(stderr, "E_OK ... t_p2 xat.c\n");
|
||||||
#endif
|
#endif
|
||||||
|
/* this actually calls pass2 on the current tokenization stream,
|
||||||
|
* but without including the Klisting token listing */
|
||||||
er=t_p2(t,ll,(0 | byte), al);
|
er=t_p2(t,ll,(0 | byte), al);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +790,7 @@ fprintf(stderr, "E_NODEF pass1 xat.c\n");
|
||||||
|
|
||||||
if(n>=0 && n<=Lastbef)
|
if(n>=0 && n<=Lastbef)
|
||||||
{
|
{
|
||||||
if(t[1]==T_END)
|
if(t[1]==T_END || t[1]==T_COMMENT)
|
||||||
{
|
{
|
||||||
sy=0; /* implied */
|
sy=0; /* implied */
|
||||||
} else
|
} else
|
||||||
|
@ -774,6 +879,48 @@ fprintf(stderr, "E_NODEF pass1 xat.c\n");
|
||||||
/* .byt, .asc, .word, .dsb, .fopt pseudo-op dispatch */
|
/* .byt, .asc, .word, .dsb, .fopt pseudo-op dispatch */
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
if(n==Kimportzp) {
|
||||||
|
int i;
|
||||||
|
*ll=0; /* no output */
|
||||||
|
bl = 0; /* no output length */
|
||||||
|
/* import labels; next follow a comma-separated list of labels that are
|
||||||
|
imported. Tokenizer has already created label entries, we only need to
|
||||||
|
set the flags appropriately */
|
||||||
|
i=1;
|
||||||
|
/*printf("Kimport: t[i]=%d\n",t[i]);*/
|
||||||
|
while(t[i]==T_LABEL) {
|
||||||
|
int n = (t[i+1] & 255) | (t[i+2] << 8); /* label number */
|
||||||
|
/*printf("lg_import: %d\n",n);*/
|
||||||
|
lg_importzp(n);
|
||||||
|
i+=3;
|
||||||
|
while (t[i]==' ') i++;
|
||||||
|
if (t[i]!=',') break;
|
||||||
|
i++;
|
||||||
|
while (t[i]==' ') i++;
|
||||||
|
}
|
||||||
|
er=E_NOLINE;
|
||||||
|
} else
|
||||||
|
if(n==Kimport) {
|
||||||
|
int i;
|
||||||
|
*ll=0; /* no output */
|
||||||
|
bl = 0; /* no output length */
|
||||||
|
/* import labels; next follow a comma-separated list of labels that are
|
||||||
|
imported. Tokenizer has already created label entries, we only need to
|
||||||
|
set the flags appropriately */
|
||||||
|
i=1;
|
||||||
|
/*printf("Kimport: t[i]=%d\n",t[i]);*/
|
||||||
|
while(t[i]==T_LABEL) {
|
||||||
|
int n = (t[i+1] & 255) | (t[i+2] << 8); /* label number */
|
||||||
|
/*printf("lg_import: %d\n",n);*/
|
||||||
|
lg_import(n);
|
||||||
|
i+=3;
|
||||||
|
while (t[i]==' ') i++;
|
||||||
|
if (t[i]!=',') break;
|
||||||
|
i++;
|
||||||
|
while (t[i]==' ') i++;
|
||||||
|
}
|
||||||
|
er=E_NOLINE;
|
||||||
|
} else
|
||||||
if(n==Kbyt || n==Kasc || n==Kaasc)
|
if(n==Kbyt || n==Kasc || n==Kaasc)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_AM
|
#ifdef DEBUG_AM
|
||||||
|
@ -817,10 +964,75 @@ fprintf(stderr, "guessing instruction length is %d\n", bl);
|
||||||
if(segment==SEG_TEXT) pc[SEG_ABS]+=bl;
|
if(segment==SEG_TEXT) pc[SEG_ABS]+=bl;
|
||||||
if(segment==SEG_ABS) pc[SEG_TEXT]+=bl;
|
if(segment==SEG_ABS) pc[SEG_TEXT]+=bl;
|
||||||
|
|
||||||
|
/* adjust length by token listing buffer length */
|
||||||
|
*ll = *ll + tlen;
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*t_pass 2*/
|
/*********************************************************************************************/
|
||||||
|
/* t_pass 2
|
||||||
|
*
|
||||||
|
* *t is the token list as given from pass1
|
||||||
|
* *ll is the returned length of bytes (doubles as
|
||||||
|
* input for whether OK or OKDEF status from pass1)
|
||||||
|
* fl defines if we allow zeropage optimization
|
||||||
|
*
|
||||||
|
* Conversion takes place "in place" in the *t array.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function called from the main loop, where "only" the
|
||||||
|
* undefined labels have to be resolved and the affected
|
||||||
|
* opcodes are assembled, the rest is passed through from
|
||||||
|
* pass1 (pass-through is done in t_p2, when *ll<0)
|
||||||
|
*
|
||||||
|
* *t is the input token list
|
||||||
|
* *ll is the input length of the token list,
|
||||||
|
* and the output of how many bytes of the buffer are to be taken
|
||||||
|
* into the file
|
||||||
|
*/
|
||||||
|
int t_p2_l(signed char *t, int *ll, int fl, int *al)
|
||||||
|
{
|
||||||
|
int er = E_OK;
|
||||||
|
|
||||||
|
if (t[0] == T_LISTING) {
|
||||||
|
int tlen;
|
||||||
|
tlen=((t[2]&255)<<8) | (t[1]&255);
|
||||||
|
if (*ll<0) {
|
||||||
|
*ll=(*ll) + tlen;
|
||||||
|
} else {
|
||||||
|
*ll=(*ll) - tlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ll != 0) {
|
||||||
|
er = t_p2(t+tlen, ll, fl, al);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do the actual listing (*ll-2 as we need to substract the place for the tlen value */
|
||||||
|
do_listing(t+3, tlen-3, t+tlen, *ll);
|
||||||
|
|
||||||
|
/* adapt back, i.e. remove token listing */
|
||||||
|
if (*ll != 0) {
|
||||||
|
memmove(t, t+tlen, abs(*ll));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
er = t_p2(t, ll, fl, al);
|
||||||
|
}
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method does not handle a token list. Thus it
|
||||||
|
* is called internally from pass1 without the token listing, and
|
||||||
|
* from the t_p2_l() method that strips the token listing
|
||||||
|
* as well
|
||||||
|
*
|
||||||
|
* *t is the input token list
|
||||||
|
* *ll is the input length of the token list,
|
||||||
|
* and the output of how many bytes of the buffer are to be taken
|
||||||
|
* into the file
|
||||||
|
*
|
||||||
|
*/
|
||||||
int t_p2(signed char *t, int *ll, int fl, int *al)
|
int t_p2(signed char *t, int *ll, int fl, int *al)
|
||||||
{
|
{
|
||||||
static int afl,nafl, i,j,k,er,v,n,l,bl,sy,am,c,vv[3],v2,label;
|
static int afl,nafl, i,j,k,er,v,n,l,bl,sy,am,c,vv[3],v2,label;
|
||||||
|
@ -835,11 +1047,12 @@ int t_p2(signed char *t, int *ll, int fl, int *al)
|
||||||
|
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
bl=0;
|
bl=0;
|
||||||
if(*ll<0) /* <0 bei E_OK, >0 bei E_OKDEF */
|
if(*ll<0) /* <0 when E_OK, >0 when E_OKDEF */
|
||||||
{
|
{
|
||||||
*ll=-*ll;
|
*ll=-*ll;
|
||||||
bl=*ll;
|
bl=*ll;
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
n=t[0];
|
n=t[0];
|
||||||
|
@ -855,7 +1068,8 @@ int t_p2(signed char *t, int *ll, int fl, int *al)
|
||||||
v2=v;
|
v2=v;
|
||||||
} else {
|
} else {
|
||||||
if( (!(er=l_get(n,&v2, &afl)))
|
if( (!(er=l_get(n,&v2, &afl)))
|
||||||
&& ((afl & A_FMASK)!=(SEG_UNDEF<<8)) )
|
&& ((afl & A_FMASK)!=(SEG_UNDEF<<8))
|
||||||
|
&& ((afl & A_FMASK)!=(SEG_UNDEFZP<<8)) )
|
||||||
{
|
{
|
||||||
if(t[3]=='+')
|
if(t[3]=='+')
|
||||||
{
|
{
|
||||||
|
@ -1172,7 +1386,7 @@ fprintf(stderr, "Kdsb E_DSB %i\n", j);
|
||||||
}
|
}
|
||||||
dsb_len = 0;
|
dsb_len = 0;
|
||||||
} else
|
} else
|
||||||
if(n<=Lastbef)
|
if(n>=0 && n<=Lastbef)
|
||||||
{
|
{
|
||||||
if((c=t[1])=='#')
|
if((c=t[1])=='#')
|
||||||
{
|
{
|
||||||
|
@ -1505,6 +1719,7 @@ fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]);
|
||||||
} else
|
} else
|
||||||
er=E_SYNTAX;
|
er=E_SYNTAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_AM
|
#ifdef DEBUG_AM
|
||||||
fprintf(stderr, "-- endof P2\n");
|
fprintf(stderr, "-- endof P2\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -1515,6 +1730,11 @@ fprintf(stderr, "-- endof P2\n");
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
/* helper function for the preprocessor, to compute an arithmetic value
|
||||||
|
* (e.g. for #if or #print).
|
||||||
|
* First tokenizes it, then calculates the value
|
||||||
|
*/
|
||||||
int b_term(char *s, int *v, int *l, int pc)
|
int b_term(char *s, int *v, int *l, int pc)
|
||||||
{
|
{
|
||||||
static signed char t[MAXLINE];
|
static signed char t[MAXLINE];
|
||||||
|
@ -1528,15 +1748,20 @@ int b_term(char *s, int *v, int *l, int pc)
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* translate a string into a first-pass sequence of tokens */
|
/*********************************************************************************************/
|
||||||
|
/* translate a string into a first-pass sequence of tokens;
|
||||||
|
* Take the text from *s (stopping at \0 or ';'), tokenize it
|
||||||
|
* and write the result to *t, returning the length of the
|
||||||
|
* token sequence in *l
|
||||||
|
*/
|
||||||
static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
|
static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
|
||||||
int *na1, int *na2, int af, int *bytep) /* Pass1 von s nach t */
|
int *na1, int *na2, int af, int *bytep)
|
||||||
/* tr. pass1, from s to t */
|
|
||||||
{
|
{
|
||||||
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 +1811,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 +1820,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;
|
||||||
|
@ -1609,15 +1846,22 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk,
|
||||||
p++;
|
p++;
|
||||||
while(s[p]==' ') p++;
|
while(s[p]==' ') p++;
|
||||||
l_set(n,pc,segment); /* set as address value */
|
l_set(n,pc,segment); /* set as address value */
|
||||||
|
t[q++]=T_DEFINE;
|
||||||
|
t[q++]=n&255;
|
||||||
|
t[q++]=(n>>8)&255;
|
||||||
n=0;
|
n=0;
|
||||||
|
|
||||||
} else { /* label ... syntax */
|
} else { /* label ... syntax */
|
||||||
l_set(n,pc,segment); /* set as address value */
|
l_set(n,pc,segment); /* set as address value */
|
||||||
|
t[q++]=T_DEFINE;
|
||||||
|
t[q++]=n&255;
|
||||||
|
t[q++]=(n>>8)&255;
|
||||||
n=0;
|
n=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((n & 0xff) <=Lastbef)
|
if(n>=0 && n<=Lastbef)
|
||||||
mk=1; /* 1= nur 1 Komma erlaubt *//* = only 1 comma ok */
|
mk=1; /* 1= nur 1 Komma erlaubt *//* = only 1 comma ok */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1674,8 +1918,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 +1937,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) {
|
||||||
|
@ -1912,13 +2158,17 @@ fprintf(stderr, "could not find %s\n", (char *)s+p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FIXME: this is an unholy union of two "!" implementations :-( */
|
/* FIXME: this is an unholy union of two "!" implementations :-( */
|
||||||
|
/* FIXME FIXME FIXME ... */
|
||||||
|
if (operand==1) {
|
||||||
t[q++]='\0';
|
t[q++]='\0';
|
||||||
t[q++]=cast;
|
t[q++]=cast;
|
||||||
|
}
|
||||||
*l=q;
|
*l=q;
|
||||||
if(bytep) *bytep=byte;
|
if(bytep) *bytep=byte;
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
static int t_keyword(signed char *s, int *l, int *n)
|
static int t_keyword(signed char *s, int *l, int *n)
|
||||||
{
|
{
|
||||||
int i = 0, j = 0, hash;
|
int i = 0, j = 0, hash;
|
||||||
|
@ -1961,6 +2211,12 @@ 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;
|
||||||
|
if(i==Kproc) i=Kopen;
|
||||||
|
if(i==Kendproc) i=Kclose;
|
||||||
|
if(i==Kzeropage) i=Kzero;
|
||||||
|
if(i==Korg) i=Kpcdef;
|
||||||
|
if(i==Krelocx) i=Kpcdef;
|
||||||
|
|
||||||
|
|
||||||
*l=j;
|
*l=j;
|
||||||
|
@ -2095,3 +2351,291 @@ fprintf(stderr, "tg_asc token = %i\n", n);
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
/* this is the listing code
|
||||||
|
*
|
||||||
|
* Unfortunately this code has to go here (for now), as this file is the only one
|
||||||
|
* where we have access to the tables that allow to convert the tokens back to
|
||||||
|
* a listing
|
||||||
|
*/
|
||||||
|
|
||||||
|
static FILE *listfp = NULL;
|
||||||
|
|
||||||
|
static int list_string(char *buf, char *string);
|
||||||
|
static int list_tokens(char *buf, signed char *input, int len);
|
||||||
|
static int list_value(char *buf, int val);
|
||||||
|
static int list_nchar(char *buf, signed char c, int n);
|
||||||
|
static int list_char(char *buf, signed char c);
|
||||||
|
static int list_sp(char *buf);
|
||||||
|
static int list_word(char *buf, int outword);
|
||||||
|
static int list_byte(char *buf, int outbyte);
|
||||||
|
static int list_nibble(char *buf, int outnib);
|
||||||
|
|
||||||
|
void list_setfile(FILE *fp) {
|
||||||
|
listfp = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* listing/listing_len give the buffer address and length respectively that contains
|
||||||
|
* the token as they are produced by the tokenizer.
|
||||||
|
* bincode/bincode_len give the buffer address and length that contain the binary code
|
||||||
|
* that is produced from the token listing
|
||||||
|
*
|
||||||
|
* Note that both lengths may be zero
|
||||||
|
*/
|
||||||
|
void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len) {
|
||||||
|
|
||||||
|
int i, n_hexb;
|
||||||
|
|
||||||
|
char outline[MAXLINE];
|
||||||
|
char *buf = outline;
|
||||||
|
|
||||||
|
int lst_seg = listing[0];
|
||||||
|
int lst_pc = (listing[2]<<8) | (listing[1] & 255);
|
||||||
|
|
||||||
|
signed char c = '?';
|
||||||
|
|
||||||
|
/* no output file (not even stdout) */
|
||||||
|
if (listfp == NULL) return;
|
||||||
|
|
||||||
|
/*printf("do_listing: listing=%p (%d), bincode=%p (%d)\n", listing, listing_len, bincode, bincode_len);*/
|
||||||
|
|
||||||
|
if (bincode_len < 0) bincode_len = -bincode_len;
|
||||||
|
|
||||||
|
/* preamble <segment>':'<address>' ' */
|
||||||
|
switch(lst_seg) {
|
||||||
|
case SEG_ABS: c='A'; break;
|
||||||
|
case SEG_TEXT: c='T'; break;
|
||||||
|
case SEG_BSS: c='B'; break;
|
||||||
|
case SEG_DATA: c='D'; break;
|
||||||
|
case SEG_UNDEF: c='U'; break;
|
||||||
|
case SEG_ZERO: c='Z'; break;
|
||||||
|
}
|
||||||
|
buf = buf + list_char(buf, c);
|
||||||
|
buf = buf + list_char(buf, ':');
|
||||||
|
buf = buf + list_word(buf, lst_pc);
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
|
||||||
|
/* binary output (up to 8 byte. If more than 8 byte, print 7 plus "..." */
|
||||||
|
n_hexb = bincode_len;
|
||||||
|
if (n_hexb >= 8) {
|
||||||
|
n_hexb = 7;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n_hexb; i++) {
|
||||||
|
buf = buf + list_byte(buf, bincode[i]);
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
}
|
||||||
|
if ((n_hexb == 7) && (bincode_len > 7)) {
|
||||||
|
buf = buf + list_nchar(buf, '.', 3);
|
||||||
|
} else {
|
||||||
|
/* can move loop into nchar ... */
|
||||||
|
for (; i < 8; i++) {
|
||||||
|
buf = buf + list_nchar(buf, ' ', 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
|
||||||
|
buf += list_tokens(buf, listing + 3, listing_len - 3);
|
||||||
|
|
||||||
|
/* for now only do a hex dump so we see what actually happens */
|
||||||
|
i = buf - outline;
|
||||||
|
if (i<80) buf += list_nchar(buf, ' ', 80-i);
|
||||||
|
|
||||||
|
buf += list_string(buf, " >>");
|
||||||
|
for (i = 3; i < listing_len; i++) {
|
||||||
|
buf = buf + list_byte(buf, listing[i]);
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
}
|
||||||
|
buf[0] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(listfp, "%s\n", outline);
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_tokens(char *buf, signed char *input, int len) {
|
||||||
|
int outp = 0;
|
||||||
|
int inp = 0;
|
||||||
|
int tmp;
|
||||||
|
char *name;
|
||||||
|
signed char c;
|
||||||
|
int is_cll;
|
||||||
|
int tabval;
|
||||||
|
|
||||||
|
if (inp >= len) return 0;
|
||||||
|
|
||||||
|
tmp = input[inp] & 255;
|
||||||
|
|
||||||
|
tabval = 0;
|
||||||
|
if (tmp == (T_DEFINE & 255)) {
|
||||||
|
while (tmp == (T_DEFINE & 255)) {
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
name=l_get_name(tmp, &is_cll);
|
||||||
|
if (is_cll) outp += list_char(buf+outp, '@');
|
||||||
|
tmp = list_string(buf+outp, name);
|
||||||
|
tabval += tmp + 1 + is_cll;
|
||||||
|
outp += tmp;
|
||||||
|
outp += list_char(buf+outp, ' ');
|
||||||
|
inp += 3;
|
||||||
|
tmp = input[inp] & 255;
|
||||||
|
}
|
||||||
|
if (tabval < 10) {
|
||||||
|
outp += list_nchar(buf+outp, ' ', 10-tabval);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tmp >= 0 && tmp < Anzkey) {
|
||||||
|
outp += list_string(buf+outp, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp >= 0 && tmp < Anzkey) {
|
||||||
|
/* assembler keyword */
|
||||||
|
/*printf("tmp=%d, kt[tmp]=%p\n", tmp, kt[tmp]);*/
|
||||||
|
if (kt[tmp] != NULL) {
|
||||||
|
outp += list_string(buf+outp, kt[tmp]);
|
||||||
|
}
|
||||||
|
outp += list_sp(buf + outp);
|
||||||
|
inp += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (inp < len) {
|
||||||
|
switch(input[inp]) {
|
||||||
|
case T_VALUE:
|
||||||
|
/*outp += list_char(buf+outp, 'V');*/
|
||||||
|
/* 24 bit value */
|
||||||
|
tmp = ((input[inp+3]&255)<<16) | ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
outp += list_value(buf+outp, tmp);
|
||||||
|
inp += 4;
|
||||||
|
break;
|
||||||
|
case T_LABEL:
|
||||||
|
/*outp += list_char(buf+outp, 'L');*/
|
||||||
|
/* 16 bit label number */
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
name=l_get_name(tmp, &is_cll);
|
||||||
|
if (is_cll) outp += list_char(buf+outp, '@');
|
||||||
|
outp += list_string(buf+outp, name);
|
||||||
|
inp += 3;
|
||||||
|
break;
|
||||||
|
case T_OP:
|
||||||
|
/* arithmetic operation; inp[3] is operation like '=' or '+' */
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
name=l_get_name(tmp, &is_cll);
|
||||||
|
if (is_cll) outp += list_char(buf+outp, '@');
|
||||||
|
outp += list_string(buf+outp, name);
|
||||||
|
outp += list_char(buf+outp, input[inp+3]);
|
||||||
|
inp += 4;
|
||||||
|
break;
|
||||||
|
case T_END:
|
||||||
|
/* end of operation */
|
||||||
|
/*outp += list_string(buf+outp, ";");*/
|
||||||
|
inp += 1;
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case T_LINE:
|
||||||
|
/* newline marker - ignored? */
|
||||||
|
outp += list_string(buf+outp, "\\n ");
|
||||||
|
/* line number */
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
outp += list_word(buf+outp, tmp);
|
||||||
|
inp += 3;
|
||||||
|
break;
|
||||||
|
case T_FILE:
|
||||||
|
/* new file marker - ignored? */
|
||||||
|
outp += list_string(buf+outp, "\\f ");
|
||||||
|
/* line number */
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
outp += list_word(buf+outp, tmp);
|
||||||
|
/* file name */
|
||||||
|
tmp = list_string(buf+outp, (char*)input+inp+3);
|
||||||
|
outp += tmp;
|
||||||
|
inp += tmp + 3;
|
||||||
|
break;
|
||||||
|
case T_POINTER:
|
||||||
|
/* what is this? It's actually resolved during token conversion */
|
||||||
|
outp += list_byte(buf+outp, input[inp+1]);
|
||||||
|
outp += list_char(buf+outp, '#');
|
||||||
|
tmp = ((input[inp+3]&255)<<8) | (input[inp+2]&255);
|
||||||
|
outp += list_value(buf+outp, tmp);
|
||||||
|
inp += 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = input[inp];
|
||||||
|
if (c > 31) {
|
||||||
|
outp += list_char(buf+outp, input[inp]);
|
||||||
|
} else {
|
||||||
|
outp += list_char(buf+outp, '\'');
|
||||||
|
outp += list_byte(buf+outp, input[inp]);
|
||||||
|
}
|
||||||
|
inp += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
return outp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_string(char *buf, char *string) {
|
||||||
|
int p = 0;
|
||||||
|
while (string[p] != 0) {
|
||||||
|
buf[p] = string[p];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_value(char *buf, int val) {
|
||||||
|
int p = 0;
|
||||||
|
p += list_char(buf + p, '$');
|
||||||
|
if (val & (255<<16)) {
|
||||||
|
p += list_byte(buf+p, val>>16);
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else
|
||||||
|
if (val & (255<<8)) {
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else {
|
||||||
|
p += list_byte(buf+p, val);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_nchar(char *buf, signed char c, int n) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
buf[i]=c;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_char(char *buf, signed char c) {
|
||||||
|
buf[0] = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_sp(char *buf) {
|
||||||
|
buf[0] = ' ';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_word(char *buf, int outword) {
|
||||||
|
buf = buf + list_byte(buf, outword >> 8);
|
||||||
|
list_byte(buf, outword);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_byte(char *buf, int outbyte) {
|
||||||
|
buf = buf + list_nibble(buf, (outbyte >> 4));
|
||||||
|
list_nibble(buf, outbyte);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_nibble(char *buf, int outnib) {
|
||||||
|
outnib = outnib & 0xf;
|
||||||
|
if (outnib < 10) {
|
||||||
|
buf[0]='0'+outnib;
|
||||||
|
} else {
|
||||||
|
buf[0]='a'-10+outnib;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@
|
||||||
|
|
||||||
extern int dsb_len;
|
extern int dsb_len;
|
||||||
|
|
||||||
|
void list_setfile(FILE *fp);
|
||||||
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
||||||
int t_p2(signed char *t, int *ll, int fl, int *al);
|
int t_p2_l(signed char *t, int *ll, int fl, int *al);
|
||||||
int b_term(char *s, int *v, int *l, int pc);
|
int b_term(char *s, int *v, int *l, int pc);
|
||||||
|
|
||||||
#endif /* __XA65_XAT_H__ */
|
#endif /* __XA65_XAT_H__ */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user