diff --git a/xa/ChangeLog b/xa/ChangeLog index 87d8d8f..c4d05dc 100644 --- a/xa/ChangeLog +++ b/xa/ChangeLog @@ -335,3 +335,20 @@ xa-2.3.9 (Just kidding.) -- Cameron Kaiser 31 January 2019 + +xa-2.3.10 + + * Three fixes, all from Andre: + - Don't crash if a useless segment is referenced outside of relocating + mode (thanks Laszlo Barath for the report). + - Don't substitute within strings, for better cpp compatibility (thanks + Glenn Holmer for the report). I added the -S option for backwards + compatibility for the old behaviour; it will be removed in 2.4 and later. + - Fix underflow issue if a variable is late-bound (with -L) when that + variable is used in computations with negative offsets. + * Deprecated options will be removed in 2.4 and everything is warned. + * Documentation updated. + * Testsuite expanded. + + -- Cameron Kaiser 9 November 2019 + diff --git a/xa/Makefile b/xa/Makefile index 01ad158..d40e328 100644 --- a/xa/Makefile +++ b/xa/Makefile @@ -63,7 +63,7 @@ install: xa uncpk #$(MKDIR) $(DOCDIR)/xa65 dist: clean - cd .. ; tar cvf xa-2.3.9.tar xa-2.3.9 ; gzip xa-2.3.9.tar + cd .. ; tar cvf xa-2.3.10.tar xa-2.3.10 ; gzip xa-2.3.10.tar test: xa uncpk cd tests && ./harness -make="$(MAKE)" -cc="$(CC)" -cflags="$(CFLAGS)" diff --git a/xa/README.1st b/xa/README.1st index 7c53629..25fbe2f 100644 --- a/xa/README.1st +++ b/xa/README.1st @@ -3,7 +3,7 @@ derivatives). xa is a small, fast, portable two-pass assembler that compiles under most ANSI C compilers. It is distributed under the GNU Public License (see COPYING). -The current version is 2.3.9, a bug fix to the long-lived 2.3.0, itself with +The current version is 2.3.10, a bug fix to the long-lived 2.3.0, itself with compatibility improvements and new man-based documentation. It also completed the merge of the 65816 and 6502/R65C02 versions and thus the current xa can generate code for all targets now. diff --git a/xa/man/xa.1 b/xa/man/xa.1 index 43170b9..9032ad8 100644 --- a/xa/man/xa.1 +++ b/xa/man/xa.1 @@ -1,4 +1,4 @@ -.TH XA "1" "31 January 2019" +.TH XA "1" "9 November 2019" .SH NAME xa \- 6502/R65C02/65816 cross-assembler @@ -21,14 +21,6 @@ further in this manual page. .B \-v Verbose output. .TP -.B \-x -Use old filename behaviour (overrides -.BR \-o , -.B \-e -and -.BR \-l ). -This option is now deprecated. -.TP .B \-C No CMOS opcodes (default is to allow R65C02 opcodes). .TP @@ -133,6 +125,23 @@ Show summary of options. .TP .B \-\-version Show version of program. +.LP +The following options are +.BR deprecated +and will be removed in 2.4 and later versions: +.TP +.B \-x +Use old filename behaviour (overrides +.BR \-o , +.B \-e +and +.BR \-l ). +.TP +.B \-S +Allow preprocessor substitution within strings (this is now disallowed +for better +.BR cpp (1) +compatibility). .SH ASSEMBLER SYNTAX @@ -946,6 +955,20 @@ be prepended with the prefix. Otherwise, the assembler will attempt to optimize to 16 bits, which may be undesirable. +.SH "IMMINENT DEPRECATION" +The following options and modes will be +.B REMOVED +in 2.4 and later versions of +.BR xa : +.LP +.B \-x +.LP +.B \-S +.LP +the original +.B mvn $xxxx +syntax + .SH "SEE ALSO" .BR file65 (1), .BR ldo65 (1), diff --git a/xa/src/xa.c b/xa/src/xa.c index cf012e0..7965970 100644 --- a/xa/src/xa.c +++ b/xa/src/xa.c @@ -55,13 +55,14 @@ #define ANZWARN 13 #define programname "xa" -#define progversion "v2.3.9" +#define progversion "v2.3.10" #define authors "Written by Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser" #define copyright "Copyright (C) 1989-2019 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser." /* exported globals */ int ncmos, cmosfl, w65816, n65816; int masm = 0; +int ppinstr = 0; int nolink = 0; int romable = 0; int romaddr = 0; @@ -210,6 +211,10 @@ int main(int argc,char *argv[]) case 'M': masm = 1; /* MASM compatibility mode */ break; + case 'S': + ppinstr = 1; /* preprocessor substitution in strings ok */ + fprintf(stderr, "Warning: -S is deprecated and will be removed in 2.4+!\n"); + break; case 'O': /* output charset */ { char *name = NULL; @@ -267,7 +272,7 @@ int main(int argc,char *argv[]) break; case 'x': /* old filename behaviour */ oldfile = 1; - fprintf(stderr, "Warning: -x is now deprecated and may disappear in future versions!\n"); + fprintf(stderr, "Warning: -x is now deprecated and will be removed in 2.4+!\n"); break; case 'I': if(argv[i][2]==0) { @@ -392,6 +397,8 @@ int main(int argc,char *argv[]) r_mode(RMODE_RELOC); segment = SEG_TEXT; } else { + /* prime old_segment in r_mode with SEG_TEXT */ + segment = SEG_ABS; r_mode(RMODE_ABS); } @@ -460,11 +467,13 @@ int main(int argc,char *argv[]) seg_pass2(); - if(!relmode) { - r_mode(RMODE_ABS); + if(relmode) { + r_mode(RMODE_RELOC); + segment = SEG_TEXT; } else { - r_mode(RMODE_RELOC); - segment = SEG_TEXT; + /* prime old_segment in r_mode with SEG_TEXT */ + segment = SEG_ABS; + r_mode(RMODE_ABS); } er=pass2(); } @@ -825,8 +834,6 @@ static void usage(int default816, FILE *fp) programname); fprintf(fp, " -v verbose output\n" - " -x old filename behaviour (overrides `-o', `-e', `-l')\n" - " This is deprecated and may disappear in future versions!\n" " -C no CMOS-opcodes\n" " -W no 65816-opcodes%s\n" " -w allow 65816-opcodes%s\n", @@ -854,11 +861,16 @@ static void usage(int default816, FILE *fp) " Other segments must be specified with `-b?'\n" " -G suppress list of exported globals\n"); fprintf(fp, + " -p? set preprocessor character to ?, default is #\n" " -DDEF=TEXT defines a preprocessor replacement\n" " -Ocharset set output charset (PETSCII, ASCII, etc.), case-sensitive\n" " -Idir add directory `dir' to include path (before XAINPUT)\n" " --version output version information and exit\n" " --help display this help and exit\n"); + fprintf(fp, + "== These options are deprecated and will be removed in 2.4+! ==\n" + " -x old filename behaviour (overrides `-o', `-e', `-l')\n" + " -S allow preprocessor substitution within strings\n"); } /* diff --git a/xa/src/xa.h b/xa/src/xa.h index 67ee3fe..b00cbed 100644 --- a/xa/src/xa.h +++ b/xa/src/xa.h @@ -22,7 +22,7 @@ #include "xah.h" /* For SEG_MAX */ extern int ncmos, cmosfl, w65816, n65816; -extern int masm, nolink; +extern int masm, nolink, ppinstr; extern int noglob; extern int showblk; extern int relmode; diff --git a/xa/src/xap.c b/xa/src/xap.c index e8ce798..e2f1491 100644 --- a/xa/src/xap.c +++ b/xa/src/xap.c @@ -456,7 +456,25 @@ int pp_replace(char *to, char *ti, int a,int b) { while(t[0]!='\0') { - while(!isalpha(t[0]) && t[0]!='_') + /* find start of a potential token to be replaced */ + while(!isalpha(t[0]) && t[0]!='_') { + + /* escape strings quoted with " */ + if (!ppinstr && t[0] == '\"') { + do { + t++; + ti++; + } while (t[0] && t[0]!='\"'); + } + + /* escape strings quoted with ' */ + if (!ppinstr && t[0] == '\'') { + do { + t++; + ti++; + } while (t[0] && t[0]!='\''); + } + if(t[0]=='\0') break; /*return(E_OK);*/ else @@ -464,6 +482,7 @@ int pp_replace(char *to, char *ti, int a,int b) t++; ti++; } + } for(l=0;isalnum(t[l])||t[l]=='_';l++); ld=l; diff --git a/xa/src/xat.c b/xa/src/xat.c index 681570c..f601b3c 100644 --- a/xa/src/xat.c +++ b/xa/src/xat.c @@ -479,48 +479,44 @@ printf(" wrote %02x %02x %02x %02x %02x %02x\n", dsb_len = 0; } else if(n==Ktext) { -/* if(segment!=SEG_ABS) { */ segment = relmode ? SEG_TEXT : SEG_ABS; t[0]=Ksegment; t[1]=segment; *ll=2; er=E_OKDEF; -/* } else { - er=E_ILLSEGMENT; - } */ } else if(n==Kdata) { -/* if(segment!=SEG_ABS) { */ + if(relmode) { segment = SEG_DATA; t[0]=Ksegment; t[1]=SEG_DATA; *ll=2; er=E_OKDEF; -/* } else { + } else { er=E_ILLSEGMENT; - } */ + } } else if(n==Kbss) { -/* if(segment!=SEG_ABS) { */ + if(relmode) { segment = SEG_BSS; t[0]=Ksegment; t[1]=SEG_BSS; *ll=2; er=E_OKDEF; -/* } else { + } else { er=E_ILLSEGMENT; - } */ + } } else if(n==Kzero) { -/* if(segment!=SEG_ABS) { */ + if(relmode) { segment = SEG_ZERO; t[0]=Ksegment; t[1]=SEG_ZERO; *ll=2; er=E_OKDEF; -/* } else { + } else { er=E_ILLSEGMENT; - } */ + } } else if (n==Kbin) { int j; @@ -704,8 +700,14 @@ fprintf(stderr, "E_NODEF pass1 xat.c\n"); } else sy=4+nk; /* absolute or zero page */ - /* length counter set to maximum length + 1 */ - bl=Maxbyt+1; + /* 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) @@ -1375,9 +1377,19 @@ fprintf(stderr, "Kdsb E_DSB %i\n", j); } } } - - bl=Maxbyt+1; + /* set bl to maximum overall length +1 as while() below starts with decrementing it */ + if (w65816 || (t[*ll-1]=='@' || t[*ll-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; + } + +#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) @@ -1415,8 +1427,8 @@ fprintf(stderr, "Kdsb E_DSB %i\n", j); { #ifdef DEBUG_AM fprintf(stderr, -"b4: pc= %d, am = %d and vv[0] = %d, optimize = %d, bitmask = %d\n", - pc[segment], am, vv[0], fl, (vv[0]&0xffff00)); +"b4: pc= %d, am = %d and vv[0] = %d, optimize = %d, bitmask = %u, er=%d\n", + pc[segment], am, vv[0], fl, (vv[0]&0xffff00), er); #endif /* terrible KLUDGE!!!! OH NOES!!!1! @@ -1455,15 +1467,21 @@ fprintf(stderr, else { bl=le[am]; + 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; + } else if( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode)) { bl++; - } + } *ll=bl; } #ifdef DEBUG_AM -fprintf(stderr, "byte length is now %d\n", bl); +fprintf(stderr, "byte length is now %d, am=%d, er=%d\n", bl, am, er); #endif if(!er) @@ -1512,6 +1530,7 @@ fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]); } } else if(am==11 || am==16) { + /* relative, relative long */ if((segment!=SEG_ABS) && (!rlt[0])) { er=E_ILLPOINTER; } else { diff --git a/xa/tests/README b/xa/tests/README index 0c024ab..74c0686 100644 --- a/xa/tests/README +++ b/xa/tests/README @@ -16,6 +16,8 @@ adrm/ Addressing mode test (especially the optimizer and quantity prefixes) nonl/ Patryk's no-new-line-on-last-line cases ;) fordef/ Optimizer warnings for forward defined labels +relocmode/ Tests to prevent use of irrational segments if relocating + mde isn't on relocundef/ Tests for the detection of undefined references during a reloc65 export ldoreloc/ Test case for the relocation table reading of ldo when undef'd @@ -27,6 +29,8 @@ cpp/ Random preprocessor tests, mostly crap incerr/ 1) .xl/.al should error without -w 2) error should be in the correct file ('816) binclude/ Binary include code with some weird casing +ppstrings/ Don't substitute inside strings (unless -S) +neg_offset/ Test handling of negative offsets with/without relocation chppch/ Changing preprocessor characters (-p) charset/ Tests of when charsets should be honoured and when not mvnmvp/ Test MVN MVP unusual addressing mode ('816) diff --git a/xa/tests/neg_offset/Makefile b/xa/tests/neg_offset/Makefile new file mode 100644 index 0000000..9856112 --- /dev/null +++ b/xa/tests/neg_offset/Makefile @@ -0,0 +1,36 @@ +default: test1 test2 test3 test4 test5 test6 test7 test8 + +test1: + ../../xa -R -LLIB6502 test1.s -o test1.o + ../hextool -cmp=ok1 < test1.o + +test2: + ../../xa -R -LLIB6502 test2.s -o test2.o + ../hextool -cmp=ok2 < test2.o + +test3: + ../../xa -R -LLIB6502 test3.s -o test3.o + ../hextool -cmp=ok3 < test3.o + +test4: + ../../xa -R -LLIB6502 test4.s -o test4.o + ../hextool -cmp=ok4 < test4.o + +test5: + ../../xa -R -LLIB6502 test5.s -o test5.o + ../hextool -cmp=ok5 < test5.o + +test6: + # this test must fail. + ../../xa -R -LLIB6502 test6.s -o test6.o || exit 0 && exit 1 + +test7: + # this test must fail. + ../../xa -R -LLIB6502 test7.s -o test7.o || exit 0 && exit 1 + +test8: + # this test must fail. + ../../xa -R -LLIB6502 test8.s -o test8.o || exit 0 && exit 1 + +clean: + rm -f *.o diff --git a/xa/tests/neg_offset/a.o65 b/xa/tests/neg_offset/a.o65 new file mode 100644 index 0000000..0bea5d1 Binary files /dev/null and b/xa/tests/neg_offset/a.o65 differ diff --git a/xa/tests/neg_offset/ok1 b/xa/tests/neg_offset/ok1 new file mode 100644 index 0000000..9f821a0 Binary files /dev/null and b/xa/tests/neg_offset/ok1 differ diff --git a/xa/tests/neg_offset/ok2 b/xa/tests/neg_offset/ok2 new file mode 100644 index 0000000..9f821a0 Binary files /dev/null and b/xa/tests/neg_offset/ok2 differ diff --git a/xa/tests/neg_offset/ok3 b/xa/tests/neg_offset/ok3 new file mode 100644 index 0000000..3663025 Binary files /dev/null and b/xa/tests/neg_offset/ok3 differ diff --git a/xa/tests/neg_offset/ok4 b/xa/tests/neg_offset/ok4 new file mode 100644 index 0000000..40a1a4a Binary files /dev/null and b/xa/tests/neg_offset/ok4 differ diff --git a/xa/tests/neg_offset/ok5 b/xa/tests/neg_offset/ok5 new file mode 100644 index 0000000..0bea5d1 Binary files /dev/null and b/xa/tests/neg_offset/ok5 differ diff --git a/xa/tests/neg_offset/test1.s b/xa/tests/neg_offset/test1.s new file mode 100644 index 0000000..8ce08a0 --- /dev/null +++ b/xa/tests/neg_offset/test1.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502-3 + + diff --git a/xa/tests/neg_offset/test2.s b/xa/tests/neg_offset/test2.s new file mode 100644 index 0000000..ec436b2 --- /dev/null +++ b/xa/tests/neg_offset/test2.s @@ -0,0 +1,9 @@ + +#define flib2osa_r LIB6502-3 + + .text + + jsr flib2osa_r + + + diff --git a/xa/tests/neg_offset/test3.s b/xa/tests/neg_offset/test3.s new file mode 100644 index 0000000..29a90cd --- /dev/null +++ b/xa/tests/neg_offset/test3.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502-255 + + diff --git a/xa/tests/neg_offset/test4.s b/xa/tests/neg_offset/test4.s new file mode 100644 index 0000000..1358dfb --- /dev/null +++ b/xa/tests/neg_offset/test4.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502+256 + + diff --git a/xa/tests/neg_offset/test5.s b/xa/tests/neg_offset/test5.s new file mode 100644 index 0000000..41d582a --- /dev/null +++ b/xa/tests/neg_offset/test5.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502-256 + + diff --git a/xa/tests/neg_offset/test6.s b/xa/tests/neg_offset/test6.s new file mode 100644 index 0000000..aa2b73f --- /dev/null +++ b/xa/tests/neg_offset/test6.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502-65537 + + diff --git a/xa/tests/neg_offset/test7.s b/xa/tests/neg_offset/test7.s new file mode 100644 index 0000000..b3ea18e --- /dev/null +++ b/xa/tests/neg_offset/test7.s @@ -0,0 +1,6 @@ + + .text + + jsr 65536 + + diff --git a/xa/tests/neg_offset/test8.s b/xa/tests/neg_offset/test8.s new file mode 100644 index 0000000..4571b2a --- /dev/null +++ b/xa/tests/neg_offset/test8.s @@ -0,0 +1,6 @@ + + .text + + jsr LIB6502+65536 + + diff --git a/xa/tests/ppstrings/ok b/xa/tests/ppstrings/ok new file mode 100644 index 0000000..64104b3 Binary files /dev/null and b/xa/tests/ppstrings/ok differ diff --git a/xa/tests/ppstrings/test.s b/xa/tests/ppstrings/test.s new file mode 100644 index 0000000..ba9f521 --- /dev/null +++ b/xa/tests/ppstrings/test.s @@ -0,0 +1,15 @@ + +#define DUP 123 + + .asc "DUP^@" + + .asc '0DUP^@' + + .asc "D","UP^@" + + .asc "DUP + + .asc "DU0 + + .asc "DU + diff --git a/xa/tests/relocmode/Makefile b/xa/tests/relocmode/Makefile new file mode 100644 index 0000000..3a375a5 --- /dev/null +++ b/xa/tests/relocmode/Makefile @@ -0,0 +1,10 @@ +default: test1 + +test1: + # this should fail in non-relocating mode + ../../xa test1.s -o test1.o || exit 0 && exit 1 + ../../xa -R test1.s -o test1.o + ../hextool -cmp=ok < test1.o + +clean: + rm -f *.o diff --git a/xa/tests/relocmode/ok b/xa/tests/relocmode/ok new file mode 100644 index 0000000..828bf95 Binary files /dev/null and b/xa/tests/relocmode/ok differ diff --git a/xa/tests/relocmode/test1.s b/xa/tests/relocmode/test1.s new file mode 100644 index 0000000..5cd10d2 --- /dev/null +++ b/xa/tests/relocmode/test1.s @@ -0,0 +1,7 @@ + + lda foo + + .data + +foo .byt $aa + diff --git a/xa/tests/reset_segment/Makefile b/xa/tests/reset_segment/Makefile new file mode 100644 index 0000000..acb6107 --- /dev/null +++ b/xa/tests/reset_segment/Makefile @@ -0,0 +1,10 @@ +default: test1 + +test1: + ../../xa -R -LLIB6502 test1.s -o test1.o + ../hextool -cmp=ok1 < test1.o + ../../xa -R test2.s -o test2.o + ../hextool -cmp=ok2 < test2.o + +clean: + rm -f *.o diff --git a/xa/tests/reset_segment/ok1 b/xa/tests/reset_segment/ok1 new file mode 100644 index 0000000..195159e Binary files /dev/null and b/xa/tests/reset_segment/ok1 differ diff --git a/xa/tests/reset_segment/ok2 b/xa/tests/reset_segment/ok2 new file mode 100644 index 0000000..4dfc6c1 Binary files /dev/null and b/xa/tests/reset_segment/ok2 differ diff --git a/xa/tests/reset_segment/test1.s b/xa/tests/reset_segment/test1.s new file mode 100644 index 0000000..4c634a4 --- /dev/null +++ b/xa/tests/reset_segment/test1.s @@ -0,0 +1,12 @@ + + ; forward reference + ; results in illegal ptr arithmetic when segment + ; is not reset between pass1 and pass2 + + bne foo +foo + + .data + + + diff --git a/xa/tests/reset_segment/test2.s b/xa/tests/reset_segment/test2.s new file mode 100644 index 0000000..9240c10 --- /dev/null +++ b/xa/tests/reset_segment/test2.s @@ -0,0 +1,23 @@ + + ; test absolute code embedded into relocatable mode + + .text + + lda foo + lda bar + + ; go into absolute mode + *=$1234 + +foo .asc "absolute",0 + + lda foo + lda bar + + ; go back into relocatble mode + *= + +bar .asc "reloc",0 + + +