diff --git a/xa-2.4.0+relmode.diff b/xa-2.4.0+relmode.diff new file mode 100644 index 0000000..ef10c8e --- /dev/null +++ b/xa-2.4.0+relmode.diff @@ -0,0 +1,302 @@ +diff --git a/xa/misc/file65.c b/xa/misc/file65.c +index cec2d98..f9fe753 100644 +--- a/xa/misc/file65.c ++++ b/xa/misc/file65.c +@@ -48,6 +48,8 @@ int rompar = 0; + int romoff = 0; + int labels = 0; + ++int verbose = 0; ++ + void usage(FILE *fp) + { + fprintf(fp, +@@ -62,13 +64,14 @@ void usage(FILE *fp) + " in the same ROM. Add offset to start address.\n" + " -A offset same as `-a', but only print the start address of the next\n" + " file in the ROM\n" +- " -V print undefined and global labels\n" ++ " -v print undefined and global labels\n" ++ " -vv print undefined and global labels, and relocation tables\n" + " --version output version information and exit\n" + " --help display this help and exit\n"); + } + + int main(int argc, char *argv[]) { +- int i = 1, n, mode, hlen; ++ int i, j, n, mode, hlen; + FILE *fp; + char *aligntxt[4]= {"[align 1]","[align 2]","[align 4]","[align 256]"}; + if(argc<=1) { +@@ -76,12 +79,14 @@ int main(int argc, char *argv[]) { + exit(1); + } + +- if (strstr(argv[1], "--help")) { ++ i = 1; ++ ++ if (strstr(argv[i], "--help")) { + usage(stdout); + exit(0); + } + +- if (strstr(argv[1], "--version")) { ++ if (strstr(argv[i], "--version")) { + version(programname, progversion, author, copyright); + exit(0); + } +@@ -90,11 +95,12 @@ int main(int argc, char *argv[]) { + if(argv[i][0]=='-') { + /* process options */ + switch(argv[i][1]) { +- case 'V': +- labels = 1; +- break; + case 'v': +- printf("file65: Version 0.2\n"); ++ j = 1; ++ while (argv[i][j] == 'v') { ++ verbose ++; ++ j++; ++ } + break; + case 'a': + case 'A': +@@ -142,7 +148,7 @@ int main(int argc, char *argv[]) { + printf(" zero segment @ $%04x - $%04x [$%04x bytes]\n", hdr[21]*256+hdr[20], hdr[21]*256+hdr[20]+hdr[23]*256+hdr[22], hdr[23]*256+hdr[22]); + printf(" stack size $%04x bytes %s\n", hdr[25]*256+hdr[24], + (hdr[25]*256+hdr[24])==0?"(i.e. unknown)":""); +- if(labels) { ++ if(verbose) { + read_options(fp); + print_labels(fp, hdr[11]*256+hdr[10] + hdr[15]*256+hdr[14]); + } +@@ -231,13 +237,13 @@ void print_option(unsigned char *buf, int len) { + } + + int read_options(FILE *fp) { +- int c, l=0; ++ int c, d, l=0; + unsigned char tb[256]; + + c=fgetc(fp); l++; + while(c && c!=EOF) { + c&=255; +- fread(tb, 1, c-1, fp); ++ d = fread(tb, 1, c-1, fp); + if(labels) print_option(tb, c); + l+=c; + c=fgetc(fp); +@@ -247,11 +253,17 @@ int read_options(FILE *fp) { + + int print_labels(FILE *fp, int offset) { + int i, nud, c, seg, off; ++ const char *segments[] = { "undef", "abs", "text", "data", "bss", "zero" }; ++ const char *reltype[] = { "-", "LOW", "HIGH", "-", "WORD", "SEG", "SEGADDR" }; ++ + /* + printf("print_labels:offset=%d\n",offset); + */ + fseek(fp, offset, SEEK_CUR); + ++ // ----------------------------------------------------------- ++ // print undefined labels ++ + nud = (fgetc(fp) & 0xff); + nud += ((fgetc(fp) << 8) & 0xff00); + +@@ -269,25 +281,59 @@ printf("print_labels:offset=%d\n",offset); + printf("\n"); + } + ++ // --------------------------------------------------------- ++ // skip relocation tables ++ ++ // two tables, one for text one for data + for(i=0;i<2;i++) { ++ unsigned char lowbyte; ++ unsigned short index; ++ unsigned short offset = 0; ++ ++ if (verbose > 1) { ++ printf("Relocation table for %s:\n", i ? "text":"data"); ++ } ++ + c=fgetc(fp); + while(c && c!=EOF) { + c&= 0xff; + while(c == 255 && c!= EOF) { ++ offset += 254; + c=fgetc(fp); + if(c==EOF) break; + c&= 0xff; + } + if(c==EOF) break; ++ offset += c; + + c=fgetc(fp); +- if( (c & 0xe0) == 0x40 ) fgetc(fp); +- if( (c & 0x07) == 0 ) { fgetc(fp); fgetc(fp); } +- ++ if( (c & 0xe0) == 0x40 ) { ++ lowbyte = fgetc(fp); ++ } ++ if( (c & 0x07) == 0 ) { ++ index = fgetc(fp) & 0xff; ++ index += (fgetc(fp) & 0xff) << 8; ++ } ++ if (verbose > 1) { ++ printf("\t%d:%s(%s (%d)", offset, reltype[ (c>>5) & 0xf], segments[c & 0x07], (c&0x07)); ++ if ( (c & 0xe0) == 0x40) { ++ printf(", %02x", lowbyte); ++ } ++ if ( (c & 0x07) == 0) { ++ printf(", %04x", index); ++ } ++ printf(")"); ++ } + c=fgetc(fp); + } ++ if (verbose > 1) { ++ printf("\n"); ++ } + } + ++ ++ // --------------------------------------------------------- ++ // print global labels + nud = (fgetc(fp) & 0xff); + nud += ((fgetc(fp) << 8) & 0xff00); + printf("Global Labels: %d\n", nud); +diff --git a/xa/src/xat.c b/xa/src/xat.c +index 52671ea..c44809d 100644 +--- a/xa/src/xat.c ++++ b/xa/src/xat.c +@@ -632,45 +632,45 @@ printf("reloc: er=%d, l=%d, segment=%d, pc[%d]=%04x, pc[abs(%d)]=%04x, pc[text(% + dsb_len = 0; + } else + if(n==Ktext) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = relmode ? SEG_TEXT : SEG_ABS; + t[0]=Ksegment; + t[1]=segment; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else + if(n==Kdata) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_DATA; + t[0]=Ksegment; + t[1]=SEG_DATA; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kbss) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_BSS; + t[0]=Ksegment; + t[1]=SEG_BSS; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kzero) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_ZERO; + t[0]=Ksegment; + t[1]=SEG_ZERO; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } +diff --git a/xa/tests/csapiec/testseg.ok b/xa/tests/csapiec/testseg.ok +index 254ccb1..6a377b3 100644 +Binary files a/xa/tests/csapiec/testseg.ok and b/xa/tests/csapiec/testseg.ok differ +diff --git a/xa/tests/relmode/Makefile b/xa/tests/relmode/Makefile +index 350a7a7..68d64ba 100644 +--- a/xa/tests/relmode/Makefile ++++ b/xa/tests/relmode/Makefile +@@ -4,7 +4,7 @@ + + XA=../../xa + +-tests: mixabs1 mixabs2 ++tests: mixabs1 mixabs2 mix1 mix2 clean + + + mixabs1: mixabsolute.a65 +@@ -17,6 +17,18 @@ mixabs2: mixabsolute.a65 + ../../reloc65 -bt 40960 -o $@ $@.tmp + ../hextool -cmp=b.ok < $@ + ++mix1: mix1.a65 ++ ${XA} -R -o $@.o65 $< ++ file65 -V $@.o65 ++ reloc65 -X -o $@ $@.o65 ++ ../hextool -cmp=$@.ok < $@.o65 ++ ++mix2: mix2.a65 ++ ${XA} -R -o $@.o65 $< ++ file65 -V $@.o65 ++ reloc65 -X -o $@ $@.o65 ++ ../hextool -cmp=$@.ok < $@.o65 ++ + clean: +- rm -f a.err a.o65 a.hex b.o65 mixabs2* ++ rm -f a.err *.o65 a.hex mixabs2* mix1 mix2 + +diff --git a/xa/tests/relmode/mix1.a65 b/xa/tests/relmode/mix1.a65 +new file mode 100644 +index 0000000..10b0762 +--- /dev/null ++++ b/xa/tests/relmode/mix1.a65 +@@ -0,0 +1,11 @@ ++ ++ .text ++ ++ .word $0401 ++ *=$0401 ++ *= ++ ++ .data ++NextPacketPtr: .byte 0,0 ; word ++ ++ +diff --git a/xa/tests/relmode/mix1.ok b/xa/tests/relmode/mix1.ok +new file mode 100644 +index 0000000..f86cb21 +Binary files /dev/null and b/xa/tests/relmode/mix1.ok differ +diff --git a/xa/tests/relmode/mix2.a65 b/xa/tests/relmode/mix2.a65 +new file mode 100644 +index 0000000..4cfc3e2 +--- /dev/null ++++ b/xa/tests/relmode/mix2.a65 +@@ -0,0 +1,11 @@ ++ ++ .text ++ ++ .word $0401 ++ *=$0401 ++ ++ ++ .data ++NextPacketPtr: .byte 0,0 ; word ++ ++ +diff --git a/xa/tests/relmode/mix2.ok b/xa/tests/relmode/mix2.ok +new file mode 100644 +index 0000000..f86cb21 +Binary files /dev/null and b/xa/tests/relmode/mix2.ok differ diff --git a/xa/Makefile b/xa/Makefile index 329e3b9..0ff93bb 100644 --- a/xa/Makefile +++ b/xa/Makefile @@ -6,7 +6,7 @@ LD = gcc # for testing. not to be used; build failures in misc/. #CFLAGS = -O2 -W -Wall -pedantic -ansi #CFLAGS = -O2 -g -CFLAGS = -g #-O2 +CFLAGS = -O2 LDFLAGS = -lc # for DOS? diff --git a/xa/misc/file65.c b/xa/misc/file65.c index f9fe753..7a6a4fc 100644 --- a/xa/misc/file65.c +++ b/xa/misc/file65.c @@ -263,7 +263,7 @@ printf("print_labels:offset=%d\n",offset); // ----------------------------------------------------------- // print undefined labels - + nud = (fgetc(fp) & 0xff); nud += ((fgetc(fp) << 8) & 0xff00); @@ -310,15 +310,15 @@ printf("print_labels:offset=%d\n",offset); if( (c & 0xe0) == 0x40 ) { lowbyte = fgetc(fp); } - if( (c & 0x07) == 0 ) { - index = fgetc(fp) & 0xff; - index += (fgetc(fp) & 0xff) << 8; + if( (c & 0x07) == 0 ) { + index = fgetc(fp) & 0xff; + index += (fgetc(fp) & 0xff) << 8; } if (verbose > 1) { printf("\t%d:%s(%s (%d)", offset, reltype[ (c>>5) & 0xf], segments[c & 0x07], (c&0x07)); if ( (c & 0xe0) == 0x40) { printf(", %02x", lowbyte); - } + } if ( (c & 0x07) == 0) { printf(", %04x", index); } diff --git a/xa/misc/ldo65.c b/xa/misc/ldo65.c index 8fb66ae..277c1f2 100644 --- a/xa/misc/ldo65.c +++ b/xa/misc/ldo65.c @@ -124,7 +124,6 @@ file65 file; unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 }; -int verbose = 0; void usage(FILE *fp) { @@ -140,7 +139,6 @@ void usage(FILE *fp) " -U accept any undef'd labels after linking\n" " -L accept specific given undef'd labels after linking\n" " -g only export the globals defined with (multiple) -g options\n" - " -v verbose output\n" " --version output version information and exit\n" " --help display this help and exit\n", programname); @@ -163,12 +161,12 @@ int main(int argc, char *argv[]) { char **defined = NULL; int ndefined = 0; int ndefalloc = 0; - + // globals allowed by -g - char **globdef = NULL; + char **globdef = NULL; int nglobal = 0; int ngloballoc = 0; - + if (argc <= 1) { usage(stderr); exit(1); @@ -188,13 +186,6 @@ int main(int argc, char *argv[]) { while(i%04x, file->tbase=%04x, f.tlen=%04x -> tdiff=%04x\n printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n", zbase, tzlen, (zbase + tzlen), file->zbase, file->zlen, file->zdiff); */ - - if (verbose > 0) { - printf("Relocating file: %s\n", file->fname); - printf(" text: from %04x to %04x (diff is %04x, length is %04x)\n", - file->tbase, file->tbase + file->tdiff, file->tdiff, file->tlen); - printf(" data: from %04x to %04x (diff is %04x, length is %04x)\n", - file->dbase, file->dbase + file->ddiff, file->ddiff, file->dlen); - printf(" bss: from %04x to %04x (diff is %04x, length is %04x)\n", - file->bbase, file->bbase + file->bdiff, file->bdiff, file->blen); - printf(" zero: from %02x to %02x (diff is %02x, length is %02x)\n", - file->zbase, file->zbase + file->zdiff, file->zdiff, file->zlen); - } - /* update globals (for result file) */ ttlen += file->tlen; tdlen += file->dlen; @@ -328,26 +306,26 @@ printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n { int er = 0; if (tbase + ttlen > 0x10000) { - fprintf(stderr, - "Overflow in text segment: end at %06x behind 64k limit\n", + fprintf(stderr, + "Overflow in text segment: end at %06x behind 64k limit\n", tbase + ttlen); er = 1; } if (dbase + tdlen > 0x10000) { - fprintf(stderr, - "Overflow in data segment: end at %06x behind 64k limit\n", + fprintf(stderr, + "Overflow in data segment: end at %06x behind 64k limit\n", dbase + tdlen); er = 1; } if (bbase + tblen > 0x10000) { - fprintf(stderr, - "Overflow in bss segment: end at %06x behind 64k limit\n", + fprintf(stderr, + "Overflow in bss segment: end at %06x behind 64k limit\n", bbase + tblen); er = 1; } if (zbase + tzlen > 0x100) { - fprintf(stderr, - "Overflow in zero segment: end at %04x behind 256 byte limit\n", + fprintf(stderr, + "Overflow in zero segment: end at %04x behind 256 byte limit\n", zbase + tzlen); er = 1; } @@ -699,21 +677,17 @@ int len_reloc_seg(unsigned char *buf, int ri) { unsigned char *reloc_globals(unsigned char *buf, file65 *fp) { int n, old, new, seg; - char *name; n = buf[0] + 256*buf[1]; buf +=2; while(n) { - name = buf; +/*printf("relocating %s, ", buf);*/ while(*(buf++)); - seg = *buf & 0x07; + seg = *buf; old = buf[1] + 256*buf[2]; new = old + reldiff(seg); - if (verbose > 1) { - printf("%s:%s: old=%04x, seg=%d, rel=%04x, new=%04x\n", - fp->fname, name, old, seg, reldiff(seg), new); - } +/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ buf[1] = new & 255; buf[2] = (new>>8) & 255; buf +=3; @@ -857,7 +831,7 @@ int write_nglobals(FILE *fp, char **globdef, int nglobal) { for(i=0;i>8)&255); } } diff --git a/xa/misc/ldo65.c.orig b/xa/misc/ldo65.c.orig new file mode 100644 index 0000000..9f4b70b --- /dev/null +++ b/xa/misc/ldo65.c.orig @@ -0,0 +1,1078 @@ +/* ldo65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite + * o65 relocatable object file linker + * + * A part of the xa65 - 65xx/65816 cross-assembler and utility suite + * + * Copyright (C) 1997-2023 André Fachat (fachat@web.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#include + +#include "version.h" + +#define BUF (9*2+8) /* 16 bit header */ + +#define programname "ldo65" +#define progversion "v0.2.0" +#define author "Written by Andre Fachat" +#define copyright "Copyright (C) 1997-2023 Andre Fachat. Formerly ld65." + +#undef DEBUG + +/* + +The process of linking works as follows: + +1. Every file is loaded in turn via load_file() +2. Calculate new base addresses per segment +3. Merge all globals from all files into a single table, checking for duplicates +4. Resolve undefined labels, and merge remaining into global list +5. relocate all segments, create global relocation tables +6. verify undefined labels +7. write out target file + +*/ + +typedef struct { + char *name; + int len; + int newidx; /* index in new global undef table (for reloc) */ + int resolved; /* index in current global label table after resolve (-1 is not found) */ +} undefs; + +/* file information */ +typedef struct { + char *fname; /* file name */ + size_t fsize; /* length of file */ + unsigned char *buf; /* file content */ + + int tbase; /* header: text base */ + int tlen; /* text length */ + int dbase; /* data base */ + int dlen; /* data length */ + int bbase; /* bss base */ + int blen; /* bss length */ + int zbase; /* zero base */ + int zlen; /* zero length */ + + int tdiff; /* text segment relocation diff */ + int ddiff; /* data segment relocation diff */ + int bdiff; /* bss segment relocation diff */ + int zdiff; /* zero segment relocation diff */ + + int tpos; /* position of text segment in file */ + int dpos; /* position of data segment in file */ + int upos; /* position of undef'd list in file */ + int trpos; /* position of text reloc tab in file */ + int drpos; /* position of data reloc tab in file */ + int gpos; /* position of globals list in file */ + + int nundef; /* number of undefined labels */ + undefs *ud; /* undefined labels list NULL if none */ +} file65; + +/* globally defined lables are stored in this struct */ +typedef struct { + char *name; + int len; /* length of labelname */ + int fl; /* 0=ok, 1=multiply defined */ + int val; /* address value */ + int seg; /* segment */ + file65 *file; /* in which file is it? */ +} glob; + + +file65 *load_file(char *fname); + +int read_options(unsigned char *f); +int read_undef(unsigned char *f, file65 *fp); +int write_undef(FILE *f, file65 *fp); +int check_undef(file65 *fp, char *defined[], int ndefined); +int len_reloc_seg(unsigned char *buf, int ri); +int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, unsigned char *obuf, int *lastaddrp, int *rop, file65 *fp); +unsigned char *reloc_globals(unsigned char *, file65 *fp); +int read_globals(file65 *file); +int write_options(FILE *fp, file65 *file); +int write_reloc(file65 *fp[], int nfp, FILE *f); +int write_globals(FILE *fp); +int write_nglobals(FILE *fp, char **globdef, int nglobal); +int find_global(unsigned char *name); +int resolve_undef(file65 *file, int *remains); + +file65 file; +unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; +unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 }; + + +void usage(FILE *fp) +{ + fprintf(fp, + "Usage: %s [OPTION]... [FILE]...\n" + "Linker for o65 object files\n" + "\n" + " -b? addr relocates segment `?' (i.e. `t' for text segment,\n" + " `d' for data, `b' for bss, and `z' for zeropage) to the new\n" + " address `addr'\n" + " -o file uses `file' as output file. Default is `a.o65'\n" + " -G suppress writing of globals\n" + " -U accept any undef'd labels after linking\n" + " -L accept specific given undef'd labels after linking\n" + " -g only export the globals defined with (multiple) -g options\n" + " --version output version information and exit\n" + " --help display this help and exit\n", + programname); +} + +int main(int argc, char *argv[]) { + int noglob=0; + int undefok=0; + int i = 1; + int tbase = 0x0400, dbase = 0x1000, bbase = 0x4000, zbase = 0x0002; + int ttlen, tdlen, tblen, tzlen; + char *outfile = "a.o65"; + int j, jm; + file65 *file, **fp = NULL; + FILE *fd; + int nundef = 0; // counter/index in list of remaining undef'd labels + + char *arg; + + char **defined = NULL; + int ndefined = 0; + int ndefalloc = 0; + + // globals allowed by -g + char **globdef = NULL; + int nglobal = 0; + int ngloballoc = 0; + + if (argc <= 1) { + usage(stderr); + exit(1); + } + + if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { + usage(stdout); + exit(0); + } + + if (strstr(argv[1], "--version")) { + version(programname, progversion, author, copyright); + exit(0); + } + + /* read options */ + while(i= ngloballoc) { + ngloballoc *= 2; + globdef = realloc(globdef, ngloballoc * sizeof(char*)); + } + globdef[nglobal++] = arg; + break; + case 'L': + if(argv[i][2]) arg=argv[i]+2; + else arg=argv[++i]; + if (ndefalloc == 0) { + ndefalloc = 20; + defined = malloc(ndefalloc * sizeof(char*)); + } else + if (ndefined >= ndefalloc) { + ndefalloc *= 2; + defined = realloc(defined, ndefalloc * sizeof(char*)); + } + defined[ndefined++] = arg; + break; + case 'b': + switch(argv[i][2]) { + case 't': + if(argv[i][3]) tbase = atoi(argv[i]+3); + else tbase = atoi(argv[++i]); + break; + case 'd': + if(argv[i][3]) dbase = atoi(argv[i]+3); + else dbase = atoi(argv[++i]); + break; + case 'b': + if(argv[i][3]) bbase = atoi(argv[i]+3); + else bbase = atoi(argv[++i]); + break; + case 'z': + if(argv[i][3]) zbase = atoi(argv[i]+3); + else zbase = atoi(argv[++i]); + break; + default: + printf("Unknown segment type '%c' - ignored!\n", argv[i][2]); + break; + } + break; + default: + fprintf(stderr,"file65: %s unknown option, use '-?' for help\n",argv[i]); + break; + } + i++; + } + + // ------------------------------------------------------------------------- + // step 1 - load files + + /* each file is loaded first */ + j=0; jm=0; fp=NULL; + while(i=jm) fp=realloc(fp, (jm=(jm?jm*2:10))*sizeof(file65*)); + if(!fp) { fprintf(stderr,"Oops, no more memory\n"); exit(1); } + fp[j++] = f; + } else { + exit(1); + } + i++; + } + + // ------------------------------------------------------------------------- + // step 2 - calculate new segment base addresses per file, by + // concatenating the segments per type + + /* now [tdbz]base holds new segment base address */ + /* set total length to zero */ + ttlen = tdlen = tblen = tzlen = 0; + + /* find new addresses for the files and read globals */ + for(i=0;itdiff = ((tbase + ttlen) - file->tbase); + file->ddiff = ((dbase + tdlen) - file->dbase); + file->bdiff = ((bbase + tblen) - file->bbase); + file->zdiff = ((zbase + tzlen) - file->zbase); +/*printf("tbase=%04x, file->tbase=%04x, ttlen=%04x -> tdiff=%04x\n", + tbase, file->tbase, ttlen, file->tdiff);*/ + + /* update globals (for result file) */ + ttlen += file->tlen; + tdlen += file->dlen; + tblen += file->blen; + tzlen += file->zlen; + } + + // ------------------------------------------------------------------------- + // step 3 - merge globals from all files into single table + // + + for(i=0;idrpos - file->trpos); + routdlen += (file->gpos - file->drpos); + + reloc_globals(file->buf+file->gpos, file); + } + + // prep global reloc tables + unsigned char *treloc = malloc(routtlen); + unsigned char *dreloc = malloc(routdlen); + +#ifdef DEBUG + printf("prep'd text reloc table at %p (%d bytes)\n", treloc, routtlen); + printf("prep'd data reloc table at %p (%d bytes)\n", dreloc, routdlen); +#endif + int tro = 0; + int dro = 0; + + // segment position of last relocation entry to compute offsets across files + int lasttaddr = tbase - 1; + int lastdaddr = dbase - 1; + + for(i=0;ibuf, // input buffer + file->tpos, // position of segment in input buffer + file->tbase, // segment base address + file->tdiff, // reloc difference + file->trpos, // position of reloc table in input + treloc, // output reloc buffer + &lasttaddr, // last relocated target address + &tro, // pointer in output reloc bufer + file); + + reloc_seg(file->buf, + file->dpos, + file->dbase, + file->ddiff, + file->drpos, + dreloc, + &lastdaddr, + &dro, + file); + + // change file information to relocated values + file->tbase += file->tdiff; + file->dbase += file->ddiff; + file->bbase += file->bdiff; + file->zbase += file->zdiff; + } + + // finalize global reloc table + treloc[tro++] = 0; + dreloc[dro++] = 0; + + // ------------------------------------------------------------------------- + // step 6 - validate undefined labels + // + + if (nundef > 0 && !undefok) { + int er = 0; + // we have undefined labels, but it's not ok (no -U) + // check -L defined labels + for(i=0;i>8) & 255; + hdr[10] = ttlen & 255; hdr[11] = (ttlen >>8)& 255; + hdr[12] = dbase & 255; hdr[13] = (dbase>>8) & 255; + hdr[14] = tdlen & 255; hdr[15] = (tdlen >>8)& 255; + hdr[16] = bbase & 255; hdr[17] = (bbase>>8) & 255; + hdr[18] = tblen & 255; hdr[19] = (tblen >>8)& 255; + hdr[20] = zbase & 255; hdr[21] = (zbase>>8) & 255; + hdr[22] = tzlen & 255; hdr[23] = (tzlen >>8)& 255; + hdr[24] = 0; hdr[25] = 0; + + // open file + fd = fopen(outfile, "wb"); + if(!fd) { + fprintf(stderr,"Couldn't open output file %s (%s)\n", + outfile, strerror(errno)); + exit(2); + } + + // write header + fwrite(hdr, 1, 26, fd); + + // write options - this writes _all_ options from _all_files! + for(i=0;ibuf + fp[i]->tpos, 1, fp[i]->tlen, fd); + } + + // write data segment + for(i=0;ibuf + fp[i]->dpos, 1, fp[i]->dlen, fd); + } + + // write list of undefined labels + fputc(nundef & 0xff,fd); + fputc((nundef >> 8) & 0xff,fd); + if (nundef > 0) { + for(i=0;i 0) { + write_nglobals(fd, globdef, nglobal); + } else { + fputc(0,fd); + fputc(0,fd); + } + } + + fclose(fd); + return 0; +} + +/***************************************************************************/ + +int write_options(FILE *fp, file65 *file) { + return fwrite(file->buf+BUF, 1, file->tpos-BUF-1, fp); +} + +int read_options(unsigned char *buf) { + int c, l=0; + + c=buf[0]; + while(c && c!=EOF) { + c&=255; + l+=c; + c=buf[l]; + } + return ++l; +} + +/***************************************************************************/ + +int read_undef(unsigned char *buf, file65 *file) { + int bufp; // pointer in input buffer + int startp; // pointer to start of label name + int nlabels; // number of labels in file + undefs *current = NULL; + int i; + + bufp = 0; + nlabels = buf[bufp] + 256*buf[bufp+1]; + bufp += 2; + + file->nundef = nlabels; + + if (nlabels == 0) { + file->ud = NULL; + } else { + file->ud = malloc(nlabels*sizeof(undefs)); + if(!file->ud) { + fprintf(stderr,"Oops, no more memory\n"); + exit(1); + } + i=0; + while(iud[i]; + current->name = (char*) buf+startp; + current->len = bufp-startp-1; + current->resolved = -1; +/*printf("read undef '%s'(%p), len=%d, ll=%d, l=%d, buf[l]=%d\n", + file->ud[i].name, file->ud[i].name, file->ud[i].len,ll,l,buf[l]);*/ + i++; + } + } + return bufp; +} + +int resolve_undef(file65 *file, int *remains) { + int i; + int nlabels = file->nundef; +#ifdef DEBUG +printf("resolved undef file %s (%d undef'd)\n", file->fname, nlabels); +#endif + if (nlabels == 0) { + return 0; + } + undefs *current = file->ud; + + for (i = 0; i < nlabels; i++) { + // store pointer to global in label info + // if NULL is returned, is not resolved + current->resolved = find_global(current->name); +#ifdef DEBUG +printf("resolved undef label %s to: resolved=%d, newidx=%d\n", current->name, current->resolved, *remains); +#endif + if (current->resolved == -1) { + // keep in global undef list + current->newidx = *remains; + *remains += 1; + } + current++; + } + return 0; +} + + +int write_undef(FILE *f, file65 *fp) { + int i; + for (i = 0; i < fp->nundef; i++) { + undefs *current = &fp->ud[i]; + + if (current->resolved == -1) { + // only write unresolved entries + fprintf(f, "%s%c", current->name, 0); + } + } + return 0; +} + +int check_undef(file65 *fp, char *defined[], int ndefined) { + + int er = 0; + int i, j; + for (i = 0; i < fp->nundef; i++) { + undefs *current = &fp->ud[i]; + + if (current->resolved == -1) { + // only check unresolved entries + int found = 0; + for (j = 0; j < ndefined; j++) { + if (defined && !strcmp(defined[j], current->name)) { + // label is found, so it's ok + found = 1; + break; + } + } + if (!found) { + fprintf(stderr, "Unresolved label '%s' from file '%s'\n", + current->name, fp->fname); + er = -1; + } + } + } + return er; +} + + +/***************************************************************************/ + +/* compute and return the length of the relocation table */ +int len_reloc_seg(unsigned char *buf, int ri) { + int type, seg; + + while(buf[ri]) { + if((buf[ri] & 255) == 255) { + ri++; + } else { + ri++; + type = buf[ri] & 0xe0; + seg = buf[ri] & 0x07; +/*printf("reloc entry @ rtab=%p (offset=%d), adr=%04x, type=%02x, seg=%d\n",buf+ri-1, *(buf+ri-1), adr, type, seg);*/ + ri++; + switch(type) { + case 0x80: + break; + case 0x40: + ri++; + break; + case 0x20: + break; + } + if(seg==0) ri+=2; + } + } + return ++ri; +} + +#define reldiff(s) (((s)==2)?fp->tdiff:(((s)==3)?fp->ddiff:(((s)==4)?fp->bdiff:(((s)==5)?fp->zdiff:0)))) + +unsigned char *reloc_globals(unsigned char *buf, file65 *fp) { + int n, old, new, seg; + + n = buf[0] + 256*buf[1]; + buf +=2; + + while(n) { +/*printf("relocating %s, ", buf);*/ + while(*(buf++)); + seg = *buf; + old = buf[1] + 256*buf[2]; + new = old + reldiff(seg); +/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ + buf[1] = new & 255; + buf[2] = (new>>8) & 255; + buf +=3; + n--; + } + return buf; +} + +/***************************************************************************/ + +file65 *load_file(char *fname) { + file65 *file; + struct stat fs; + FILE *fp; + int mode, hlen; + size_t n; + + file=malloc(sizeof(file65)); + if(!file) { + fprintf(stderr,"Oops, not enough memory!\n"); + exit(1); + } + +/*printf("load_file(%s)\n",fname);*/ + + file->fname=fname; + stat(fname, &fs); + file->fsize=fs.st_size; + file->buf=malloc(file->fsize); + if(!file->buf) { + fprintf(stderr,"Oops, no more memory!\n"); + exit(1); + } + + fp = fopen(fname,"rb"); + if(fp) { + n = fread(file->buf, 1, file->fsize, fp); + fclose(fp); + if((n>=file->fsize) && (!memcmp(file->buf, cmp, 5))) { + mode=file->buf[7]*256+file->buf[6]; + if(mode & 0x2000) { + fprintf(stderr,"file65: %s: 32 bit size not supported\n", fname); + free(file->buf); free(file); file=NULL; + } else + if(mode & 0x4000) { + fprintf(stderr,"file65: %s: pagewise relocation not supported\n", + fname); + free(file->buf); free(file); file=NULL; + } else { + hlen = BUF+read_options(file->buf+BUF); + + file->tbase = file->buf[ 9]*256+file->buf[ 8]; + file->tlen = file->buf[11]*256+file->buf[10]; + file->dbase = file->buf[13]*256+file->buf[12]; + file->dlen = file->buf[15]*256+file->buf[14]; + file->bbase = file->buf[17]*256+file->buf[16]; + file->blen = file->buf[19]*256+file->buf[18]; + file->zbase = file->buf[21]*256+file->buf[20]; + file->zlen = file->buf[23]*256+file->buf[22]; + + file->tpos = hlen; + file->dpos = hlen + file->tlen; + file->upos = file->dpos + file->dlen; + file->trpos= file->upos + read_undef(file->buf+file->upos, file); + file->drpos= len_reloc_seg(file->buf, file->trpos); + file->gpos = len_reloc_seg(file->buf, file->drpos); + } + } else { + fprintf(stderr,"Error: %s: not an o65 file\n", fname); + return NULL; + } + } else { + fprintf(stderr,"file65: %s: %s\n", fname, strerror(errno)); + return NULL; + } + return file; +} + +/***************************************************************************/ + +// global list of all global labels +glob *gp = NULL; +// number of global labels +int g=0; +// number of globals for which memory is already allocated +int gm=0; + + +int write_globals(FILE *fp) { + int i; + + fputc(g&255, fp); + fputc((g>>8)&255, fp); + + for(i=0;i>8)&255); + } + return 0; +} + +int write_nglobals(FILE *fp, char **globdef, int nglobal) { + int i, j; + int newnum = 0; + + // first check which defined globals are allowed to be exported + // and clear out the other ones + for (i = 0; i < g; i++) { + for (j = 0; j < nglobal; j++) { + if (!strcmp(gp[i].name, globdef[j])) { + // found + break; + } + } + if (j >= nglobal) { + // not found + gp[i].name = NULL; + } else { + // found, so we inc the counter + newnum++; + } + } + + // then check which globals from the -g list are actually used, and warn about unused ones + for (j = 0; j < nglobal; j++) { + for (i = 0; i < g; i++) { + if (gp[i].name != NULL && !strcmp(gp[i].name, globdef[j])) { + // found + break; + } + } + if (i >= g) { + // not found + fprintf(stderr,"Warning: command line allowed global '%s' is not defined!\n", globdef[j]); + } + } + + // write out only defined globals + fputc(newnum&255, fp); + fputc((newnum>>8)&255, fp); + + for(i=0;i>8)&255); + } + } + return 0; +} + +int read_globals(file65 *fp) { + int i, l, n, old, new, seg, ll; + char *name; + unsigned char *buf = fp->buf + fp->gpos; + + n = buf[0] + 256*buf[1]; + buf +=2; + + while(n) { +/*printf("reading %s, ", buf);*/ + name = (char*) buf; + l=0; + while(buf[l++]); + buf+=l; + ll=l-1; + seg = *buf; + old = buf[1] + 256*buf[2]; + new = old + reldiff(seg); +/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ + + /* multiply defined? */ + for(i=0;ifname, gp[i].file->fname); + gp[i].fl = 1; + break; + } + } + /* not already defined */ + if(i>=g) { + if(g>=gm) { + gp = realloc(gp, (gm=(gm?2*gm:40))*sizeof(glob)); + if(!gp) { + fprintf(stderr,"Oops, no more memory\n"); + exit(1); + } + } + if(g>=0x10000) { + fprintf(stderr,"Outch, maximum number of labels (65536) exceeded!\n"); + exit(3); + } + gp[g].name = name; + gp[g].len = ll; + gp[g].seg = seg; + gp[g].val = new; + gp[g].fl = 0; + gp[g].file = fp; +#ifdef DEBUG +printf("set global label '%s' (l=%d, seg=%d, val=%04x)\n", gp[g].name, + gp[g].len, gp[g].seg, gp[g].val); +#endif + g++; + } + + buf +=3; + n--; + } + return 0; +} + +int find_global(unsigned char *name) { + int i; + for (i = 0; i < g; i++) { + + if (!strcmp(gp[i].name, name)) { + // found + return i; + } + } + return -1; +} + +// searches for a global label in a file by name. +// returns the value of a found global value +int find_file_global(unsigned char *bp, file65 *fp, int *seg) { + int i,l; + char *n; + int nl = bp[0]+256*bp[1]; + + l=fp->ud[nl].len; + n=fp->ud[nl].name; +/*printf("find_global(%s (len=%d))\n",n,l);*/ + + for(i=0;i>8) & 255; +/*printf("return gp[%d]=%s (len=%d), val=%04x\n",i,gp[i].name,gp[i].len,gp[i].val);*/ + return gp[i].val; + } + } + fprintf(stderr,"Warning: undefined label '%s' in file %s\n", + n, fp->fname); + return 0; +} + +/***************************************************************************/ + +#define forwardpos() \ + while(addr-lastaddr>254){obuf[ro++]=255;lastaddr+=254;}obuf[ro++]=addr-lastaddr;lastaddr=addr + +int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, + unsigned char *obuf, int *lastaddrp, int *rop, file65 *fp) { + int type, seg, old, new, ro, lastaddr, diff; + int base; + + /* + pos = address of current position + ri = position of relocation table in *buf for reading the reloc entries + ro(p) = position of relocation table entry for writing the modified entries + */ + base = addr; + addr--; + ro = *rop; + lastaddr = *lastaddrp - rdiff; + +#ifdef DEBUG +printf("reloc_seg: %s: addr=%04x, pos=%04x, lastaddr=%04x (%04x - %04x)\n", + fp->fname, addr, pos, lastaddr, *lastaddrp, rdiff); +#endif + + while(buf[ri]) { + // still reloc entry + if((buf[ri] & 255) == 255) { + addr += 254; + ri++; + } else { + addr += buf[ri] & 255; + type = buf[ri+1] & 0xe0; + seg = buf[ri+1] & 0x07; +#ifdef DEBUG +printf("reloc entry @ ri=%04x, pos=%04x, type=%02x, seg=%d, offset=%d, reldiff=%04x\n", + ri, pos, type, seg, addr-lastaddr, reldiff(seg)); +#endif + switch(type) { + case 0x80: + // address (word) relocation + old = buf[addr-base+pos] + 256*buf[addr-base+pos+1]; + if(seg) { + diff = reldiff(seg); + ri++; // skip position byte + forwardpos(); // re-write position offset + obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) + } else { + // undefined + undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; +#ifdef DEBUG +printf("found undef'd label %s, resolved=%d, newidx=%d, (ri=%d, ro=%d)\n", u->name, u->resolved, u->newidx, ri, ro); +#endif + if (u->resolved == -1) { + // not resolved + diff = 0; + ri++; // skip position byte + forwardpos(); // re-write position offset + obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) + obuf[ro++] = u->newidx & 0xff; // output label number lo/hi + obuf[ro++] = (u->newidx >> 8) & 0xff; + ri += 2; // acount for label number in input + } else { + // resolved from global list + glob *gl = &gp[u->resolved]; + diff = gl->val; + seg = gl->seg; + if (seg != 1) { + // not an absolute value + forwardpos(); // re-write position offset + obuf[ro++] = 0x80 | seg;// relocation byte for new segment + } else { + // absolute value - do not write a new relocation entry + } + ri += 4; // account for position, segment byte, label number in reloc table + } + } + new = old + diff; +/*printf("old=%04x, new=%04x\n",old,new);*/ + buf[addr-base+pos] = new & 255; + buf[addr-base+pos+1] = (new>>8)&255; + break; + case 0x40: + // high byte relocation + if(seg) { + old = buf[addr-base+pos]*256 + buf[ri+2]; + diff = reldiff(seg); + forwardpos(); // re-write position offset + obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) + obuf[ro++] = (old + diff) & 255; + ri += 3; // skip position, segment, and low byte + } else { + old = buf[addr-base+pos]*256 + buf[ri+4]; + // undefined + undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; + if (u->resolved == -1) { + // not resolved + diff = 0; + forwardpos(); // re-write position offset + obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) + obuf[ro++] = u->newidx & 0xff; // output label number lo/hi + obuf[ro++] = (u->newidx >> 8) & 0xff; + obuf[ro++] = buf[ri+4]; // low byte for relocation + } else { + // resolved from global list + glob *gl = &gp[u->resolved]; + diff = gl->val; + seg = gl->seg; + if (seg != 1) { + // not an absolute value + forwardpos(); // re-write position offset + obuf[ro++] = 0x40 | seg; // relocation byte for new segment + obuf[ro++] = (old + diff) & 0xff; // low byte for relocation + } else { + // absolute value - do not write a new relocation entry + } + } + ri += 5; // account for position, segment byte, label number in reloc table, low byte + } + new = old + diff; + buf[addr-base+pos] = (new>>8)&255; + break; + case 0x20: + // low byte relocation + old = buf[addr-base+pos]; + diff = 0; + if(seg) { + diff = reldiff(seg); + forwardpos(); + obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) + ri += 2; // account for position & segment + } else { + // undefined + undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; + if (u->resolved == -1) { + // not resolved + diff = 0; + forwardpos(); // re-write position offset + obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) + obuf[ro++] = u->newidx & 0xff; // output label number lo/hi + obuf[ro++] = (u->newidx >> 8) & 0xff; + } else { + // resolved from global list + glob *gl = &gp[u->resolved]; + diff = gl->val; + seg = gl->seg; + if (seg != 1) { + // not an absolute value + forwardpos(); // re-write position offset + obuf[ro++] = 0x20 | seg; // relocation byte for new segment + } else { + // absolute value - do not write a new relocation entry + } + } + ri += 4;// account for position, segment byte, label number in reloc table + } + new = old + diff; + if (((diff & 0xff) + (old & 0xff)) > 0xff) { + fprintf(stderr,"Warning: overflow in byte relocation at %04x in file %s\n", + pos, fp->fname); + } + buf[addr-base+pos] = new & 255; + break; + } + } + } + + *lastaddrp = lastaddr + rdiff; + *rop = ro; +#ifdef DEBUG + printf(" --> lastaddr=%04x (%04x - %04x), rop=%d\n", lastaddr, *lastaddrp, rdiff, ro); +#endif + return ++ri; +} + + + diff --git a/xa/src/xa.c b/xa/src/xa.c index aeea907..4bc4d4f 100644 --- a/xa/src/xa.c +++ b/xa/src/xa.c @@ -931,7 +931,7 @@ static void usage(int default816, FILE *fp) " -M allow ``:'' to appear in comments for MASM compatibility\n" " (deprecated: prefer -XMASM)\n" " -Xcompatset set compatibility flags for other assemblers, known values are:\n" - " MASM, CA65, XA23 (deprecated: for better 2.3 compatibility)\n" + " C, MASM, CA65, XA23 (deprecated: for better 2.3 compatibility)\n" " -R start assembler in relocating mode\n" " -U allow all undefined labels in relocating mode\n"); fprintf(fp, @@ -992,7 +992,7 @@ static char *ertxt[] = { "Illegal quantity", // E_ILLQUANT =-35 ".bin", // E_BIN =-36 "#error directive", // E_UERROR =-37 - "Assertion", // E_AERROR =-38 + "Assertion", // E_AERROR =-38 "DSB has negative length", // E_NEGDSBLEN =-39 /* placeholders for future fatal errors */ "", // -40 diff --git a/xa/src/xaa.c b/xa/src/xaa.c index db8cc3c..85577f9 100644 --- a/xa/src/xaa.c +++ b/xa/src/xaa.c @@ -213,7 +213,7 @@ printf("pointer: v=%04x, afl=%04x\n",*v,afl); /* subtract pointer from constant */ errout(W_SUBTRACT); } - /* allow math in the same segment */ + /* allow math in the same segment */ if(segment!=SEG_ABS && segment != afl) { if(!dsb_len) { /*printf("ILLPOINTER=dsb_len=%d,segment=%d\n",dsb_len, segment);*/ diff --git a/xa/src/xah.h b/xa/src/xah.h index 8a0b5bb..a126ed2 100644 --- a/xa/src/xah.h +++ b/xa/src/xah.h @@ -141,7 +141,6 @@ typedef struct { #define E_UERROR -37 /* #error */ #define E_AERROR -38 /* .assert failed */ #define E_NEGDSBLEN -39 /* .dsb has negative length */ - /* errors thru 64 are placeholders available for use */ #define W_ADRRELOC -65 /* word relocation in byte value */ diff --git a/xa/src/xal.c b/xa/src/xal.c index b5612f7..f24f8fb 100644 --- a/xa/src/xal.c +++ b/xa/src/xal.c @@ -707,9 +707,6 @@ int ll_pdef(char *t) return(E_NODEF); } -/* - * Write out the list of global labels in an o65 file - */ int l_write(FILE *fp) { int i, afl, n=0; @@ -719,39 +716,25 @@ int l_write(FILE *fp) fputc(0, fp); return 0; } - // calculate number of global labels for (i=0;ila.lti;i++) { ltp=afile->la.lt+i; if((!ltp->blk) && (ltp->fl==1)) { n++; } } - // write number of globals to file fputc(n&255, fp); fputc((n>>8)&255, fp); - // iterate over labels and write out label for (i=0;ila.lti;i++) { ltp=afile->la.lt+i; if((!ltp->blk) && (ltp->fl==1)) { - // write global name fprintf(fp, "%s",ltp->n); fputc(0,fp); - - // segment byte afl = ltp->afl; - // hack to switch undef and abs flag from internal to file format - // if asolute of undefined (< SEG_TEXT, i.e. 0 or 1) - // then invert bit 0 (0 = absolute) - if( (afl & (A_FMASK>>8)) < SEG_TEXT) { - afl^=1; - } - // remove residue flags, only write out real segment number - // according to o65 file format definition - afl = afl & (A_FMASK >> 8); + /* hack to switch undef and abs flag from internal to file format */ +/*printf("label %s, afl=%04x, A_FMASK>>8=%04x\n", ltp->n, afl, A_FMASK>>8);*/ + if( (afl & (A_FMASK>>8)) < SEG_TEXT) afl^=1; fputc(afl,fp); - - // value fputc(ltp->val&255, fp); fputc((ltp->val>>8)&255, fp); } diff --git a/xa/src/xalisting.c b/xa/src/xalisting.c index f63ca91..8423884 100644 --- a/xa/src/xalisting.c +++ b/xa/src/xalisting.c @@ -132,6 +132,11 @@ static char *html_escape(char *toescape) { strcpy(q, "&"); q+=5; p++; + } else + if (*p == '>') { + strcpy(q, ">"); + q+=4; + p++; } else { *q = *p; q++; diff --git a/xa/src/xat.c.orig b/xa/src/xat.c.orig new file mode 100644 index 0000000..52671ea --- /dev/null +++ b/xa/src/xat.c.orig @@ -0,0 +1,2831 @@ +/* xa65 - 65xx/65816 cross-assembler and utility suite + * + * Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de) + * maintained by Cameron Kaiser + * + * Core tokenizing module/pass 1 and pass 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* enable this to turn on (copious) optimization output */ + +#undef LISTING_DEBUG +#undef DEBUG_CONV +#undef DEBUG_CAST +#undef DEBUG_RELOC +#undef DEBUG_AM + +#include +#include +#include + +#include "xad.h" +#include "xah.h" +#include "xah2.h" + +#include "xar.h" +#include "xa.h" +#include "xaa.h" +#include "xal.h" +#include "xat.h" +#include "xao.h" +#include "xap.h" +#include "xacharset.h" +#include "xalisting.h" + +int dsb_len = 0; + +static int t_conv(signed char*,signed char*,int*,int,int*,int*,int*,int,int*); +static int t_keyword(signed char*,int*,int*); +static int tg_asc(signed char*,signed char*,int*,int*,int*,int*,int); +static void tg_dez(signed char*,int*,int*); +static void tg_hex(signed char*,int*,int*); +static void tg_oct(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); + +void list_setbytes(int number_of_bytes_per_line); + +/* assembly mnemonics and pseudo-op tokens */ +/* 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. + */ +char *kt[] ={ +/* 1 2 3 4 5 6 7 8 9 10 */ + "adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi", + "bne","bpl","bra","brk","bvc","bvs","brl","clc","cld","cli", +/* + "clv","cmp","cpx","cpy","cop","dea","dec","dex","dey","eor", +*/ + "clv","cmp","cpx","cpy","cop",/*"dea",*/"dec","dex","dey","eor", + +/* + "ina","inc","inx","iny","jmp","jsr","lda","ldx","ldy","lsr", +*/ + /*"ina",*/"inc","inx","iny","jmp","jsr","lda","ldx","ldy","lsr", + "mvp","mvn","nop","ora","pha","php","phx","phy","pla","plp", + "plx","ply","phb","phd","phk","plb","pld","pea","pei","per", + + "rmb","rol","ror","rti","rts","rep","rtl","sbc","sec","sed", + "sei","smb","sta","stx","sty","stz","sep","stp","tax","tay", + "trb","tsb","tsx","txa","txs","tya","txy","tyx","tcd","tdc", + + "tcs","tsc","wai","wdb","xba","xce", + + ".byt",".word",".asc",".dsb", ".(", ".)", "*=", ".text",".data",".bss", + ".zero",".fopt", ".byte", ".end", ".list", ".xlist", ".dupb", ".blkb", ".db", ".dw", + ".align",".block", ".bend",".al",".as",".xl",".xs", ".bin", ".aasc", ".code", + ".include", ".import", ".importzp", ".proc", ".endproc", + ".zeropage", ".org", ".reloc", ".listbytes", + ".scope", ".endscope", ".assert" + +}; + +/* arithmetic operators (purely for listing, parsing is done programmatically */ +char *arith_ops[] = { + "", "+", "-", + "*", "/", + ">>", "<<", + "<", ">", "=" + "<=", ">=", "<>", + "&", "^", "|", + "&&", "||", "==", "!=", "!" +}; + +/* length of arithmetic operators indexed by operator number */ +static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2,2,2,1 }; + +/* mvn and mvp are handled specially, they have a weird syntax */ +#define Kmvp 38 +#define Kmvn Kmvp+1 + +/* index into token array for pseudo-ops */ +/* last valid mnemonic */ +#define Lastbef 93 + +#define Kbyt Lastbef+1 +#define Kword Lastbef+2 +#define Kasc Lastbef+3 +#define Kdsb Lastbef+4 +#define Kopen Lastbef+5 /* .( */ +#define Kclose Lastbef+6 /* .) */ +#define Kpcdef Lastbef+7 /* *=value */ +#define Ktext Lastbef+8 +#define Kdata Lastbef+9 +#define Kbss Lastbef+10 +#define Kzero Lastbef+11 +#define Kfopt Lastbef+12 +#define Kbyte Lastbef+13 /* gets remapped to Kbyt */ +#define Kend Lastbef+14 /* ignored (MASM compat.) */ +#define Klist Lastbef+15 /* ignored (MASM compat.) */ +#define Kxlist Lastbef+16 /* ignored (MASM compat.) */ +#define Kdupb Lastbef+17 /* gets remapped to Kdsb */ +#define Kblkb Lastbef+18 /* gets remapped to Kdsb */ +#define Kdb Lastbef+19 /* gets remapped to Kbyt */ +#define Kdw Lastbef+20 /* gets remapped to Kword */ +#define Kalign Lastbef+21 +#define Kblock Lastbef+22 /* gets remapped to .( */ +#define Kbend Lastbef+23 /* gets remapped to .) */ + +#define Kalong Lastbef+24 +#define Kashort Lastbef+25 +#define Kxlong Lastbef+26 +#define Kxshort Lastbef+27 + +#define Kbin Lastbef+28 +#define Kaasc Lastbef+29 + +#define Kcode Lastbef+30 /* gets remapped to Ktext */ + +/* 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 "*=" */ +#define Klistbytes (Lastbef+39-256) +#define Kscope (Lastbef+40) /* mapped to Kopen */ +#define Kendscope (Lastbef+41) /* mapped to Kclose */ + +#define Kassert (Lastbef+42-256) + +/* last valid token+1 */ +#define Anzkey Lastbef+43 /* 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 ... */ + +int number_of_valid_tokens = Anzkey; + +/* array used for hashing tokens (26 entries, a-z) */ + +static int ktp[]={ 0,3,17,25,28,29,29,29,29,32,34,34,38,40,41,42,58, + 58,65,76,90,90,90,92,94,94,94,Anzkey }; + +#define Admodes 24 + +/* + * opcodes for each addressing mode + * high byte: supported architecture (no bits = original NMOS 6502) + * bit 1: R65C02 + * bit 2: 65816 and allows 16-bit quantity (accum only) + * bit 3: 65816 and allows 16-bit quantity (index only) + * low byte: opcode itself + * + * each opcode is indexed in this order: *=65816, ^=R65C02 + * 00 = implied + * 01 = zero page + * 02 = zero page,x + * 03 = direct page,y* + * 04 = direct page (indirect)* + * 05 = (indirect,x) + * 06 = (indirect),y + * 07 = immediate (8-bit) + * 08 = absolute + * 09 = absolute,x + * 10 = absolute,y + * 11 = relative + * 12 = (indirect-16) i.e., jmp (some_vector) + * 13 = (absolute,x)* + * 14 = zero page+relative test'n'branch ^ + * 15 = zero page clear'n'set'bit ^ + * 16 = relative long* + * 17 = absolute long* + * 18 = absolute long,x* + * 19 = stack relative* + * 20 = stack relative (indirect),y* + * 21 = direct page (indirect long)* + * 22 = direct page (indirect long),y* + * 23 = (indirect long) + */ + +static int ct[Lastbef+1][Admodes] ={ +/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 imm */ +{ -1, 0x65,0x75,-1,0x172,0x61,0x71,0x469,0x6d,0x7d,0x79,-1, -1, -1, -1, -1, -1,0x26f,0x27f,0x263,0x273,0x267,0x277,-1 }, /*adc*/ +{ -1, 0x25,0x35,-1,0x132,0x21,0x31,0x429,0x2d,0x3d,0x39,-1, -1, -1, -1, -1, -1,0x22f,0x23f,0x223,0x233,0x227,0x237,-1 }, /*and*/ +{ 0x0a,0x06,0x16,-1, -1, -1, -1, -1, 0x0e,0x1e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*asl*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x10f,-1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bbr*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x18f,-1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bbs*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x90,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bcc*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xb0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bcs*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xf0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*beq*/ +{ -1, 0x24,0x134,-1, -1, -1, -1, 0x589,0x2c,0x13c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bit*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x30,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bmi*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xd0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bne*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x10,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bpl*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x180,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bra*/ +{ 0x00,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*brk*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x50,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bvc*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x70,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bvs*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x282, -1, -1, -1, -1, -1, -1, -1 }, /*brl*/ +{ 0x18,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*clc*/ +{ 0xd8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cld*/ +{ 0x58,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cli*/ +{ 0xb8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*clv*/ +{ -1, 0xc5,0xd5,-1, 0x1d2,0xc1,0xd1,0x4c9,0xcd,0xdd,0xd9,-1, -1, -1, -1, -1,-1,0x2cf,0x2df,0x2c3,0x2d3,0x2c7,0x2d7,-1 }, /*cmp*/ +{ -1, 0xe4,-1, -1, -1, -1, -1, 0x8e0,0xec,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cpx*/ +{ -1, 0xc4,-1, -1, -1, -1, -1, 0x8c0,0xcc,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cpy*/ +{ -1, -1, -1, -1, -1, -1, -1, 0x202,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cop*/ +/* +{ 0x13a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },*/ /*dea*/ +{ 0x13a,0xc6,0xd6,-1, -1, -1, -1, -1, 0xce,0xde,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dec*/ +{ 0xca,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dex*/ +{ 0x88,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dey*/ +{ -1, 0x45,0x55,-1, 0x152,0x41,0x51,0x449,0x4d,0x5d,0x59,-1, -1, -1, -1, -1,-1,0x24f,0x25f,0x243,0x253,0x247,0x257,-1 }, /*eor*/ +/* +{ 0x11a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },*/ /*ina*/ +{ 0x11a,0xe6,0xf6,-1, -1, -1, -1, -1, 0xee,0xfe,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*inc*/ +{ 0xe8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*inx*/ +{ 0xc8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*iny*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, 0x4c,-1, -1, -1, 0x6c,0x17c,-1, -1, -1,0x25c, -1, -1, -1, -1, -1,0x2dc}, /*jmp*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, 0x20,-1, -1, -1, -1, 0x2fc,-1, -1, -1,0x222, -1, -1, -1, -1, -1, -1 }, /*jsr*/ +{ -1, 0xa5,0xb5,-1, 0x1b2,0xa1,0xb1,0x4a9,0xad,0xbd,0xb9,-1, -1, -1, -1, -1,-1,0x2af,0x2bf,0x2a3,0x2b3,0x2a7,0x2b7,-1 }, /*lda*/ +{ -1, 0xa6,-1, 0xb6,-1, -1, -1, 0x8a2,0xae,-1, 0xbe,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ldx*/ +{ -1, 0xa4,0xb4,-1, -1, -1, -1, 0x8a0,0xac,0xbc,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ldy*/ +{ 0x4a,0x46,0x56,-1, -1, -1, -1, -1, 0x4e,0x5e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*lsr*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, 0x244,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*mvp*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, 0x254,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*mvn*/ +{ 0xea,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*nop*/ +{ -1, 0x05,0x15,-1, 0x112,0x01,0x11,0x409,0x0d,0x1d,0x19,-1, -1, -1, -1, -1,-1,0x20f,0x21f,0x203,0x213,0x207,0x217,-1 }, /*ora*/ +{ 0x48,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pha*/ +{ 0x08,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*php*/ +{ 0x1da,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phx*/ +{ 0x15a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phy*/ +{ 0x68,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pla*/ +{ 0x28,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plp*/ +{ 0x1fa,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plx*/ +{ 0x17a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ply*/ +{ 0x28b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phb*/ +{ 0x20b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phd*/ +{ 0x24b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phk*/ +{ 0x2ab,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plb*/ +{ 0x22b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pld*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, 0x2f4,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pea*/ +{ -1, -1, -1, -1,0x2d4, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pei*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, 0x262,-1, -1, -1, -1, -1, -1, -1 }, /*per*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x107, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rmb*/ +{ 0x2a,0x26,0x36,-1, -1, -1, -1, -1, 0x2e,0x3e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rol*/ +{ 0x6a,0x66,0x76,-1, -1, -1, -1, -1, 0x6e,0x7e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ror*/ +{ 0x40,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rti*/ +{ 0x60,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rts*/ +{ -1, -1, -1, -1, -1, -1, -1, 0x2c2,-1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rep*/ +{ 0x26b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rtl*/ +{ -1, 0xe5,0xf5,-1, 0x1f2,0xe1,0xf1,0x4e9,0xed,0xfd,0xf9,-1, -1, -1, -1, -1,-1,0x2ef,0x2ff,0x2e3,0x2f3,0x2e7,0x2f7,-1 }, /*sbc*/ +{ 0x38,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sec*/ +{ 0xf8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sed*/ +{ 0x78,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sei*/ +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x187, -1, -1, -1, -1, -1, -1, -1, -1 }, /*smb*/ +{ -1, 0x85,0x95,-1, 0x192,0x81,0x91,-1, 0x8d,0x9d,0x99,-1, -1, -1, -1, -1,-1,0x28f,0x29f,0x283,0x293,0x287,0x297,-1 }, /*sta*/ +{ -1, 0x86,-1, 0x96,-1, -1, -1, -1, 0x8e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stx*/ +{ -1, 0x84,0x94,-1, -1, -1, -1, -1, 0x8c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sty*/ +{ -1, 0x164,0x174,-1, -1, -1, -1, -1, 0x19c,0x19e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stz*/ +{ -1, -1, -1, -1, -1, -1, -1, 0x2e2,-1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sep*/ +{ 0x2db,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stp*/ +{ 0xaa,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tax*/ +{ 0xa8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tay*/ +{ -1, 0x114,-1, -1, -1, -1, -1, -1, 0x11c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*trb*/ +{ -1, 0x104,-1, -1, -1, -1, -1, -1, 0x10c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsb*/ +{ 0xba,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsx*/ +{ 0x8a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txa*/ +{ 0x9a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txs*/ +{ 0x98,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tya*/ +{ 0x29b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txy*/ +{ 0x2bb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tyx*/ +{ 0x25b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tcd*/ +{ 0x27b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tdc*/ +{ 0x21b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tcs*/ +{ 0x23b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsc*/ +{ 0x2cb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*wai*/ +{ 0x242,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*wdb*/ +{ 0x2eb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*xba*/ +{ 0x2fb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /*xce*/ + + +} ; + +#define Syntax 14 +#define Maxbyt 4 + +/* grouped syntaxes. each row = operand type, column = bytes allowed */ +static int at[Syntax][Maxbyt] ={ +{ 0, -1, -1 ,-1 }, /* implied: no operand */ +{ -1, 7, -1 ,-1 }, /* immediate: single byte operand only */ +{ -1, 15, -1 ,-1 }, /* relative: single byte operand only */ +{ -1, -1, 14 ,-1 }, /* test'n'branch: two bytes only */ +{ -1, 1, 8 ,17 }, /* addressing: 1 byte for zp, + 2 for absolute, + 3 for absolute long */ +{ -1, 2, 9 ,18 }, /* ,x: same */ +{ -1, 3, 10 ,-1 }, /* ,y: 1 byte for dp,y, + 2 for absolute,y */ +{ -1, 4, 12 ,-1 }, /* (indirect): 1 byte for (dp), + 2 for (absolute) */ +{ -1, 5, 13 ,-1 }, /* (i,x): 1 byte for (zp,x), + 2 for (a,x) */ +{ -1, 6, -1 ,-1 }, /* (i),y: 1 byte only */ +{ -1, 21, 23 ,-1 }, /* (indirect long): 1 byte for (dp), + 2 for (a) */ +{ -1, 22, -1 ,-1 }, /* (indirect long),y: 1 byte only */ +{ -1, 19, -1 ,-1 }, /* stack relative: 1 byte only */ +{ -1, 20, -1 ,-1 } /* SR (in),y: 1 byte only */ +}; + +#define AnzAlt 5 + +/* disambiguation table. for example, arbitrary instruction xxx $0000 could + be either interpreted as an absolute operand, or possibly relative. + note: does not look at comma or after, if present. */ +static int xt[AnzAlt][2] ={ /* Alternativ Adr-Modes */ +{ 8, 11 }, /* abs -> rel */ +{ 2, 3 }, /* z,x -> z,y */ +{ 5, 6 }, /* ,x) -> ),y */ +{ 9, 10 }, /* a,x -> a,y */ + +{ 8, 16 } /* abs -> relong */ +}; + +/* cross check: instruction should be this many bytes long in total */ +/* indexed by addressing mode */ +static int le[] ={ 1,2,2,2,2,2,2,2,3,3,3,2,3,3,3,2, + /* new modes */ 3,4,4,2,2,2,2,3 }; + +/* indicates absolute->zp optimizable addressing modes (abs->zp) */ +/* indexed by addressing mode */ +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 */ + +/*********************************************************************************************/ +/* pass 1 */ +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 ;*/ + int afl = 0; + int tlen; /* token listing length, to adjust length that is returned */ + int inp; /* input pointer in t[] */ + unsigned char cast; + +/* notes and typical conventions ... er = error code + am = addressing mode in use +*/ + + cast='\0'; + bl=0; + *al = 0; + +/* printf("\n"); */ + + /* convert the next token from string s */ +#ifdef DEBUG_AM +fprintf(stderr, "- p1 %d starting -\n", pc[segment]); +#endif + + /* 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 we have to 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 + */ + inp = 0; + /* discard label definitions before copying the buffer, so we don't get + * label defined errors */ + while (inp1) && (t[inp]base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length(); + romable=1; + } + if(!er) + { + +/* + * + * pseudo-op dispatch (except .byt, .asc) + * + */ + // fix sign + n=t[0]; // & 0xff; + + /* TODO: make that a big switch statement... */ + /* maybe later. Cameron */ + + if(n==Kend || n==Klist || n==Kxlist) { + *ll = 0; /* ignore */ + } 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 255) + er = E_NOMEM; /* buffer overflow */ + } + binfname[j] = '\0'; + er=icl_open(binfname); + } else { + er=E_SYNTAX; + } + } else + if(n==Kfopt) { + if(romable==1) er=E_ROMOPT; + t[0] = Kbyt; + set_fopt(l,t,nk+1-na1+na2); + *ll = 0; + } else + if(n==Klistbytes) { + int p = 0; + if(!(er=a_term(t+1,&p,&l,pc[segment],&afl,&label,0))) { + er=E_OKDEF; + } + *ll = 3; + t[0] = Klistbytes; + t[1] = p & 0xff; + t[2] = (p >> 8) & 0xff; + //printf("Klistbytes p1: er=%d, l=%d\n", er, l); + } else + if(n==Kpcdef) + { + int tmp; + // get parameter for *= + er=a_term(t+1,&tmp,&l,pc[segment],&afl,&label,0); + // found? + if(!er) + { + i=1; + wval(i,tmp, 0); /* writes T_VALUE, 3 bytes value, plus one byte */ + t[i++]=T_END; + *ll=7; + er=E_OKDEF; +#ifdef DEBUG_RELOC +printf("set pc=%04x, oldsegment=%d, pc[segm]=%04x, ", + pc[SEG_ABS], segment, pc[segment]); +printf(" wrote %02x %02x %02x %02x %02x %02x, %02x, %02x\n", + t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7]); +#endif + if(segment==SEG_TEXT) { + pc[SEG_ABS] = tmp; + r_mode(RMODE_ABS); + } else { + if(!relmode) { + pc[segment] = tmp; + } else { + er = E_ILLSEGMENT; + } + } +/*printf("newsegment=%d, pc[ABS]=%04x\n", segment, pc[SEG_ABS]);*/ + } else { + // no param found, only "*=". + // if we ABS, we switch back to reloc +#ifdef DEBUG_RELOC +printf("reloc: er=%d, l=%d, segment=%d, pc[%d]=%04x, pc[abs(%d)]=%04x, pc[text(%d)]=%04x\n", + er, l, segment, segment, pc[segment], SEG_ABS, pc[SEG_ABS],SEG_TEXT, pc[SEG_TEXT]); +#endif + if((segment==SEG_ABS) && (er==E_SYNTAX && l==0)) { + t[0]=Kreloc; + i=1; + wval(i,pc[SEG_TEXT], 0); + t[i++]=T_END; + *ll=7; + er=E_OKDEF; + r_mode(RMODE_RELOC); +/*printf(" : newseg=%d, pc[newseg]=%04x, pc[abs]=%04x, pc[text]=%04x\n", + segment, pc[segment], pc[SEG_ABS], pc[SEG_TEXT]);*/ + } + } + } else + if(n==Kopen) + { + if(showblk) fprintf(stderr, "%s line %d: .(\n", pp_getidat()->fname, pp_getidat()->fline); + b_open(); + er=E_NOLINE; + } else + if(n==Kclose) + { + if(showblk) fprintf(stderr, "%s line %d: .)\n", pp_getidat()->fname, pp_getidat()->fline); + er=b_close(); + if(!er) er=E_NOLINE; + } else + if(n==Kalong) + { + if (!w65816) { + er=E_65816; + } else { + memode=1; + t[0]=Kalong; + *ll=1; + er=E_OKDEF; + } + } else + if(n==Kashort) + { + memode=0; + t[0]=Kashort; + *ll=1; + er=E_OKDEF; + } else + if(n==Kxlong) + { + if (!w65816) { + er=E_65816; + } else { + xmode=1; + t[0]=Kxlong; + *ll=1; + er=E_OKDEF; + } + } else + if(n==Kxshort) + { + xmode=0; + t[0]=Kxshort; + *ll=1; + er=E_OKDEF; + } else + if(n==Kdsb) + { + dsb_len = 1; + if(!(er=a_term(t+1,&bl,&l,pc[segment],&afl,&label,0))) { + er=E_OKDEF; + } + dsb_len = 0; + } else + if(n==Ktext) { + segment = relmode ? SEG_TEXT : SEG_ABS; + t[0]=Ksegment; + t[1]=segment; + *ll=2; + er=E_OKDEF; + r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else + if(n==Kdata) { + if(relmode) { + segment = SEG_DATA; + t[0]=Ksegment; + t[1]=SEG_DATA; + *ll=2; + er=E_OKDEF; + r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kbss) { + if(relmode) { + segment = SEG_BSS; + t[0]=Ksegment; + t[1]=SEG_BSS; + *ll=2; + er=E_OKDEF; + r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kzero) { + if(relmode) { + segment = SEG_ZERO; + t[0]=Ksegment; + t[1]=SEG_ZERO; + *ll=2; + er=E_OKDEF; + r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if (n==Kassert) { /* ignore this in first pass, just check syntax */ + int x; + i = 1; + + /* XXX: sadly, can't implement unary logical not yet */ + if(!(er=a_term(t+i,&x,&l,pc[segment],&afl,&label,1))) { + i += l; + } + if(t[i] == ',') { /* skip comma */ + i++; + } else { + er = E_SYNTAX; + } + /* get filename. + the tokenizer can either see it as a multichar string ... */ + if (!er) { + int k; + + if(t[i]=='\"') { + i++; + k=t[i]+i+1; + i++; + while(i 255) + er = E_NOMEM; /* buffer overflow */ + } + binfnam[j] = '\0'; + /* or as a 'char' if it's a single character ("word" would + have been caught by the above) */ + } else + if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { + binfnam[0] = v; + binfnam[1] = '\0'; + i += l; + } + } + + /* three arguments only please */ + if (!er && t[i] != T_END && t[i] != T_COMMENT) { + er = E_SYNTAX; + } + + if (!er) { + FILE *foo; + +#ifdef DEBUG_AM + fprintf(stderr, +"binclude1 offset = %i len = %i filename = %s endchar = %i\n", + offset, length, binfnam, i); +#endif + if (!(foo = fopen(binfnam, "rb"))) { + er = E_FNF; + } else { + fseek(foo, 0, SEEK_END); + if ((length+offset) > ftell(foo)) { + er = E_OUTOFDATA; + } else { + length = (length) ? length : + (ftell(foo)-offset); + } + fclose(foo); + } + if (!er) { + if (length > 65535 && !w65816) { + errout(W_OVER64K); + } else if (length > 16777215) { + errout(W_OVER16M); + } + /* pass parameters back to xa.c */ + *ll=i+1; +/* + bl=length+2; +*/ + bl=length; + er = E_OKDEF; /* defer to pass 2 */ + } + } + } else + if(n==Kalign) { + int tmp; + if(segment!=SEG_ABS) { + if(!(er=a_term(t+1,&tmp,&l,pc[segment],&afl,&label,0))) { + if(tmp == 1 || tmp == 2 || tmp == 4 || tmp == 256) { + set_align(tmp); + if(pc[segment] & (tmp-1)) { /* not aligned */ + int tmp2; + t[0]=Kdsb; + i=1; + bl=tmp=(tmp - (pc[segment] & (tmp-1))) & (tmp-1); + wval(i,tmp, 0); + t[i++]=','; + tmp2= 0xea; + wval(i,tmp2, 0); /* nop opcode */ + t[i++]=T_END; + *ll=9; + er=E_OKDEF; + } else { + *ll=0; /* ignore if aligned right */ + } + } else { + er=E_ILLALIGN; + } + } + } else { + er=E_ILLSEGMENT; + } + } else + /* optimization okay on pass 1: use 0 for fl */ + { +#ifdef DEBUG_AM +fprintf(stderr, "E_OK ... t_p2 xat.c %i %i\n", t[0], *ll); +#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); +#ifdef DEBUG_AM +fprintf(stderr, "... --> er=%d\n", er); +#endif + } + + } else + if(er==E_NODEF) + { + + /* + * no label was found from t_conv! + * try to figure out most likely length + * + */ + +#ifdef DEBUG_AM +fprintf(stderr, "E_NODEF pass1 xat.c\n"); +#endif + er = E_OK; /* stuff error */ + n=t[0]; /* look at first token */ + + /* mnemonic dispatch -- abbreviated form in t_p2, but changed here + to not do anything other than 24-bit optimization since we + don't know the value of the label */ + + /* choose addressing mode; add commas found */ + + if(n>=0 && n<=Lastbef && n != Kmvn && n != Kmvp) /* not for mvn/p */ + { + int inp = 1; /* input pointer */ + + if(t[inp]==T_END || t[inp]==T_COMMENT) + { + sy=0; /* implied */ + inp++; + } else + if(t[inp]=='#') + { + sy=1+nk; /* immediate */ + inp++; + } else + if(t[inp]=='(') + { + sy=7+nk; /* computed */ + inp++; + } else { + sy=4+nk; /* absolute or zero page */ + } + + /* this actually finds the cast for all addressing modes, + but t_conv() only puts it there for immediate (#) or absolute/ + absolute indexed addressing modes */ + if (t[inp] == T_CAST) { + inp++; + cast = t[inp]; + inp++; +#ifdef DEBUG_CAST + printf("Found cast to: %c\n", cast); +#endif + } + + /* length counter set to maximum length + 1 */ + if (w65816 || (t[l-1]=='@' || t[l-1] == '!')) { + /* for 65816 allow addressing modes up to 4 byte overall length */ + bl=Maxbyt+1; + } else { + /* for other modes only check for addressing modes up to 3 byte overall length */ + bl=Maxbyt; + } + + /* find best fit for length of this operand */ + while(--bl) + { + + /* look at syntax table (at) using syntax (sy) as index. + is there an addressing mode for an operand + of this length? am = addressing mode */ + + if((am=at[sy][bl-1])>=0) + { + if(am>Admodes-1) /* no, it's -1, syntax error */ + { + er=E_SYNTAX; + break; + } + if(ct[n][am]>=0) /* yes, valid token *and* mode, + so we're done */ + break; + + /* no valid mode for this token, see if it's something + ambiguous; if so, try to interpret in that + context. */ + for(v=0;v=0) + break; + if(v=0 && am>16) /* <<< NOTE! */ + if(ct[n][opt[am]]>=0) + am=opt[am]; + } + /* if ` is declared, force further optimization */ + if (cast=='`') { + if (opt[am]<0 || ct[n][opt[am]]<0) + errout(E_ADRESS); + am=opt[am]; + } + /* if ! is declared, force to 16-bit quantity */ + if (cast=='!' && am>16 && opt[am]>=0 && bl) { + am=opt[am]; + } + + /* couldn't match anything for this opcode */ + if(!bl) + er=E_SYNTAX; + else { + /* ok, get length of instruction */ + bl=le[am]; + /* and add one for 65816 special instruction modes */ + if( ((ct[n][am]&0x400) && memode) || + ((ct[n][am]&0x800) && xmode)) { + bl++; + } + } + + + if (er == E_NODEF) + er = E_OK; + + /* .byt, .asc, .word, .dsb, .fopt pseudo-op dispatch */ + + } 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==Kmvn || n==Kmvp) + { + bl=3; + if (!w65816) er = E_65816; + } else + if(n==Kbyt || n==Kasc || n==Kaasc) + { +#ifdef DEBUG_AM +fprintf(stderr, "byt pass 1 %i\n", nk+1-na1+na2); +#endif + bl=nk+1-na1+na2; + } else + if(n==Kword) + { + bl=2*nk+2; + } else + if(n==Kdsb) + { + er=a_term(t+1,&bl,&l,pc[segment],&afl,&label,0); + } else + if(n==Kfopt) + { + set_fopt(l-1,t+1, nk+1-na1+na2); + *ll = 0; + } else + if(n==T_OP) + { + er=E_OKDEF; + } else + er=E_NODEF; + + if(!er) + er=E_OKDEF; +#ifdef DEBUG_AM +fprintf(stderr, "guessing instruction length is %d\n", bl); +#endif + } + if(er==E_NOLINE) + { + er=E_OK; + *ll=0; + } + + *al += bl; + pc[segment]+=bl; + if(segment==SEG_TEXT) pc[SEG_ABS]+=bl; + if(segment==SEG_ABS) pc[SEG_TEXT]+=bl; + + /* adjust length by token listing buffer length */ +#ifdef DEBUG_CONV + printf("converted: (er=%d, t=%p, ll=%d, tlen=%d):",er, t, *ll, tlen); + for(i=0;i<*ll;i++) + printf("%02x,",t[i] & 0xff); + printf("\n"); + printf("adjusted len=%d\n", *ll+tlen); +#endif + + *ll = *ll + tlen; + return(er); +} + +/*********************************************************************************************/ +/* 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) + * As this is not called from p1, assume that we do not + * do length optimization + * + * *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; note that for .dsb and .bin, this does NOT match + * the length in the internal data structures! + */ +int t_p2_l(signed char *t, int *ll, int *al) +{ + int er = E_OK; + int l = *ll; + + if (l < 0) l = -l; + +#if 0 + { + printf("t_p2_l (ll=%d, t=%p):", *ll, t); + for(int i=0;i l) + { + int i; + + // that is corrupt data and should not happen + list_flush(); + printf("corrupt: t_p2_l (l=%d, tlen=%d, ll=%d, t=%p):", l, tlen, *ll, t); + for(i=0;i0 when E_OKDEF */ + { + *ll=-*ll; + bl=*ll; + er=E_OK; + + } else + { + n=t[0]; + if(n==T_OP) + { + n=cval(t+1); + er=a_term(t+4,&v,&l,pc[segment],&nafl,&label,0); + + if(!er) + { + if(t[3]=='=') + { + v2=v; + } else { + if( (!(er=l_get(n,&v2, &afl))) + && ((afl & A_FMASK)!=(SEG_UNDEF<<8)) + && ((afl & A_FMASK)!=(SEG_UNDEFZP<<8)) ) + { + if(t[3]=='+') + { + if(afl && nafl) { errout(E_WPOINTER); nafl=0; } + nafl = afl; + v2+=v; + } else + if(t[3]=='-') + { + if( (((nafl & A_FMASK)>>8) != afl) + || ((nafl & A_MASK)==A_HIGH) ) { + errout(E_WPOINTER); + nafl=0; + } else { + nafl = afl; + } + v2-=v; + } else + if(t[3]=='*') + { + if(afl || nafl) { errout(E_WPOINTER); nafl=0; } + v2*=v; + } else + if(t[3]=='/') + { + if(afl || nafl) { errout(E_WPOINTER); nafl=0; } + if(v) + v2/=v; + else + er=E_DIV; + } else + if(t[3]=='|') + { + if(afl || nafl) { errout(E_WPOINTER); nafl=0; } + v2=v|v2; + } else + if(t[3]=='&') + { + if(afl || nafl) { errout(E_WPOINTER); nafl=0; } + v2=v2&v; + } + } + } + l_set(n,v2,nafl>>8); + + *ll=0; + if(!er) + er=E_NOLINE; + } + } else + if(n==Kword) + { + i=1; + j=0; + while(!er && t[i]!=T_END && t[i] != T_COMMENT) + { + if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) + { +/*if(afl) printf("relocation 1 %04x at pc=$%04x, value now =$%04x\n", + afl,pc[segment],v); */ + if(afl) u_set(pc[segment]+j, afl, label, 2); + t[j++]=v&255; + t[j++]=(v>>8)&255; + + i+=l; + if(t[i]!=T_END && t[i] != T_COMMENT && t[i]!=',') + er=E_SYNTAX; + else + if(t[i]==',') + i++; + + } + } + *ll=j; + bl=j; + } else + if (n == Kassert) + { + int result = 0; + int c; + i = 1; + + /* this time, actually check something */ + if(!(er=a_term(t+i,&result,&l,pc[segment],&afl,&label,1))) { + i += l; + } + if(t[i] == ',') { /* skip comma */ + i++; + } else { + er = E_SYNTAX; + } + /* get filename. + the tokenizer can either see it as a multichar string ... */ + if (!er) { + int k; + + if (!result) + fprintf(stderr, "Assertion failed: "); + if(t[i]=='\"') { + i++; + k=t[i]+i+1; + i++; + while(i 255) + er = E_NOMEM; /* buffer overflow */ + } + binfnam[j] = '\0'; + flen = j; + /* or as a 'char' if it's a single character ("word" would + have been caught by the above) */ + } else + if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { + binfnam[0] = v; + binfnam[1] = '\0'; + i += l; + flen = 1; + } + } + + /* three arguments only please */ + if (!er && t[i] != T_END && t[i] != T_COMMENT) { + er = E_SYNTAX; + } + + if (!er) { + FILE *foo; + +#ifdef DEBUG_AM + fprintf(stderr, +"binclude2 offset = %i len = %i filename = %s endchar = %i\n", + offset, length, binfnam, i); +#endif + if (!(foo = fopen(binfnam, "rb"))) { + er = E_FNF; + } else { + fseek(foo, 0, SEEK_END); + if ((length+offset) > ftell(foo)) { + er = E_OUTOFDATA; + } else { + length = (length) ? length : + (ftell(foo)-offset); + } + fclose(foo); + } + if (!er) { + if (length > 65535 && !w65816) { + errout(W_OVER64K); + } else if (length > 16777215) { + errout(W_OVER16M); + } + /* pass parameters back to xa.c */ + *ll=length; +/* + bl=length+2; +*/ + bl=length; + t[0] = offset & 255; + t[1] = (offset >> 8) & 255; + t[2] = (offset >> 16) & 255; + /* God help us if the index is > 65535 */ + t[3] = fstart & 255; + t[4] = (fstart >> 8) & 255; + t[5] = flen; /* to massage 'char' types */ + er = E_BIN; + } + } + } else + if (n==Kmvn || n==Kmvp) + { + /* special case these instructions' syntax */ + int wide=0; + i=1; + j=1; + /* write opcode */ + t[0] = ((n == Kmvp) ? 0x44 : 0x54); + while(!er && t[i]!=T_END && t[i]!=T_COMMENT) + { + if (wide) /* oops */ + er = E_SYNTAX; +#ifdef DEBUG_AM +fprintf(stderr, "mvn mvp: %i %i %i %i %i\n", t[0], t[i], wide, i, j); +#endif + if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) + { +/*if(afl) printf("relocation 1 %04x at pc=$%04x, value now =$%04x\n", + afl,pc[segment],v); */ + if(afl) u_set(pc[segment]+j, afl, label, 2); + i+=l; + if (v & 0xff00) + er=E_ILLQUANT; + else + t[j++]=v; + } + if (j > 3) + er=E_SYNTAX; + if(t[i]!=T_END && t[i]!=T_COMMENT && t[i]!=',') + er=E_SYNTAX; + else + if(t[i]==',') + i++; + } + if (j != 3) er = E_SYNTAX; /* oops */ + + /* before we leave, swap the bytes. although disassembled as + mv? src,dest it's actually represented as + mv? $ddss -- see + http://6502org.wikidot.com/software-65816-memorymove */ + i = t[2]; + t[2] = t[1]; + t[1] = i; + + *ll = j; + bl = j; + if (!w65816) er = E_65816; + } else if(n==Kasc || n==Kbyt || n==Kaasc) { + i=1; + j=0; + while(!er && t[i]!=T_END && t[i] != T_COMMENT) + { + if(t[i]=='\"') + { + i++; + k=t[i]+i+1; + i++; + while(i er=%d, nbytes=%d\n", er, nbytes); + list_setbytes(nbytes); + l = 2; + *ll=0; + bl =0; + } else + if(n==Ksegment) { + segment = t[1]; + *ll=0; + bl =0; + } else + if(n==Kdsb) + { + dsb_len = 1; + if(!(er=a_term(t+1,&j,&i,pc[segment],&afl,&label,0))) + { + if (j<0) + er=E_NEGDSBLEN; + else +/* + if(t[i+1]!=',') + er=E_SYNTAX; + else +*/ +/* + if((segment!=SEG_ABS) && afl) + er=E_ILLPOINTER; + else +*/ + { + dsb_len = 0; + + if(t[i+1]==',') { + er=a_term(t+2+i,&v,&l,pc[segment],&afl,&label,0); + } else { + v=0; + } + if(!er && v>>8) + er=E_OVERFLOW; + t[0]=v&255; + if(!er) + { + *ll=j; + bl=j; +#ifdef DEBUG_AM +fprintf(stderr, "Kdsb E_DSB %i\n", j); +#endif + er=E_DSB; + } + } + if(!er) + bl=j; + } + dsb_len = 0; + } else + if(n>=0 && n<=Lastbef) + { + int inp = 1; /* input pointer */ + signed char cast = '\0'; /* cast value */ + + c = t[inp]; + + if(c=='#') + { + inp++; + if (t[inp] == T_CAST) { + inp++; + cast = t[inp]; + inp++; +#ifdef DEBUG_CAST + printf("Found cast to (2): %c\n", cast); +#endif + } + sy=1; + if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) + { +/* if(1) printf("a_term returns afl=%04x\n",afl); */ + + rlt[0] = afl; + lab[0] = label; + inp+=l; + if(t[inp]!=T_END && t[inp] != T_COMMENT) + { + if(t[inp]!=',') + er=E_SYNTAX; + else + { + inp++; + sy++; + if(!(er=a_term(t+inp,vv+1,&l,pc[segment],&afl,&label,1))) + { + rlt[1] = afl; + lab[1] = label; + inp+=l; + if(t[inp]!=T_END && t[inp] != T_COMMENT) + { + if(t[inp]!=',') + er=E_SYNTAX; + else + { + inp++; + sy++; + if(!(er=a_term(t+inp,vv+2,&l,pc[segment],&afl,&label,1))) + { + rlt[2] = afl; + lab[2] = label; + inp+=l; + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + er=E_SYNTAX; + } + } + } + } + } + } + } + } else + if(c==T_END || c==T_COMMENT) + { + sy=0; + } else + if(c=='(') + { + inp++; + if (t[inp] == T_CAST) { + inp++; + cast = t[inp]; + inp++; +#ifdef DEBUG_CAST + printf("Found cast to (3): %c\n", cast); +#endif + } + sy=7; + if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) + { + inp += l; + rlt[0] = afl; + lab[0] = label; + + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + { + if(t[inp]==',') + { + inp++; + if (tolower(t[inp])=='x') + sy=8; + else + sy=13; + + } else + if(t[inp]==')') + { + inp++; + if(t[inp]==',') + { + inp++; + if(tolower(t[inp])=='y') + sy=9; + else + er=E_SYNTAX; + } else + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + er=E_SYNTAX; + } + } else + er=E_SYNTAX; + } + } else + if(c=='[') + { + inp++; + if (t[inp] == T_CAST) { + inp++; + cast = t[inp]; + inp++; +#ifdef DEBUG_CAST + printf("Found cast to (4): %c\n", cast); +#endif + } + sy=10; + if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) + { + inp += l; + rlt[0] = afl; + lab[0] = label; + + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + { + if(t[inp]==']') + { + inp++; + if(t[inp]==',') + { + inp++; + if(tolower(t[inp])=='y') + sy=11; + else + er=E_SYNTAX; + } else + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + er=E_SYNTAX; + } + } else + er=E_SYNTAX; + } + } else + { + if (t[inp] == T_CAST) { + inp++; + cast = t[inp]; + inp++; +#ifdef DEBUG_CAST + printf("Found cast to (5): %c\n", cast); +#endif + } + sy=4; + if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) + { + inp += l; + rlt[0] = afl; + lab[0] = label; + if(t[inp]!=T_END && t[inp]!=T_COMMENT) + { + if(t[inp]==',') + { + inp++; + if(tolower(t[inp])=='y') + sy=6; + else + if(tolower(t[inp])=='s') + sy=12; + else + sy=5; + } else + er=E_SYNTAX; + } + } + } + + /* set bl to maximum overall length +1 as while() below starts with decrementing it */ + if (w65816 || cast=='@' || cast== '!') { + /* for 65816 allow addressing modes up to 4 byte overall length */ + bl=Maxbyt+1; + } else { + /* for other modes only check for addressing modes up to 3 byte overall length */ + bl=Maxbyt; + } + +#ifdef DEBUG_AM + printf("--- trying to find am using: (max+1) bl=%d, sy=%d\n", bl, sy); +#endif + while(--bl) + { + if((am=at[sy][bl-1])>=0) + { + if(am>Admodes) + { + er=E_SYNTAX; + break; + } + if(ct[n][am]>=0) + break; + + for(v=0;v=0) + break; + if(v16 + && !er + && (((vv[0]&0xff8000)==0xff8000) || !(vv[0]&0xff0000)) + && opt[am]>=0) + if(ct[n][opt[am]]>=0) + am=opt[am]; +#ifdef DEBUG_AM +fprintf(stderr, +"aftaa1: pc= %d, am = %d and vv[0] = %d, optimize = %d, bitmask = %d, bl = %d\n", + pc[segment], am, vv[0], fl, (vv[0]&0xffff00), bl); +#endif + if(cast!='!') { + if(bl && !er && !(vv[0]&0xffff00) && opt[am]>=0) { + if(ct[n][opt[am]]>=0) { + if (!fl || cast=='`') { + am=opt[am]; + } else { + errout(W_FORLAB); + } + } + } + } +#ifdef DEBUG_AM +fprintf(stderr, +"aftaa2: pc=%d, am=%d and vv[0]=%d, optimize=%d, bitmask=%d, op=%d, bl=%d\n", + pc[segment], am, vv[0], fl, (vv[0]&0xffff00), ct[n][opt[am]], bl); +#endif + } + + if(!bl) + er=E_SYNTAX; + else + { + bl=le[am]; + if( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode)) { + bl++; + } + if ((am != 11 && am != 16) && (vv[0] > 255 || vv[0] < -256) && bl == 2) { + er = E_OVERFLOW; + } else + if ((am != 11 && am != 16) && (vv[0] > 65535 || vv[0] < -65536) && (bl == 2 || bl == 3)) { + er = E_OVERFLOW; + } + *ll=bl; + } + +#ifdef DEBUG_AM +fprintf(stderr, "byte length is now %d, am=%d, er=%d\n", bl, am, er); +#endif + + if(!er) + { + t[0]=ct[n][am]&0x00ff; + if(ct[n][am]&0x0300) + { + if(ct[n][am]&0x100) { + ncmos++; + if(!cmosfl) + er=E_CMOS; + } else { + n65816++; + if(!w65816) { +fprintf(stderr,"n=%d, am=%d\n", n, am); + er=E_65816; + } + } + } + if(am!=0) + { + if((am<8 && !( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode) )) || (am>=19 && am!=23)) + { + if(vv[0]&0xff00) { +#ifdef DEBUG_AM +fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]); +#endif + er=E_OVERFLOW; + } + else + t[1]=vv[0]; +/*if(rlt[0]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[0],pc[segment]+1,*vv); */ + if(rlt[0]) u_set(pc[segment]+1, rlt[0], lab[0], 1); + } else + if(((am<14 || am==23) && am!=11) || am==7) + { + if (vv[0]>0xffff) { +#ifdef DEBUG_AM +fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]); +#endif + er=E_OVERFLOW; + } + else { + t[1]=vv[0]&255; + t[2]=(vv[0]>>8)&255; +/*if(rlt[0]) printf("relocation 2 byte %04x at pc=$%04x, value now =$%04x\n",rlt[0],pc[segment]+1,*vv); */ + if(rlt[0]) u_set(pc[segment]+1, rlt[0], lab[0], 2); + } + } else + if(am==11 || am==16) { + /* relative, relative long */ + if((segment!=SEG_ABS) && (!rlt[0])) { + er=E_ILLPOINTER; + } else { +/*printf("am=11, pc=%04x, vv[0]=%04x, segment=%d\n",pc[segment],vv[0], segment);*/ + v=vv[0]-pc[segment]-le[am]; + if(((v&0xff80)!=0xff80) && (v&0xff80) && (am==11)) + er=E_RANGE; + else { + t[1]=v&255; + t[2]=(v>>8)&255; + } + } + } else + if(am==14) { + if(vv[0]&0xfff8 || vv[1]&0xff00) + er=E_RANGE; + else + if((segment!=SEG_ABS) && (rlt[0] || !rlt[2])) { + er=E_ILLPOINTER; + } else { +/*if(rlt[1]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[1],pc[segment]+1,*vv); */ + if(rlt[1]) u_set(pc[segment]+1, rlt[1], lab[1], 1); + t[0]=t[0]|(vv[0]<<4); + t[1]=vv[1]; + v=vv[2]-pc[segment]-3; + if((v&0xff80) && ((v&0xff80)!=0xff80)) + er=E_OVERFLOW; + else + t[2]=v; + } + } else + if(am==15) + { +/*if(rlt[1]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[1],pc[segment]+1,*vv); */ + if(rlt[1]) u_set(pc[segment]+1, rlt[1], lab[1], 1); + if(vv[0]&0xfff8 || vv[1]&0xff00) + er=E_OVERFLOW; + else + { + t[0]=t[0]|(vv[0]<<4); + t[1]=vv[1]; + } + } else + if(am==17 || am==18) + { + t[1]=vv[0]&255; + t[2]=(vv[0]>>8)&255; + t[3]=(vv[0]>>16)&255; + if(rlt[0]) { + rlt[0]|=A_LONG; + u_set(pc[segment]+1, rlt[0], lab[0], 3); + } + + } else + er=E_SYNTAX; + } + } + + } else + er=E_SYNTAX; + } + +#ifdef DEBUG_AM +fprintf(stderr, "-- endof P2\n"); +#endif + pc[segment]+=bl; + if(segment==SEG_TEXT) pc[SEG_ABS]+=bl; + if(segment==SEG_ABS) pc[SEG_TEXT]+=bl; + *al = bl; + 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) +{ + static signed char t[MAXLINE]; + int er,i,afl, label; + + if(!(er=t_conv((signed char*)s,t,l,pc,&i,&i,&i,1,NULL))) + { + er=a_term(t,v,&i,pc,&afl,&label,0); + + } + return(er); +} + +/*********************************************************************************************/ +/* 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 + * + * Input params: + * s source input line + * t output token sequence buffer + * l return length of output token sequence here + * pc the current PC to set address labels to that value + * nk return number of comma in the parameters + * na1 asc text count returned + * na2 total byte count in asc texts returned + * af arithmetic flag: 0=do label definitions, parse opcodes and params; + * 1=only tokenize parameters, for b_term() call from the preprocessor + * for arithmetic conditions + * bytep ??? + */ +static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk, + int *na1, int *na2, int af, int *bytep) +{ + static int v,f; + static int operand,o; + int fl,afl; + int p,q,ll,mk,er; + int ud; /* counts undefined labels */ + int n; /* label number to be passed between l_def (definition) and l_set (set the value) */ + int byte; + int uz; /* unused at the moment */ + /*static unsigned char cast;*/ + +/* ich verstehe deutsch, aber verstehen andere leute nicht; so, werde ich + diese bemerkungen uebersetzen ... cameron */ +/* I understand German, but other folks don't, so I'll translate these + comments ... Cameron */ +/* note that I don't write so good tho' ;) */ + + *nk=0; /* comma count */ + *na1=0; /* asc text count */ + *na2=0; /* total bytecount in asc texts */ + ll=0; + er=E_OK; /* error state */ + p=0; + q=0; + ud = uz = byte =0; + mk=0; /* 0 = add'l commas ok */ + fl=0; /* 1 = pass text thru */ + afl=0; /* pointer flag for label */ + + // skip leading whitespace + while(isspace(s[p])) p++; + + n=T_END; + /*cast='\0';*/ + + if(!af) + { + while(s[p]!='\0' && s[p]!=';') + { + //printf("CONV: %s\n", s); + + if (s[p] == ':') { + // this is a ca65 unnamed label + if ((er = l_def((char*)s+p, &ll, &n, &f))) + break; + l_set(n,pc,segment); /* set as address value */ + t[q++]=T_DEFINE; + t[q++]=n&255; + t[q++]=(n>>8)&255; + n=0; + + p+=ll; + + while(isspace(s[p])) p++; + + // end of line + if (s[p] == 0 || s[p] == ';') { + break; + } + } + + /* is keyword? */ + if(!(er=t_keyword(s+p,&ll,&n))) + break; + + /* valid syntax, but just not a real token? */ + if(er && er!=E_NOKEY) + break; + + // if so, try to understand as label + // it returns the label number in n + if((er=l_def((char*)s+p,&ll,&n,&f))) + break; + + p+=ll; + + while(isspace(s[p])) p++; + + if(s[p]=='=') + { + /*printf("Found = @%s\n",s+p);*/ + t[q++]=T_OP; + t[q++]=n&255; + t[q++]=(n>>8)&255; + t[q++]='='; + p++; + ll=n=0; + break; + } else + if(s[p]==':' && s[p+1]=='=') /* support := label assignments (ca65 compatibility) */ + { + /*printf("Found := @%s\n", s+p);*/ + t[q++]=T_OP; + t[q++]=n&255; + t[q++]=(n>>8)&255; + t[q++]='='; + p+=2; + ll=n=0; + break; + } else + if(f && s[p]!='\0' && s[p+1]=='=') + { + t[q++]=T_OP; + t[q++]=n&255; + t[q++]=(n>>8)&255; + t[q++]=s[p]; + p+=2; + ll=n=0; + break; + } else + if(s[p]==':') /* to support label: ... syntax */ + { + p++; + while(s[p]==' ') p++; + l_set(n,pc,segment); /* set as address value */ + t[q++]=T_DEFINE; + t[q++]=n&255; + t[q++]=(n>>8)&255; + n=0; + + } else { /* label ... syntax */ + l_set(n,pc,segment); /* set as address value */ + t[q++]=T_DEFINE; + t[q++]=n&255; + t[q++]=(n>>8)&255; + n=0; + } + + } + + if(n != Kmvn && n != Kmvp && ((n & 0xff) <=Lastbef)) { + mk=1; /* = only 1 comma ok for normal opcodes */ + } + } + + if(s[p]=='\0' || s[p]==';') + { + er=E_NOLINE; + ll=0; + } else + if(!er) + { + + p+=ll; + if(ll) { + t[q++]= n & 0xff; +/* + if( (n&0xff) == Kmacro) { + t[q++]= (n >> 8) & 0xff; + } +*/ + } + + operand=1; + + // skip whitespace + while(isspace(s[p])) { + p++; + } + + if(s[p]=='#') + { + mk=0; + t[q++]=s[p++]; + + // skip following whitespace + while(isspace(s[p])) { + p++; + } + } + +/* + * + * operand processing + * byte = length of operand in bytes to be assembled + * + * + */ + + /* this addresses forced high/low/two byte addressing, but only + for the first operand. Further processing is done in a_term() + */ + +/* FIXIT2 */ + + while(s[p]!='\0' && s[p]!=';' && !er) + { + if(fl) + { + // pass through text (e.g. for ",y") + t[q++]=s[p++]; + + } else + { + if(operand) + { + /* are we forcing the operand into a particular + addressing mode? !, @, ` operators + Note these are not available in ca65, but we only + switch off "@" which are used for cheap local labels*/ + if(s[p]=='!' || (s[p]=='@' && !ca65) || s[p]=='`') + { +#ifdef DEBUG_CAST + printf("Setting cast to: %c\n", s[p]); +#endif + t[q++]=T_CAST; + t[q++]=s[p]; + operand= -operand+1; + p++; + } else + if(s[p]=='(' || s[p]=='-' || s[p]=='>' || + s[p]=='<' || s[p]=='[') + { + t[q++]=s[p++]; + operand= -operand+1; /* invert to become reinverted */ + } else + if(s[p]=='*') + { + t[q++]=s[p++]; + } else + /* maybe it's a label + Note that for ca65 cheap local labels, we check for "@" */ + if(isalpha(s[p]) || s[p]=='_' || ((s[p]==':' || s[p]=='@') && ca65)) + { + + int p2 = 0; + if (n == (Klistbytes & 0xff)) { + // check for "unlimited" + // Note: this could be done by a more general "constants" handling, + // where in appropriate places (like the one here), constants are + // replaced by a pointer to a predefined constants info, e.g. using + // a T_CONSTANT. Which would also fix the listing of this constant + // (which is currently listed as "0") + static char *unlimited = "unlimited"; + while (s[p+p2] != 0 && unlimited[p2] != 0 && s[p+p2] == unlimited[p2]) p2++; + } + if (p2 == 9) { // length of "unlimited" + er = E_OK; + // found constant + wval(q, 0, 'd'); + p += p2; + } else { + //m=n; + er=l_search((char*)s+p,&ll,&n,&v,&afl); + + if (er == E_NODEF && undefok) { + lg_toglobal(s+p); + } + + if(!er) + { + if(afl) { + t[q++]=T_POINTER; + t[q++]=afl & 255; + t[q++]=v & 255; + t[q++]=(v>>8) & 255; + t[q++]=n & 255; /* cheap fix for listing */ + t[q++]=(n>>8) & 255; /* why is the label already resolved in t_conv? */ + } else { + t[q++]=T_LABEL; + t[q++]=n & 255; + t[q++]=(n>>8) & 255; + /*wval(q,v, 0);*/ + } + } else + if(er==E_NODEF) + { +#ifdef DEBUG_AM +fprintf(stderr, "could not find %s\n", (char *)s+p); +#endif + t[q++]=T_LABEL; + t[q++]=n & 255; + t[q++]=(n>>8) & 255; +/* + if(afl==SEG_ZEROUNDEF) uz++; +*/ + ud++; // number of undefined labels + er=E_OK; + } + p+=ll; + } + } + else + if(s[p]<='9' && (s[p]>'0' || (s[p] == '0' && !ctypes))) + { + tg_dez(s+p,&ll,&v); + p+=ll; + wval(q,v, 'd'); + } + else + /* handle encodings: hex, binary, octal, quoted strings */ + switch(s[p]) { + case '0': + // only gets here when "ctypes" is set, and starts with 0 + // we here check for the C stype "0xHEX" and "0OCTAL" encodings + if ('x' == tolower(s[p+1])) { + // c-style hex + tg_hex(s+p+2, &ll, &v); + p+=2+ll; + wval(q, v, '$'); + } else + if (isdigit(s[p+1])) { + // c-style octal if digit follows + tg_oct(s+p+1,&ll,&v); + p+=1+ll; + wval(q,v, '&'); + } else { + // else use decimal (0) + tg_dez(s+p,&ll,&v); + p+=ll; + wval(q,v, 'd'); + } + break; + case '$': + tg_hex(s+p+1,&ll,&v); + p+=1+ll; + wval(q,v, '$'); + break; + case '%': + tg_bin(s+p+1,&ll,&v); + p+=1+ll; + wval(q,v, '%'); + break; + case '&': + tg_oct(s+p+1,&ll,&v); + p+=1+ll; + wval(q,v, '&'); + break; + case '\'': + case '\"': + er=tg_asc(s+p,t+q,&q,&p,na1,na2,n); + break; + case ',': + if(mk) + while(s[p]!='\0' && s[p]!=';') + { + while(s[p]==' ') p++; + *nk+=(s[p]==','); + t[q++]=s[p++]; + } + else + { + *nk+=1; + t[q++]=s[p++]; + } + break; + default : + er=E_SYNTAX; + break; + } + operand= -operand+1; + + } else /* operator */ + { + o=0; + if(s[p]==')' || s[p]==']') + { + t[q++]=s[p++]; + operand =-operand+1; + } else + if(s[p]==',') + { + t[q++]=s[p++]; + if(mk) { + // if only one comma, pass through all following text - esp. ",y" or ",x" etc + fl++; + } + *nk+=1; + } else + switch(s[p]) { + case '+': + o=1; + break; + case '-': + o=2; + break; + case '*': + o=3; + break; + case '/': + o=4; + break; + case '!': + if (s[p+1] == '=') o=12; + break; + case '<': + switch (s[p+1]) { + case '<': + o=6; + break; + case '>': + o=12; + break; + case '=': + o=10; + break; + default : + o=7; + break; + } + break; + case '>': + switch (s[p+1]) { + case '>': + o=5; + break; + case '<': + o=12; + break; + case '=': + o=11; + break; + default: + o=8; + break; + } + break; + case '=': + switch (s[p+1]) { + case '<': + o=10; + break; + case '>': + o=11; + break; + case '=': + o=9; p++; /* hack */ + break; + default: + o=9; + break; + } + break; + case '&': + if (s[p+1]=='&') + o=16; + else + o=13; + break; + case '|': + if (s[p+1]=='|') + o=17; + else + o=15; + break; + case '^': + o=14; + break; + default: + er=E_SYNTAX; + break; + } + if(o) + { + t[q++]=o; + p+=lp[o]; + } + operand= -operand+1; + } + + while(s[p]==' ') p++; + } + } + } +//printf("er=%d, ud=%d\n", er, ud); + if(!er) + { +/* + if(uz==1 && ud==1 && byte!=2) { + byte=1; + } + if(byte == 1) { + t[q++] = T_FBYTE; + } else if(byte == 2) { + t[q++] = T_FADDR; + } +*/ + byte = 0; + if(ud > 0) { + er=E_NODEF; + byte = 1; + } + } + + if (s[p] == ';') { + /* handle comments */ + /* first find out how long */ + int i; + for (i = p+1; s[i] != '\0'; i++); + i = i - p; /* actual length of the comment, including zero-byte terminator */ + /*if (i >= 1) {*/ + /* there actually is a comment */ + t[q++] = T_COMMENT; + t[q++] = i&255; + t[q++] = (i>>8)&255; + memcpy(t+q, s+p+1, i); /* also copy zero terminator, used in listing */ + q += i; + /*}*/ + } + t[q++]=T_END; + /* FIXME: this is an unholy union of two "!" implementations :-( */ + /* FIXME FIXME FIXME ... + if (operand==1) { + t[q++]='\0'; + t[q++]=cast; + } + */ + *l=q; + if(bytep) *bytep=byte; + return(er); +} + +/********************************************************************************************* + * identifies a keyword in s, if it is found, starting with s[0] + * A keyword is either a mnemonic, or a pseudo-opcode + */ +static int t_keyword(signed char *s, int *l, int *n) +{ + int i = 0; // index into keywords + int j = 0; + int hash; + + // keywords either start with a character, a "." or "*" + if(!isalpha(s[0]) && s[0]!='.' && s[0]!='*' ) + return(E_NOKEY); + + // if first char is a character, use it as hash... + if(isalpha(s[0])) + hash=tolower(s[0])-'a'; + else + hash=26; + + + // check for "*=" + if(s[0]=='*') { + j=1; + while(s[j] && isspace(s[j])) j++; + if(s[j]=='=') { + i=Kpcdef; + j++; + } + } + + // no keyword yet found? + if(!i) { + // get sub-table from hash code, and compare with table content + // (temporarily) redefine i as start index in opcode table, and hash as end index + i=ktp[hash]; + hash=ktp[hash+1]; + // check all entries in opcode table from start to end for that hash code + while(i='0') + val=val*8+(s[i++]-'0'); + + *l=i; + *v=val; +} + +static void tg_hex(signed char *s, int *l, int *v) +{ + int i=0,val=0; + + while((s[i]>='0' && s[i]<='9') || (tolower(s[i])<='f' && tolower(s[i])>='a')) + { + val=val*16+(s[i]<='9' ? s[i]-'0' : tolower(s[i])-'a'+10); + i++; + } + *l=i; + *v=val; +} + +/* + * tokenize a string - handle two delimiter types, ' and " + */ +static int tg_asc(signed char *s, signed char *t, int *q, int *p, int *na1, int *na2,int n) +{ + + int er=E_OK,i=0,j=0,bs=0; + + signed char delimiter = s[i++]; + +#ifdef DEBUG_AM +fprintf(stderr, "tg_asc token = %i\n", n); +#endif + + t[j++]='"'; /* pass2 token for string */ + j++; /* skip place for length */ + + while(s[i]!='\0' && (bs || s[i]!=delimiter)) + { + + /* implement backslashed quotes for 2.4 */ + if(n != Kbin && s[i] == '\\' && !bs && !xa23) { + bs=1; i++; continue; + } else bs=0; + /* do NOT convert for Kbin or Kaasc, or for initial parse */ + if (!n || n == Kbin || n == Kaasc) { + t[j++]=s[i]; +/* XXX 2.4 implement option for ^ for backwards compatibility */ + } else if(ca65 || !xa23 || s[i]!='^') { /* no escape code "^" - TODO: does ca65 has an escape code */ + t[j++]=convert_char(s[i]); + } else { /* escape code */ + signed char payload = s[i+1]; + switch(payload) { + case '\0': + er=E_SYNTAX; + break; + case '\"': + if (payload == delimiter) { + t[j++]=convert_char(payload); + i++; + } else { + er=E_SYNTAX; + } + break; + case '\'': + if (payload == delimiter) { + t[j++]=convert_char(payload); + i++; + } else { + er=E_SYNTAX; + } + break; + case '^': + t[j++]=convert_char('^'); + i++; + break; + default: + t[j++]=convert_char(payload&0x1f); + i++; + break; + } + } + i++; + } + if(j==3) /* optimize single byte string to value */ + { + t[0]=T_VALUE; + t[1]=t[2]; + t[2]=0; + t[3]=0; + t[4]=delimiter; + j+=2; + } else + { /* handle as string */ + t[1]=j-2; + *na1 +=1; + *na2 +=j-2; + } + if(s[i]==delimiter) { /* in case of no error */ + i++; /* skip ending delimiter */ + } + *q +=j; + *p +=i; + return(er); +} + + diff --git a/xa/src/xat.c.rej b/xa/src/xat.c.rej new file mode 100644 index 0000000..160d731 --- /dev/null +++ b/xa/src/xat.c.rej @@ -0,0 +1,52 @@ +--- src/xat.c ++++ src/xat.c +@@ -632,45 +632,45 @@ + dsb_len = 0; + } else + if(n==Ktext) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = relmode ? SEG_TEXT : SEG_ABS; + t[0]=Ksegment; + t[1]=segment; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else + if(n==Kdata) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_DATA; + t[0]=Ksegment; + t[1]=SEG_DATA; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kbss) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_BSS; + t[0]=Ksegment; + t[1]=SEG_BSS; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } + } else + if(n==Kzero) { + if(relmode) { ++ r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode + segment = SEG_ZERO; + t[0]=Ksegment; + t[1]=SEG_ZERO; + *ll=2; + er=E_OKDEF; +- r_mode(RMODE_RELOC); // use of segments always switches of ABS reloc mode + } else { + er=E_ILLSEGMENT; + } diff --git a/xa/tests/ca65/Makefile b/xa/tests/ca65/Makefile index 64cb429..b40f7ea 100644 --- a/xa/tests/ca65/Makefile +++ b/xa/tests/ca65/Makefile @@ -34,5 +34,5 @@ escape2: escape2.a65 ../hextool -cmp=escape2.ca65 < $@ clean: - rm -f a.err a.o65 $(OBJS) + rm -f *.err a.o65 $(OBJS) diff --git a/xa/tests/ca65/unnamed2.err b/xa/tests/ca65/unnamed2.err deleted file mode 100644 index f89e1d2..0000000 --- a/xa/tests/ca65/unnamed2.err +++ /dev/null @@ -1,3 +0,0 @@ -unnamed2.a65:line 9: 4007:Label '(null)' not defined -unnamed2.a65:line 13: 400e:Label '(null)' not defined -Break after 2 errors diff --git a/xa/tests/csapiec/testseg.ok b/xa/tests/csapiec/testseg.ok index 6a377b3..254ccb1 100644 Binary files a/xa/tests/csapiec/testseg.ok and b/xa/tests/csapiec/testseg.ok differ diff --git a/xa/tests/globals/Makefile b/xa/tests/globals/Makefile deleted file mode 100644 index 92bdf98..0000000 --- a/xa/tests/globals/Makefile +++ /dev/null @@ -1,10 +0,0 @@ - -all: test1 clean - -test1: test1.s - ../../xa -R -o $@.o65 $< - ../hextool -cmp=$@.o65 < $@.ok - -clean: - rm -f *.o65 - diff --git a/xa/tests/globals/test1.ok b/xa/tests/globals/test1.ok deleted file mode 100644 index 790de10..0000000 Binary files a/xa/tests/globals/test1.ok and /dev/null differ diff --git a/xa/tests/globals/test1.s b/xa/tests/globals/test1.s deleted file mode 100644 index faa85b9..0000000 --- a/xa/tests/globals/test1.s +++ /dev/null @@ -1,8 +0,0 @@ - - .( -foo lda #0 - jmp bar - -&bar =foo - .) - diff --git a/xa/tests/ldoreloc/60.s b/xa/tests/ldoreloc/60.s index 70e5a40..a4cf5bb 100644 --- a/xa/tests/ldoreloc/60.s +++ b/xa/tests/ldoreloc/60.s @@ -5,7 +5,7 @@ ptr .word 0 foo =$1234 - lda ptr2 + lda ptr2 loop: jmp loop .data diff --git a/xa/tests/ldoreloc/61.s b/xa/tests/ldoreloc/61.s index bc3f771..00b716f 100644 --- a/xa/tests/ldoreloc/61.s +++ b/xa/tests/ldoreloc/61.s @@ -1,4 +1,4 @@ - jsr loop + jsr loop bla: lda ptr lda #ptr diff --git a/xa/tests/ldoreloc/Makefile b/xa/tests/ldoreloc/Makefile index 818d56c..5851839 100644 --- a/xa/tests/ldoreloc/Makefile +++ b/xa/tests/ldoreloc/Makefile @@ -58,32 +58,26 @@ linked62.o65: 60.o65 61.o65 t1: linked.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t1.ok t2: linked2.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t2.ok t10: linked10.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t10.ok t11: linked11.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t11.ok t20: linked20.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t20.ok t21: linked21.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t21.ok t22: linked22.o65 @@ -91,46 +85,38 @@ t22: linked22.o65 t30: linked30.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t30.ok t31: linked31.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t31.ok t40: linked40.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t40.ok t41: linked41.o65 ../../reloc65 -bt 32768 -xt -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t41.ok t50: linked50.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t50.ok t51: linked51.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t51.ok t60: linked60.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t60.ok t61: linked61.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ $< - ../hextool $@ > $@.hex ../hextool -cmp=$@ < t61.ok t62: linked62.o65 clean: - rm -f *.o65 *.hex t1 t2 t10 t11 t20 t21 t30 t31 t40 t41 t50 t51 t60 t61 t62 + rm -f *.o65 *.hex t1 t2 t10 t11 t20 t21 t30 t31 t40 t41 t50 t51 t60 t61 diff --git a/xa/tests/listing/Makefile b/xa/tests/listing/Makefile index 44c207e..e5d4992 100644 --- a/xa/tests/listing/Makefile +++ b/xa/tests/listing/Makefile @@ -7,33 +7,41 @@ XA=../../xa CA65=ca65 LD65=ld65 -tests: linebreak.out include1.out listblocks.html listca65.html listca65_2.html +tests: assertx.out assertx.html linebreakx.out include1x.out listblocksx.html listca65x.html listca65_2x.html +assertx.out: assert.a65 + ${XA} -P- -o assertx.o65 $< > $@ + ../hextool -cmp=assert.out < $@ + ../hextool -cmp=assert.o65 < assertx.o65 -include1.out: include1.a65 - ${XA} -P- $< > a.out - ../hextool -cmp=include1.out < a.out +assertx.html: assert.a65 + ${XA} -P- -Fhtml -o assertx.o65 $< > $@ + ../hextool -cmp=assert.html < $@ -linebreak.out: linebreak.a65 - ${XA} -P- $< > a.out - ../hextool -cmp=linebreak.out < a.out +include1x.out: include1.a65 + ${XA} -P- $< > $@ + ../hextool -cmp=include1.out < $@ -listblocks.html: listblocks.a65 - ${XA} -P- -Fhtml listblocks.a65 > a.out - ../hextool -cmp=listblocks.html < a.out +linebreakx.out: linebreak.a65 + ${XA} -P- $< > $@ + ../hextool -cmp=linebreak.out < $@ -listca65.html: listca65.a65 - ${XA} -XCA65 -P- -Fhtml listca65.a65 > a.out +listblocksx.html: listblocks.a65 + ${XA} -P- -Fhtml listblocks.a65 > $@ + ../hextool -cmp=listblocks.html < $@ + +listca65x.html: listca65.a65 + ${XA} -XCA65 -P- -Fhtml -o listca65x.o65 listca65.a65 > $@ #${CA65} $<; ${LD65} -t none -o listca65.ca65 listca65.o; rm listca65.o - ../hextool -cmp=listca65.html < a.out - ../hextool -cmp=listca65.ca65 < a.o65 + ../hextool -cmp=listca65.html < $@ + ../hextool -cmp=listca65.ca65 < listca65x.o65 -listca65_2.html: listca65_2.a65 - ${XA} -XCA65 -P- -Fhtml listca65_2.a65 > a.out +listca65_2x.html: listca65_2.a65 + ${XA} -XCA65 -P- -Fhtml -o listca65_2x.o65 listca65_2.a65 > $@ #${CA65} $<; ${LD65} -t none -o listca65_2.ca65 listca65_2.o; rm listca65_2.o - ../hextool -cmp=listca65_2.html < a.out - ../hextool -cmp=listca65_2.ca65 < a.o65 + ../hextool -cmp=listca65_2.html < $@ + ../hextool -cmp=listca65_2.ca65 < listca65_2x.o65 clean: - rm -f a.err a.o65 a.out + rm -f *.err *x.out *x.html *x.o65 diff --git a/xa/tests/listing/a.o65 b/xa/tests/listing/a.o65 new file mode 100644 index 0000000..301d9c0 Binary files /dev/null and b/xa/tests/listing/a.o65 differ diff --git a/xa/tests/listing/assert.a65 b/xa/tests/listing/assert.a65 new file mode 100644 index 0000000..e6eed67 --- /dev/null +++ b/xa/tests/listing/assert.a65 @@ -0,0 +1,8 @@ + *=$0400 + + .assert *<$17e6, "routine too long" + + lda #<$17e6 >> 2 + + lda *-2 + diff --git a/xa/tests/listing/assert.html b/xa/tests/listing/assert.html new file mode 100644 index 0000000..34f635c --- /dev/null +++ b/xa/tests/listing/assert.html @@ -0,0 +1,12 @@ +(null)
+
+assert.a65
+
+    1 A:1000                                     *= $0400
+
+    3 A:0400                                     .assert *<$17e6,"routine too long"
+
+    5 A:0400  a9 f9                              lda #<$17e6>>2
+
+    7 A:0402  ad 00 04                           lda *-2
+
diff --git a/xa/tests/listing/assert.o65 b/xa/tests/listing/assert.o65 new file mode 100644 index 0000000..5700a95 Binary files /dev/null and b/xa/tests/listing/assert.o65 differ diff --git a/xa/tests/listing/assert.out b/xa/tests/listing/assert.out new file mode 100644 index 0000000..7a8da2a --- /dev/null +++ b/xa/tests/listing/assert.out @@ -0,0 +1,10 @@ + +assert.a65 + + 1 A:1000 *= $0400 + + 3 A:0400 .assert *<$17e6,"routine too long" + + 5 A:0400 a9 f9 lda #<$17e6>>2 + + 7 A:0402 ad 00 04 lda *-2 diff --git a/xa/tests/listing/listexpr.a65 b/xa/tests/listing/listexpr.a65 deleted file mode 100644 index 65f8668..0000000 --- a/xa/tests/listing/listexpr.a65 +++ /dev/null @@ -1,8 +0,0 @@ - - *=$0400 - - .assert *<$17e6, "routine too long" - - lda #<$17e6 >> 2 - - lda *-2 diff --git a/xa/tests/relmode/Makefile b/xa/tests/relmode/Makefile index 68d64ba..2411c00 100644 --- a/xa/tests/relmode/Makefile +++ b/xa/tests/relmode/Makefile @@ -4,7 +4,7 @@ XA=../../xa -tests: mixabs1 mixabs2 mix1 mix2 clean +tests: mixabs1 mixabs2 mix1 mix2 mixabs1: mixabsolute.a65 @@ -13,22 +13,22 @@ mixabs1: mixabsolute.a65 mixabs2: mixabsolute.a65 ${XA} -R $< -o $@.tmp - ../../file65 -V $@.tmp + ../../file65 -v $@.tmp ../../reloc65 -bt 40960 -o $@ $@.tmp ../hextool -cmp=b.ok < $@ mix1: mix1.a65 ${XA} -R -o $@.o65 $< - file65 -V $@.o65 - reloc65 -X -o $@ $@.o65 + ../../file65 -v $@.o65 + ../../reloc65 -X -o $@ $@.o65 ../hextool -cmp=$@.ok < $@.o65 mix2: mix2.a65 ${XA} -R -o $@.o65 $< - file65 -V $@.o65 - reloc65 -X -o $@ $@.o65 + ../../file65 -v $@.o65 + ../../reloc65 -X -o $@ $@.o65 ../hextool -cmp=$@.ok < $@.o65 clean: - rm -f a.err *.o65 a.hex mixabs2* mix1 mix2 + rm -f a.err *.o65 a.hex mixabs2* mix1 mix2 *.tmp diff --git a/xa/tests/relmode/mix1.a65 b/xa/tests/relmode/mix1.a65 index 10b0762..bd4cb89 100644 --- a/xa/tests/relmode/mix1.a65 +++ b/xa/tests/relmode/mix1.a65 @@ -1,11 +1,11 @@ - - .text - - .word $0401 - *=$0401 - *= - - .data -NextPacketPtr: .byte 0,0 ; word + + .text + + .word $0401 + *=$0401 + *= + + .data +NextPacketPtr: .byte 0,0 ; word diff --git a/xa/tests/relmode/mix2.a65 b/xa/tests/relmode/mix2.a65 index 4cfc3e2..c61e3ab 100644 --- a/xa/tests/relmode/mix2.a65 +++ b/xa/tests/relmode/mix2.a65 @@ -1,11 +1,11 @@ - - .text - - .word $0401 - *=$0401 - - - .data -NextPacketPtr: .byte 0,0 ; word + + .text + + .word $0401 + *=$0401 + + + .data +NextPacketPtr: .byte 0,0 ; word diff --git a/xa/tests/relmode/testseg.ok b/xa/tests/relmode/testseg.ok new file mode 100644 index 0000000..6a377b3 Binary files /dev/null and b/xa/tests/relmode/testseg.ok differ diff --git a/xa/tests/usb65/Makefile b/xa/tests/usb65/Makefile index 8202be6..7a3a77f 100644 --- a/xa/tests/usb65/Makefile +++ b/xa/tests/usb65/Makefile @@ -1,14 +1,8 @@ +default: test1.a65 test2.a65 test1.o65 test2.o65 + ../../xa -XC -R -U test1.a65 + ../hextool -cmp=test1.o65 < a.o65 + ../../xa -R -U test2.a65 + ../hextool -cmp=test2.o65 < a.o65 -XA=../../xa - -all: test1 test2 test3 - -test1: test1.a65 - ${XA} -XC -R -U $< - -test2: test2.a65 - ${XA} -R -U $< - -test3: test3.a65 - ${XA} -R -U $< - +clean: + rm -f a.o65 diff --git a/xa/tests/usb65/test1.a65 b/xa/tests/usb65/test1.a65 index 6e0c11c..0045e47 100644 --- a/xa/tests/usb65/test1.a65 +++ b/xa/tests/usb65/test1.a65 @@ -5,7 +5,7 @@ #define max3421e_enable() \ lda #MAX3421E_EnMask :\ jsr spi_enable - + #define max3421e_disable() \ jsr spi_disable @@ -25,7 +25,7 @@ spi_wra() :\ lda #(val) :\ spi_wra() :\ - max3421e_disable() + max3421e_disable() /********************************************************************/ @@ -38,5 +38,5 @@ max3421e_disable() ; macro used o give syntax... - wreg(rPINCTL, bmFDUPSPI+bmINTLEVEL) + wreg(rPINCTL, bmFDUPSPI+bmINTLEVEL) diff --git a/xa/tests/usb65/test1.o65 b/xa/tests/usb65/test1.o65 new file mode 100644 index 0000000..21cb525 Binary files /dev/null and b/xa/tests/usb65/test1.o65 differ diff --git a/xa/tests/usb65/test2.a65 b/xa/tests/usb65/test2.a65 index a553411..7704b30 100644 --- a/xa/tests/usb65/test2.a65 +++ b/xa/tests/usb65/test2.a65 @@ -8,9 +8,9 @@ single jmp single jmp lenerr bne lenerr - + lenerr jsr lenerr - + .) diff --git a/xa/tests/usb65/test2.o65 b/xa/tests/usb65/test2.o65 new file mode 100644 index 0000000..3da0f76 Binary files /dev/null and b/xa/tests/usb65/test2.o65 differ diff --git a/xa/tests/usb65/test3.a65 b/xa/tests/usb65/test3.a65 deleted file mode 100644 index 5c01898..0000000 --- a/xa/tests/usb65/test3.a65 +++ /dev/null @@ -1,28 +0,0 @@ - - -;#define DEBUG -;#undef DEBUG_POLL -;#define DEBUG_HW -; -;printc=$ffd2 - - .( - -;#include "hostmsg.i65" - -; .word $0401 - *=$0401 - -; .word eol -; .word 10 -; .byt $9e, "1040" -; .byt 0 -;eol .word 0 - .dsb 1040-*, $00 -; jmp start - -;irqvec =$90 -;irqsave .word 0 - - .) -