From 3be092964c80b10564f600325b1e4ff455387140 Mon Sep 17 00:00:00 2001 From: "A. Fachat" Date: Tue, 12 Mar 2024 09:25:18 +0100 Subject: [PATCH] release 2.4.1 --- xa/ChangeLog | 17 ++ xa/Makefile | 7 +- xa/README.1st | 2 +- xa/man/file65.1 | 5 +- xa/man/ldo65.1 | 5 +- xa/man/printcbm.1 | 2 +- xa/man/reloc65.1 | 42 +++- xa/man/uncpk.1 | 5 +- xa/man/xa.1 | 42 +++- xa/misc/file65.c | 45 +++- xa/misc/ldo65.c | 338 +++++++++++++++++++++++++++++-- xa/misc/reloc65.c | 80 +++++++- xa/src/xa.c | 93 +++++---- xa/src/xa.h | 4 +- xa/src/xad.h | 2 + xa/src/xah.h | 11 + xa/src/xal.c | 6 +- xa/src/xat.c | 21 +- xa/tests/README | 1 + xa/tests/align/Makefile | 100 +++++++++ xa/tests/align/t01.a65 | 10 + xa/tests/align/t01.ok | Bin 0 -> 36 bytes xa/tests/align/t02.a65 | 10 + xa/tests/align/t02.ok | Bin 0 -> 38 bytes xa/tests/align/t03.a65 | 10 + xa/tests/align/t03.ok | Bin 0 -> 290 bytes xa/tests/align/t11.a65 | 10 + xa/tests/align/t11.ok | Bin 0 -> 36 bytes xa/tests/align/t12.a65 | 10 + xa/tests/align/t12.ok | Bin 0 -> 38 bytes xa/tests/align/t13.a65 | 10 + xa/tests/align/t13.ok | Bin 0 -> 290 bytes xa/tests/align/t21.mok | 1 + xa/tests/align/t21.msg | 1 + xa/tests/align/t21.ok | Bin 0 -> 35 bytes xa/tests/align/t22.mok | 1 + xa/tests/align/t22.msg | 1 + xa/tests/align/t22.ok | Bin 0 -> 37 bytes xa/tests/align/t23.mok | 1 + xa/tests/align/t23.msg | 1 + xa/tests/align/t23.ok | Bin 0 -> 289 bytes xa/tests/align/t31.mok | 1 + xa/tests/align/t31.msg | 1 + xa/tests/align/t31.ok | Bin 0 -> 36 bytes xa/tests/align/t32.mok | 1 + xa/tests/align/t32.msg | 1 + xa/tests/align/t32.ok | Bin 0 -> 38 bytes xa/tests/align/t33.mok | 1 + xa/tests/align/t33.msg | 1 + xa/tests/align/t33.ok | Bin 0 -> 290 bytes xa/tests/align/t41.mok | 1 + xa/tests/align/t41.msg | 1 + xa/tests/align/t41.ok | Bin 0 -> 35 bytes xa/tests/align/t42.mok | 1 + xa/tests/align/t42.msg | 1 + xa/tests/align/t42.ok | Bin 0 -> 37 bytes xa/tests/align/t43.mok | 1 + xa/tests/align/t43.msg | 1 + xa/tests/align/t43.ok | Bin 0 -> 289 bytes xa/tests/ca65/Makefile | 21 +- xa/tests/ca65/escape1.a65 | 1 + xa/tests/ca65/escape1.out | 2 +- xa/tests/ca65/lll.a65 | 28 +++ xa/tests/ca65/lll.out | Bin 0 -> 11 bytes xa/tests/cll/Makefile | 14 ++ xa/tests/cll/test1.a65 | 30 +++ xa/tests/comcom/816com.asm | 6 + xa/tests/comcom/816com.ok | 1 + xa/tests/comcom/Makefile | 12 +- xa/tests/masmcom/Makefile | 2 +- xa/tests/mode/Makefile | 149 ++++++++++++++ xa/tests/mode/ab1.a65 | 6 + xa/tests/mode/ab2.a65 | 6 + xa/tests/mode/ab256.a65 | 6 + xa/tests/mode/ab4.a65 | 6 + xa/tests/mode/ad1.a65 | 6 + xa/tests/mode/ad2.a65 | 6 + xa/tests/mode/ad256.a65 | 6 + xa/tests/mode/ad4.a65 | 6 + xa/tests/mode/at1.a65 | 4 + xa/tests/mode/at2.a65 | 4 + xa/tests/mode/at256.a65 | 4 + xa/tests/mode/at4.a65 | 4 + xa/tests/mode/c6502-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c6502-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65816-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65816-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65c02-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65c02-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65ce02-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65ce02-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65sc02-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/c65sc02-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/linkup1.tmp.ok | 7 + xa/tests/mode/n6502-ad4.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/n6502-at2.o65.ok | Bin 0 -> 34 bytes xa/tests/mode/test1.o65.ok | Bin 0 -> 547 bytes xa/tests/mode/test2.o65.ok | Bin 0 -> 49 bytes xa/tests/mode/test3.o65.ok | Bin 0 -> 547 bytes 99 files changed, 1129 insertions(+), 114 deletions(-) create mode 100644 xa/tests/align/Makefile create mode 100644 xa/tests/align/t01.a65 create mode 100644 xa/tests/align/t01.ok create mode 100644 xa/tests/align/t02.a65 create mode 100644 xa/tests/align/t02.ok create mode 100644 xa/tests/align/t03.a65 create mode 100644 xa/tests/align/t03.ok create mode 100644 xa/tests/align/t11.a65 create mode 100644 xa/tests/align/t11.ok create mode 100644 xa/tests/align/t12.a65 create mode 100644 xa/tests/align/t12.ok create mode 100644 xa/tests/align/t13.a65 create mode 100644 xa/tests/align/t13.ok create mode 100644 xa/tests/align/t21.mok create mode 100644 xa/tests/align/t21.msg create mode 100644 xa/tests/align/t21.ok create mode 100644 xa/tests/align/t22.mok create mode 100644 xa/tests/align/t22.msg create mode 100644 xa/tests/align/t22.ok create mode 100644 xa/tests/align/t23.mok create mode 100644 xa/tests/align/t23.msg create mode 100644 xa/tests/align/t23.ok create mode 100644 xa/tests/align/t31.mok create mode 100644 xa/tests/align/t31.msg create mode 100644 xa/tests/align/t31.ok create mode 100644 xa/tests/align/t32.mok create mode 100644 xa/tests/align/t32.msg create mode 100644 xa/tests/align/t32.ok create mode 100644 xa/tests/align/t33.mok create mode 100644 xa/tests/align/t33.msg create mode 100644 xa/tests/align/t33.ok create mode 100644 xa/tests/align/t41.mok create mode 100644 xa/tests/align/t41.msg create mode 100644 xa/tests/align/t41.ok create mode 100644 xa/tests/align/t42.mok create mode 100644 xa/tests/align/t42.msg create mode 100644 xa/tests/align/t42.ok create mode 100644 xa/tests/align/t43.mok create mode 100644 xa/tests/align/t43.msg create mode 100644 xa/tests/align/t43.ok create mode 100644 xa/tests/ca65/lll.a65 create mode 100644 xa/tests/ca65/lll.out create mode 100644 xa/tests/cll/Makefile create mode 100644 xa/tests/cll/test1.a65 create mode 100644 xa/tests/comcom/816com.asm create mode 100644 xa/tests/comcom/816com.ok create mode 100644 xa/tests/mode/Makefile create mode 100644 xa/tests/mode/ab1.a65 create mode 100644 xa/tests/mode/ab2.a65 create mode 100644 xa/tests/mode/ab256.a65 create mode 100644 xa/tests/mode/ab4.a65 create mode 100644 xa/tests/mode/ad1.a65 create mode 100644 xa/tests/mode/ad2.a65 create mode 100644 xa/tests/mode/ad256.a65 create mode 100644 xa/tests/mode/ad4.a65 create mode 100644 xa/tests/mode/at1.a65 create mode 100644 xa/tests/mode/at2.a65 create mode 100644 xa/tests/mode/at256.a65 create mode 100644 xa/tests/mode/at4.a65 create mode 100644 xa/tests/mode/c6502-ad4.o65.ok create mode 100644 xa/tests/mode/c6502-at2.o65.ok create mode 100644 xa/tests/mode/c65816-ad4.o65.ok create mode 100644 xa/tests/mode/c65816-at2.o65.ok create mode 100644 xa/tests/mode/c65c02-ad4.o65.ok create mode 100644 xa/tests/mode/c65c02-at2.o65.ok create mode 100644 xa/tests/mode/c65ce02-ad4.o65.ok create mode 100644 xa/tests/mode/c65ce02-at2.o65.ok create mode 100644 xa/tests/mode/c65sc02-ad4.o65.ok create mode 100644 xa/tests/mode/c65sc02-at2.o65.ok create mode 100644 xa/tests/mode/linkup1.tmp.ok create mode 100644 xa/tests/mode/n6502-ad4.o65.ok create mode 100644 xa/tests/mode/n6502-at2.o65.ok create mode 100644 xa/tests/mode/test1.o65.ok create mode 100644 xa/tests/mode/test2.o65.ok create mode 100644 xa/tests/mode/test3.o65.ok diff --git a/xa/ChangeLog b/xa/ChangeLog index b648897..7b649a1 100644 --- a/xa/ChangeLog +++ b/xa/ChangeLog @@ -438,3 +438,20 @@ xa-2.4.0 -- André Fachat and -- Cameron Kaiser , 18 November, 2023 +xa 2.4.1 + + * Allow colon-based unnamed labels to be used separately of CA65 mode + (such as with 65816) with -a. Implies -XMASM. + * Restore ^ syntax for generating control sequences (e.g., "^m^j" evaluates + as 0d 0a) with -k. + * Fix a bug using cheap local labels in expressions. + * Properly tag and match CPU types in o65 objects during relocation and + linking. + * Fix a bug with .align when aligning segments. + * Better validation of arguments to indexed opcodes. + * Testsuite expanded. + + -- André Fachat and + -- Cameron Kaiser , 5 March, 2024 + + diff --git a/xa/Makefile b/xa/Makefile index fb0204f..7691165 100644 --- a/xa/Makefile +++ b/xa/Makefile @@ -1,12 +1,11 @@ # Unix gcc or DOS go32 cross-compiling gcc # -VERS = 2.4.0 +VERS = 2.4.1 CC = gcc LD = gcc # for testing. not to be used; build failures in misc/. -#CFLAGS = -O2 -W -Wall -pedantic -ansi -#CFLAGS = -O2 -g -CFLAGS = -O2 +#CFLAGS = -O2 -W -Wall -pedantic -ansi -g +CFLAGS = -O2 -g LDFLAGS = -lc # for DOS? diff --git a/xa/README.1st b/xa/README.1st index d7e4ede..ccfdb42 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.4.0, the first new feature release literally in +The current version is 2.4.1, a bug fix for 2.4.0, the first major release in years. It builds upon the improvements in 2.3.x and its unified 6502/65816 assembler core by adding listing capability, greater flexibility with relocatable objects, and better cross-compatibility with other popular diff --git a/xa/man/file65.1 b/xa/man/file65.1 index 713fd01..495064e 100644 --- a/xa/man/file65.1 +++ b/xa/man/file65.1 @@ -1,4 +1,4 @@ -.TH FILE65 "1" "18 November 2023" +.TH FILE65 "1" "5 March 2024" .SH NAME file65 \- print information for o65 object files @@ -44,7 +44,6 @@ Show version of program. .SH "SEE ALSO" .BR ldo65 (1), -.BR printcbm (1), .BR reloc65 (1), .BR uncpk (1), .BR xa (1), @@ -54,7 +53,7 @@ Show version of program. This manual page was written by David Weinehall and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE diff --git a/xa/man/ldo65.1 b/xa/man/ldo65.1 index 9a4c366..2491a1b 100644 --- a/xa/man/ldo65.1 +++ b/xa/man/ldo65.1 @@ -1,4 +1,4 @@ -.TH LDO65 "1" "18 November 2023" +.TH LDO65 "1" "5 March 2024" .SH NAME ldo65 \- linker for o65 object files @@ -57,7 +57,6 @@ Show version of program. .SH "SEE ALSO" .BR file65 (1), -.BR printcbm (1), .BR reloc65 (1), .BR uncpk (1), .BR dxa (1), @@ -67,7 +66,7 @@ Show version of program. This manual page was written by David Weinehall and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE diff --git a/xa/man/printcbm.1 b/xa/man/printcbm.1 index a79b64a..41fc92b 100644 --- a/xa/man/printcbm.1 +++ b/xa/man/printcbm.1 @@ -40,7 +40,7 @@ Show version of program. .SH AUTHOR This manual page was written by David Weinehall . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE diff --git a/xa/man/reloc65.1 b/xa/man/reloc65.1 index eda869b..c37675e 100644 --- a/xa/man/reloc65.1 +++ b/xa/man/reloc65.1 @@ -1,4 +1,4 @@ -.TH RELOC65 "1" "18 November 2023" +.TH RELOC65 "1" "5 March 2024" .SH NAME reloc65 \- relocator for o65 object files @@ -47,6 +47,43 @@ file. Relocating data segment to the end of the text segment and bss segment to the end of the data segment (\-xd and \-xb options override the derived address) before extracting. .TP +.B \-C cputype +Define a new CPU type for the output file. Available values are: +.IP +.B 6502 +- documented 6502 opcodes only +.IP +.B NMOS6502 +- +.B 6502 +plus undocumented opcodes +.IP +.B 65SC02 +- extends +.B 6502 +with CMOS opcodes, except for +.BR BBR / BBS / SMB +and +.B RMB +.IP +.B 65C02 +- extends +.B 65SC02 +with the +.BR BBR / BBS / SMB +and +.B RMB +opcodes +.IP +.B 65CE02 +- extends +.B 65C02 +with additional CE-specific opcodes +.IP +.B 65816 +- 65816 in 6502 emulation mode; extends +.B 65SC02 +.TP .B \-\-help Show summary of options. .TP @@ -56,7 +93,6 @@ Show version of program. .SH "SEE ALSO" .BR file65 (1), .BR ldo65 (1), -.BR printcbm (1), .BR uncpk (1), .BR dxa (1), .BR xa (1) @@ -65,7 +101,7 @@ Show version of program. This manual page was written by David Weinehall and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE diff --git a/xa/man/uncpk.1 b/xa/man/uncpk.1 index d97dbb7..109515c 100644 --- a/xa/man/uncpk.1 +++ b/xa/man/uncpk.1 @@ -1,4 +1,4 @@ -.TH UNCPK "1" "18 November 2023" +.TH UNCPK "1" "5 March 2024" .SH NAME uncpk \- manage c64 cpk archives @@ -61,7 +61,6 @@ List contents of archive .SH "SEE ALSO" .BR file65 (1), .BR ldo65 (1), -.BR printcbm (1), .BR reloc65 (1), .BR dxa (1), .BR xa (1) @@ -70,7 +69,7 @@ List contents of archive This manual page was written by David Weinehall and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE diff --git a/xa/man/xa.1 b/xa/man/xa.1 index a91a3cf..3135cfc 100644 --- a/xa/man/xa.1 +++ b/xa/man/xa.1 @@ -1,4 +1,4 @@ -.TH XA "1" "18 November 2023" +.TH XA "1" "5 March 2024" .SH NAME xa \- 6502/R65C02/65816 cross-assembler @@ -117,13 +117,22 @@ restores partial compatibility with .B xa 2.3.x. In particular, it uses .B ^ -for quote escapes instead of 2.4's +for generating control characters, disables escaped characters with .BR \e , allows nested multi-line comments, and disables all predefined .B xa -preprocessor macros. This option is inherently deprecated and may be removed +preprocessor macros. Although some portions of this option remain +supported syntax, the option itself is inherently deprecated and may be removed in the next 2.x or 3.x release. .TP +.B \-a +Support +.BR ca65 (1)-style +unnamed labels using colons, but not the remainder of the other supported +.BR ca65 (1) +features. This allows their use with 65816 mode, for example. Implies +.BR -XMASM . +.TP .B \-M This option is deprecated and will be removed in a future version; use .B \-XMASM @@ -131,6 +140,14 @@ instead. Allows colons to appear in comments for MASM compatibility. This does not affect colon interpretation elsewhere, and may become the default in a future version. .TP +.B \-k +Allow the carat +.RB ( ^ ) +to mask a character with $1f/31. This can be used as a shorthand for +control characters, such as +.B "^m^j" +becoming a carriage return followed by a linefeed. +.TP .B \-R Start assembler in relocating mode, i.e. use segments. .TP @@ -323,14 +340,14 @@ and .LP If .B \-XCA65 -is specified, "cheap" local labels may be used, marked by the -.B @ -prefix. Additionally, unnamed labels may be specified with +or +.B \-a +is specified, "unnamed" labels may be specified with .B : (i.e., no label, just a colon); branches may then reference these unnamed labels with a colon and plus signs for forward branching or minus signs for backward branching. For example (from the -.B ca65 +.BR ca65 (1) documentation), .LP : lda (ptr1),y ; #1 @@ -367,6 +384,14 @@ documentation), .BR : rts ; #4 .LP +Additionally, in +.B \-XCA65 +mode, "cheap" local labels may be used, marked by the +.B @ +prefix. These temporary labels exist only between two regular labels and +automatically go out of scope with the next regular label. This allows, +with reasonable care, reuse of common label names like "loop." +.LP For those instructions where the accumulator is the implied argument (such as .B asl and @@ -1175,7 +1200,6 @@ indexed, branching and so on. .SH "SEE ALSO" .BR file65 (1), .BR ldo65 (1), -.BR printcbm (1), .BR reloc65 (1), .BR uncpk (1), .BR dxa (1) @@ -1185,7 +1209,7 @@ This manual page was written by David Weinehall , Andre Fachat and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes -(C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall, +(C)1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall, Cameron Kaiser. The official maintainer is Cameron Kaiser. .SH OVER 30 YEARS OF XA diff --git a/xa/misc/file65.c b/xa/misc/file65.c index 064f588..6c69b46 100644 --- a/xa/misc/file65.c +++ b/xa/misc/file65.c @@ -37,6 +37,36 @@ #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre Fachat." +/* o65 file format mode bits */ +#define FM_OBJ 0x1000 +#define FM_SIZE 0x2000 +#define FM_RELOC 0x4000 +#define FM_CPU 0x8000 + +#define FM_CPU2 0x00f0 + +#define FM_CPU2_6502 0x0000 +#define FM_CPU2_65C02 0x0010 +#define FM_CPU2_65SC02 0x0020 +#define FM_CPU2_65CE02 0x0030 +#define FM_CPU2_NMOS 0x0040 +#define FM_CPU2_65816E 0x0050 + +const char *cpunames[16] = { + "6502", + "65C02", + "65SC02", + "65CE02", + "NMOS6502", + "65816", + NULL, NULL, + "6809", NULL, // 1000 - + "Z80", NULL, NULL, // 1010 - + "8086", // 1101 - + "80286", // 1110 - + NULL +}; + int read_options(FILE *fp); int print_labels(FILE *fp, int offset); @@ -81,7 +111,7 @@ int main(int argc, char *argv[]) { i = 1; - if (strstr(argv[i], "--help") || strstr(argv[i], "-?")) { + if (strstr(argv[i], "--help") || strstr(argv[i], "-?") || strstr(argv[i], "-h")) { usage(stdout); exit(0); } @@ -114,7 +144,7 @@ int main(int argc, char *argv[]) { xapar = 1; break; default: - fprintf(stderr,"%s: %s unknown option\n",programname,argv[i]); + fprintf(stderr,"%s: %s unknown option, use '-h' for help\n",programname,argv[i]); break; } } else { @@ -127,11 +157,12 @@ int main(int argc, char *argv[]) { printf("%s: o65 version %d %s file\n", argv[i], hdr[5], hdr[7]&0x10 ? "object" : "executable"); printf(" mode: %04x =",mode ); - printf("%s%s%s%s%s\n", - (mode & 0x1000)?"[object]":"[executable]", - (mode & 0x2000)?"[32bit]":"[16bit]", - (mode & 0x4000)?"[page relocation]":"[byte relocation]", - (mode & 0x8000)?"[CPU 65816]":"[CPU 6502]", + printf("[%s][%sbit][%s relocation][CPU %s][CPU2 %s]%s\n", + (mode & 0x1000)?"object":"executable", + (mode & 0x2000)?"32":"16", + (mode & 0x4000)?"page":"byte", + (mode & 0x8000)?"65816":"6502", + cpunames[(mode & FM_CPU2) >> 4], aligntxt[mode & 3]); } if(mode & 0x2000) { diff --git a/xa/misc/ldo65.c b/xa/misc/ldo65.c index 32ae45b..05e48cd 100644 --- a/xa/misc/ldo65.c +++ b/xa/misc/ldo65.c @@ -54,6 +54,22 @@ The process of linking works as follows: */ +/* o65 file format mode bits */ +#define FM_OBJ 0x1000 +#define FM_SIZE 0x2000 +#define FM_RELOC 0x4000 +#define FM_CPU 0x8000 + +#define FM_CPU2 0x00f0 + +#define FM_CPU2_6502 0x0000 +#define FM_CPU2_65C02 0x0010 +#define FM_CPU2_65SC02 0x0020 +#define FM_CPU2_65CE02 0x0030 +#define FM_CPU2_NMOS 0x0040 +#define FM_CPU2_65816E 0x0050 + + typedef struct { char *name; int len; @@ -67,12 +83,21 @@ typedef struct { size_t fsize; /* length of file */ unsigned char *buf; /* file content */ + int mode; /* mode value */ + int align; /* align value */ + int tbase; /* header: text base */ int tlen; /* text length */ + int talign; /* insert to get correct alignment */ + int dbase; /* data base */ int dlen; /* data length */ + int dalign; /* insert to get correct alignment */ + int bbase; /* bss base */ int blen; /* bss length */ + int balign; /* insert to get correct alignment */ + int zbase; /* zero base */ int zlen; /* zero length */ @@ -124,6 +149,21 @@ file65 file; unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 }; +const char *cpunames[16] = { + "documented 6502", + "65C02 (CMOS with BBR/BBS/RMB/SMB)", + "65SC02 (CMOS without BBR/BBS/RMB/SMB)", + "65CE02", + "6502 with undocumented opcodes", + "65816 in 6502 emulation mode", + "n/a", "n/a", + "6809?", "n/a", // 1000 - + "Z80?", "n/a", "n/a", // 1010 - + "8086?", // 1101 - + "80286?", // 1110 - + "n/a" +}; + int verbose = 0; void usage(FILE *fp) @@ -150,6 +190,7 @@ int main(int argc, char *argv[]) { int noglob=0; int undefok=0; int i = 1; + // default output segment addresses, overwritten by cmdline params int tbase = 0x0400, dbase = 0x1000, bbase = 0x4000, zbase = 0x0002; int ttlen, tdlen, tblen, tzlen, routtlen, routdlen, tro, dro; int lasttaddr, lastdaddr; @@ -158,8 +199,11 @@ int main(int argc, char *argv[]) { int j, jm; file65 *file, **fp = NULL; FILE *fd; - int nundef = 0; // counter/index in list of remaining undef'd labels - + int nundef = 0; // counter/index in list of remaining undef'd labels + int maxalign; // maximum alignment over all files + char *alignfname; // (first) file that requires that alignment + int trgmode = 0; // mode for the output file + char alignbuf[256]; // to efficiently write align fillers char *arg; char **defined = NULL; @@ -176,7 +220,7 @@ int main(int argc, char *argv[]) { exit(1); } - if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { + if (strstr(argv[1], "--help") || strstr(argv[1], "-?") || strstr(argv[1], "-h")) { usage(stdout); exit(0); } @@ -188,6 +232,7 @@ int main(int argc, char *argv[]) { /* read options */ while(ialign > maxalign) { + maxalign = file->align; + alignfname = file->fname; + } + if (file->mode & 0x8000) { + // 65816 + trgmode |= 0x8000; + if (trgcpu == 4) { + fprintf(stderr, "Error: file '%s' in 65816 CPU mode is incompatible with previous NMOS undocumented opcodes CPU mode\n", + file->fname); + er = 1; + } + } + if (file->mode & 0x0200) { + // zero out bss + trgmode |= 0x0200; + } + // CPU bits + fcpu = (file->mode & FM_CPU2) >> 4; + if (verbose) { + printf("Matching file %s with CPU %s (%d) to target %s (%d) ...\n", + file->fname, cpunames[fcpu], fcpu, cpunames[trgcpu], trgcpu); + } + switch (fcpu) { + case 0x0: // bare minimum documented 6502 is just fine + break; + + case 0x1: // 65C02 - CMOS with BBR/BBS/RMB/SMB, incompatible with 65816 + case 0x3: // 65CE02 - CMOS with BBR/... and add'l opcodes, incompatible w/ 65816 + if (trgmode & 0x8000 || trgcpu == 5) { + fprintf(stderr, "Error: file '%s' in CPU mode %d (%s) " + "is incompatible with previous 65816 CPU mode\n", + file->fname, fcpu, cpunames[fcpu]); + er = 1; + } + // fall-through + case 0x2: // 65SC02 - CMOS without BBR/BBS/RMB/SMB, compatible with 65816 + if (trgcpu == 4) { + // is incompatible with nmos6502 with undocumented opcodes + fprintf(stderr, "Error: file '%s' in CPU mode %d (%s) " + "is incompatible with previous files with mode %d (%s)\n", + file->fname, fcpu, cpunames[fcpu], trgcpu, cpunames[trgcpu]); + er = 1; + } + break; + + case 0x5: // 65816 in 6502 emulation mode + if (trgcpu == 1 || trgcpu == 3) { + // 65C02 and 65CE02 are incompatible with nmos6502 with undocumented opcodes + fprintf(stderr, "Error: file '%s' in CPU mode %d (%s) is " + "incompatible with previous files with mode %d (%s)\n", + file->fname, fcpu, cpunames[fcpu], trgcpu, cpunames[trgcpu]); + er = 1; + } + break; + + case 0x4: // NMOS 6502 with undocumented opcodes + if (trgcpu == 1 || trgcpu == 2 || trgcpu == 3 || trgcpu == 5) { + // is incompatible with nmos6502 with undocumented opcodes + fprintf(stderr, "Error: file '%s' in CPU mode %d (%s) is " + "incompatible with previous files with mode %d (%s)\n", + file->fname, fcpu, cpunames[fcpu], trgcpu, cpunames[trgcpu]); + er = 1; + } + if (trgmode & 0x8000) { + fprintf(stderr, "Error: file '%s' in mode %d (%s) is incompatible with previous 65816 CPU mode\n", + file->fname, 4, cpunames[4]); + er = 1; + } + break; + default: + if (fcpu > 5) { + printf("Warning: unknown CPU mode %d (%s) detected in file %s\n", + fcpu, cpunames[fcpu], file->fname); + } + break; + } + // setting the new mode + switch (fcpu) { + case 0x0: // compatible with everything, no change + break; + case 0x3: // 65CE02 -> supersedes 6502, 65SC02, and 65C02 + if (trgcpu == 1) { + // 65C02 + trgcpu = fcpu; + } + // fall-through + case 0x5: // 65816 in 6502 emu mode, supersedes documented NMOS and 65SC02 + case 0x1: // CMOS w/ BBR.. -> supersedes documented NMOS and 65SC02 + if (trgcpu == 2) { + // 65SC02 + trgcpu = fcpu; + } + // fall-through + case 0x2: // 65SC02 -> supersedes only NMOS 6502 + case 0x4: // NMOS 6502 w/ undocumented opcodes + default: + if (trgcpu == 0) { + // NMOS 6502 + trgcpu = fcpu; + } + break; + } + if (verbose && !er) { + printf("... to new target %s (%d)\n", + cpunames[trgcpu], trgcpu); + } + } + if (er) { + exit(1); + } + trgmode |= trgcpu << 4; + } + if (maxalign) { + printf("Info: Alignment at %d-boundaries required\n", maxalign + 1); + } + switch (maxalign) { + case 0: + break; + case 1: + trgmode |= 1; + break; + case 3: + trgmode |= 2; + break; + case 255: + trgmode |= 3; + break; + } + + // ------------------------------------------------------------------------- // step 2 - calculate new segment base addresses per file, by // concatenating the segments per type @@ -290,10 +483,64 @@ int main(int argc, char *argv[]) { /* set total length to zero */ ttlen = tdlen = tblen = tzlen = 0; + + // then check start addresses + file = fp[0]; + if (file->align != 0) { + int er = 0; + if (tbase & file->align) { + fprintf(stderr, "Error: text segment start address ($%04x) " + "not aligned as required by first file (at %d bytes)\n", + tbase, file->align + 1); + er = 1; + } + if (dbase & file->align) { + fprintf(stderr, "Error: data segment start address ($%04x) " + "not aligned as required by first file (at %d bytes)\n", + dbase, file->align + 1); + er = 1; + } + if (bbase & file->align) { + fprintf(stderr, "Error: bss segment start address ($%04x) " + "not aligned as required (by first file at %d bytes)\n", + bbase, file->align + 1); + er = 1; + } + if (er) { + exit(1); + } + } + /* find new addresses for the files and read globals */ for(i=0;italign = 0; + file->dalign = 0; + file->balign = 0; + // filler only needed if align not zero ... + if (file->align) { + // ... and respective segment not empty + if (file->tlen) { + //file->talign = file->align + 1 - ((tbase + ttlen) & file->align); + file->talign = ( -((tbase + ttlen) & file->align) ) & file->align; + } + if (file->dlen) { + //file->dalign = file->align + 1 - ((dbase + tdlen) & file->align); + file->dalign = ( -((dbase + tdlen) & file->align) ) & file->align; + } + if (file->blen) { + //file->balign = file->align + 1 - ((bbase + tblen) & file->align); + file->balign = ( -((bbase + tblen) & file->align) ) & file->align; + } + } + + /* insert align fillers */ + ttlen += file->talign; + tdlen += file->dalign; + tblen += file->balign; + /* compute relocation differences */ file->tdiff = ((tbase + ttlen) - file->tbase); file->ddiff = ((dbase + tdlen) - file->dbase); @@ -308,14 +555,14 @@ printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n */ 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", + printf("Relocating file: %s [CPU %s]\n", file->fname, cpunames[((file->mode & FM_CPU2) >> 4) & 0x0f]); + printf(" text: align fill %04x, relocate from %04x to %04x (diff is %04x, length is %04x)\n", + file->talign, file->tbase, file->tbase + file->tdiff, file->tdiff, file->tlen); + printf(" data: align fill %04x, relocate from %04x to %04x (diff is %04x, length is %04x)\n", + file->dalign, file->dbase, file->dbase + file->ddiff, file->ddiff, file->dlen); + printf(" bss: align fill %04x, relocate from %04x to %04x (diff is %04x, length is %04x)\n", + file->balign, file->bbase, file->bbase + file->bdiff, file->bdiff, file->blen); + printf(" zero: relocate from %02x to %02x (diff is %02x, length is %02x)\n", file->zbase, file->zbase + file->zdiff, file->zdiff, file->zlen); } @@ -326,6 +573,31 @@ printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n tzlen += file->zlen; } + // validate various situations. + if (maxalign != 0) { + int er = 0; + if (tbase & maxalign) { + fprintf(stderr, "Error: text segment start address ($%04x) " + "not aligned as first required by file %s (at %d bytes)\n", + tbase, alignfname, maxalign + 1); + er = 1; + } + if (dbase & maxalign) { + fprintf(stderr, "Error: data segment start address ($%04x) " + "not aligned as first required by file %s (at %d bytes)\n", + dbase, alignfname, maxalign + 1); + er = 1; + } + if (bbase & maxalign) { + fprintf(stderr, "Error: bss segment start address ($%04x) " + "not aligned as first required (by file %s (at %d bytes)\n", + bbase, alignfname, maxalign + 1); + er = 1; + } + if (er) { + exit(1); + } + } // validate various situations. { int er = 0; @@ -471,7 +743,7 @@ printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n // // prepare header - hdr[ 6] = 0; hdr[ 7] = 0; + hdr[ 6] = trgmode & 255; hdr[ 7] = (trgmode>>8)& 255; hdr[ 8] = tbase & 255; hdr[ 9] = (tbase>>8) & 255; hdr[10] = ttlen & 255; hdr[11] = (ttlen >>8)& 255; hdr[12] = dbase & 255; hdr[13] = (dbase>>8) & 255; @@ -499,13 +771,22 @@ printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n } fputc(0,fd); + // align filler is NOP, just in case + memset(alignbuf, 0xea, sizeof(alignbuf)); + // write text segment for(i=0;italign) { + fwrite(alignbuf, 1, fp[i]->talign, fd); + } fwrite(fp[i]->buf + fp[i]->tpos, 1, fp[i]->tlen, fd); } // write data segment for(i=0;idalign) { + fwrite(alignbuf, 1, fp[i]->dalign, fd); + } fwrite(fp[i]->buf + fp[i]->dpos, 1, fp[i]->dlen, fd); } @@ -732,6 +1013,7 @@ file65 *load_file(char *fname) { struct stat fs; FILE *fp; int mode, hlen; + int align; size_t n; file=malloc(sizeof(file65)); @@ -743,7 +1025,10 @@ file65 *load_file(char *fname) { /*printf("load_file(%s)\n",fname);*/ file->fname=fname; - stat(fname, &fs); + if(stat(fname, &fs) < 0) { + perror("while opening file: stat"); + exit(1); + } file->fsize=fs.st_size; file->buf=malloc(file->fsize); if(!file->buf) { @@ -757,6 +1042,7 @@ file65 *load_file(char *fname) { fclose(fp); if((n>=file->fsize) && (!memcmp(file->buf, cmp, 5))) { mode=file->buf[7]*256+file->buf[6]; + file->mode = mode; if(mode & 0x2000) { fprintf(stderr,"file65: %s: 32 bit size not supported\n", fname); free(file->buf); free(file); file=NULL; @@ -766,14 +1052,38 @@ file65 *load_file(char *fname) { fname); free(file->buf); free(file); file=NULL; } else { + + align = mode & 3; + switch(align) { + case 0: + align = 0; + break; + case 1: + // word align + align = 1; + break; + case 2: + // long align + align = 3; + break; + case 3: + // page align + align = 255; + break; + } + file->align = align; + 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->talign= 0; file->dbase = file->buf[13]*256+file->buf[12]; file->dlen = file->buf[15]*256+file->buf[14]; + file->dalign= 0; file->bbase = file->buf[17]*256+file->buf[16]; file->blen = file->buf[19]*256+file->buf[18]; + file->balign= 0; file->zbase = file->buf[21]*256+file->buf[20]; file->zlen = file->buf[23]*256+file->buf[22]; diff --git a/xa/misc/reloc65.c b/xa/misc/reloc65.c index 7d4dec6..83dffa0 100644 --- a/xa/misc/reloc65.c +++ b/xa/misc/reloc65.c @@ -34,6 +34,21 @@ #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre Fachat." +/* o65 file format mode bits */ +#define FM_OBJ 0x1000 +#define FM_SIZE 0x2000 +#define FM_RELOC 0x4000 +#define FM_CPU 0x8000 + +#define FM_CPU2 0x00f0 + +#define FM_CPU2_6502 0x0000 +#define FM_CPU2_65C02 0x0010 +#define FM_CPU2_65SC02 0x0020 +#define FM_CPU2_65CE02 0x0030 +#define FM_CPU2_NMOS 0x0040 +#define FM_CPU2_65816E 0x0050 + typedef struct { char *fname; size_t fsize; @@ -74,13 +89,32 @@ void usage(FILE *fp) " -X extracts the file such that text and data\n" " segments are chained, i.e. possibly relocating\n" " the data segment to the end of the text segment\n" + " -C Set the o65 CPU flags in the output for the following CPUs:\n" + " 6502, 65SC02, 65C02, 65CE02, 65816, NMOS6502\n" + " (for details see the man page)\n" " -v verbose output\n" " --version output version information and exit\n" " --help display this help and exit\n"); } +const char *cpunames[16] = { + "6502", + "65C02", + "65SC02", + "65CE02", + "NMOS6502", + "65816", + NULL, NULL, + "6809", NULL, // 1000 - + "Z80", NULL, NULL, // 1010 - + "8086", // 1101 - + "80286", // 1110 - + NULL +}; + int main(int argc, char *argv[]) { int i = 1, mode, hlen; + int j; size_t n; FILE *fp; int tflag = 0, dflag = 0, bflag = 0, zflag = 0; @@ -89,13 +123,15 @@ int main(int argc, char *argv[]) { char *outfile = "a.o65"; int extract = 0; int verbose = 0; + int trgcpu = -1; // output file target CPU flag (-1 = do not change) + char *arg; // temporary argument pointer if (argc <= 1) { usage(stderr); exit(1); } - if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { + if (strstr(argv[1], "--help") || strstr(argv[1], "-?") || strstr(argv[1], "-h")) { usage(stdout); exit(0); } @@ -106,6 +142,7 @@ int main(int argc, char *argv[]) { } while(i %s\n",argv[i],outfile); @@ -187,12 +243,26 @@ int main(int argc, char *argv[]) { fclose(fp); if((n>=file.fsize) && (!memcmp(file.buf, cmp, 5))) { mode=file.buf[7]*256+file.buf[6]; - if(mode & 0x2000) { + if(mode & FM_SIZE) { fprintf(stderr,"reloc65: %s: 32 bit size not supported\n", argv[i]); } else - if(mode & 0x4000) { + if(mode & FM_RELOC) { fprintf(stderr,"reloc65: %s: pagewise relocation not supported\n", argv[i]); } else { + if (trgcpu >= 0) { + // change CPU flags + mode &= ~FM_CPU; + mode &= ~FM_CPU2; + mode |= (trgcpu << 4); + if (trgcpu == 5) { + // this trgcpu is actually 65816 in emulation mode + // unsure if we should do an own cmdline option + mode |= FM_CPU; // 65816 native + } + } + file.buf[6] = mode & 0xff; + file.buf[7] = (mode >> 8) & 0xff; + hlen = BUF+read_options(file.buf+BUF); file.tbase = file.buf[ 9]*256+file.buf[ 8]; diff --git a/xa/src/xa.c b/xa/src/xa.c index 4bc4d4f..08b7517 100644 --- a/xa/src/xa.c +++ b/xa/src/xa.c @@ -58,7 +58,7 @@ #define programname "xa" /* progversion now in xa.h */ #define authors "Written by Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser" -#define copyright "Copyright (C) 1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser." +#define copyright "Copyright (C) 1989-2024 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser." /* exported globals */ int ncmos, cmosfl, w65816, n65816; @@ -66,6 +66,7 @@ int ncmos, cmosfl, w65816, n65816; /* compatibility flags */ int masm = 0; /* MASM */ int ca65 = 0; /* CA65 */ +int collab = 0; /* allow colon relative labels even without ca65 mode */ int xa23 = 0; /* ^ and recursive comments, disable \ escape */ int ctypes = 0; /* C compatibility, like "0xab" types */ int nolink = 0; @@ -74,6 +75,7 @@ int romaddr = 0; int noglob = 0; int showblk = 0; int crossref = 0; +int mask = 0; int undefok = 0; // -R only accepts -Llabels; with -U all undef'd labels are ok in -R mode char altppchar; @@ -140,12 +142,20 @@ int main(int argc,char *argv[]) char old_o[MAXLINE]; tim1=time(NULL); - - ncmos=0; - n65816=0; + + // note: unfortunately we do no full distinction between 65C02 and 65816. + // The conflict is in the column 7 and column f opcodes, where the 65C02 + // has the BBR/BBS/SMB/RMB opcodes, but the 65816 has its own. + // Also, we potentially could support the 65SC02, which is the 65C02, but + // without the conflicting BBR/BBS/SMB/RMB opcodes. + // This, however, is a TODO for a later version. cmosfl=1; + //fmode = FM_CPU2_65C02; w65816=0; /* default: 6502 only */ + ncmos=0; // counter for CMOS opcodes used + n65816=0; // counter for 65816-specific opcodes used + altppchar = '#' ; /* i.e., NO alternate char */ if((tmpp = strrchr(argv[0],'/'))) { @@ -205,6 +215,15 @@ int main(int argc,char *argv[]) while(i0) fmode |= 0x8000; switch(align) { @@ -612,32 +648,6 @@ int h_length(void) { return 26+o_length(); } -#if 0 -/* write header for relocatable output format */ -int h_write(FILE *fp, int tbase, int tlen, int dbase, int dlen, - int bbase, int blen, int zbase, int zlen) { - - fputc(1, fp); /* version byte */ - fputc(0, fp); /* hi address 0 -> no C64 */ - fputc("o", fp); - fputc("6", fp); - fputc("5", fp); - fputc(0, fp); /* format version */ - fputw(mode, fp); /* file mode */ - fputw(tbase,fp); /* text base */ - fputw(tlen,fp); /* text length */ - fputw(dbase,fp); /* data base */ - fputw(dlen,fp); /* data length */ - fputw(bbase,fp); /* bss base */ - fputw(blen,fp); /* bss length */ - fputw(zbase,fp); /* zerop base */ - fputw(zlen,fp); /* zerop length */ - - o_write(fp); - - return 0; -} -#endif static int setfext(char *s, char *ext) { @@ -665,11 +675,6 @@ static int setfext(char *s, char *ext) return(0); } -/* -static char *tmp; -static unsigned long tmpz; -static unsigned long tmpe; -*/ static long ga_p1(void) { @@ -932,6 +937,8 @@ static void usage(int default816, FILE *fp) " (deprecated: prefer -XMASM)\n" " -Xcompatset set compatibility flags for other assemblers, known values are:\n" " C, MASM, CA65, XA23 (deprecated: for better 2.3 compatibility)\n" + " -a Allow ca65-style unnamed labels with colons, implies -XMASM\n" + " -k Allow carat to mask character value with 31/$1f\n" " -R start assembler in relocating mode\n" " -U allow all undefined labels in relocating mode\n"); fprintf(fp, @@ -1169,10 +1176,12 @@ static int xa_getline(char *s) we have ca65 compatibility, we ignore the colon */ // also check for ":+" and ":-" - if (((!startofline) && l[i]!='=' && l[i]!='+' && l[i]!='-') || !ca65 || comcom) { +//#error gotta get collab into this test + //if (((!startofline) && l[i]!='=' && l[i]!='+' && l[i]!='-') || !ca65 || comcom) { + if (((!startofline) && l[i]!='=' && l[i]!='+' && l[i]!='-') || !(ca65 || collab) || comcom) { /* but otherwise we check if it is in a comment and we have MASM or CA65 compatibility, then we ignore the colon as well */ - if(!comcom || !(masm || ca65)) { + if(!comcom || !(masm || ca65 || collab)) { /* we found a colon, so we keep the current line in memory but return the part before the colon, and next time the part after the colon, so we can parse C64 BASIC text assembler... */ diff --git a/xa/src/xa.h b/xa/src/xa.h index 52ac51e..76c48e5 100644 --- a/xa/src/xa.h +++ b/xa/src/xa.h @@ -23,11 +23,11 @@ #define progmajor "2" #define progminor "4" -#define progpatch "0" +#define progpatch "1" #define progversion progmajor "." progminor "." progpatch extern int ncmos, cmosfl, w65816, n65816; -extern int masm, ca65, xa23, nolink, undefok; +extern int masm, ca65, xa23, nolink, undefok, collab, mask; extern int noglob; extern int showblk; extern int relmode; diff --git a/xa/src/xad.h b/xa/src/xad.h index 2c2a64c..244241f 100644 --- a/xa/src/xad.h +++ b/xa/src/xad.h @@ -39,4 +39,6 @@ t[i++] = f & 255; \ } while (0) +#define wval_len 5 /* number of bytes stored in wval() call */ + #endif /* __XA65_XAD_H__ */ diff --git a/xa/src/xah.h b/xa/src/xah.h index a126ed2..1d3321e 100644 --- a/xa/src/xah.h +++ b/xa/src/xah.h @@ -192,11 +192,22 @@ typedef struct { #define A_LONG 0xc000 +/* o65 file format mode bits */ #define FM_OBJ 0x1000 #define FM_SIZE 0x2000 #define FM_RELOC 0x4000 #define FM_CPU 0x8000 +#define FM_CPU2 0x00f0 + +#define FM_CPU2_6502 0x0000 +#define FM_CPU2_65C02 0x0010 +#define FM_CPU2_65SC02 0x0020 +#define FM_CPU2_65CE02 0x0030 +#define FM_CPU2_NMOS 0x0040 +#define FM_CPU2_65816E 0x0050 + +/* segment definitions */ #define SEG_ABS 0 #define SEG_UNDEF 1 #define SEG_TEXT 2 diff --git a/xa/src/xal.c b/xa/src/xal.c index 1781112..4965f7c 100644 --- a/xa/src/xal.c +++ b/xa/src/xal.c @@ -278,8 +278,8 @@ int l_def(char *s, int *l, int *x, int *f) cll_clear(); } - if((!isalpha(s[i])) && (s[i]!='_') && !(ca65 && ((cll_fl == UNNAMED) || isdigit(s[i])) ) ) { - //printf("SYNTAX cll_fl=%d, i=%d, s[i]=%02x (%c)\n", cll_fl, i, s[i], s[i]); + if((!isalpha(s[i])) && (s[i]!='_') && !((ca65 || collab) && ((cll_fl == UNNAMED) || isdigit(s[i])) ) ) { + //printf("SYNTAX ca65=%d collab=%d cll_fl=%d, i=%d, s[i]=%02x (%c)\n", ca65, collab, cll_fl, i, s[i], s[i]); er=E_SYNTAX; } else { @@ -653,7 +653,7 @@ int ll_search(char *s, int *n, xalabel_t cll_fl) /* search Label in Tab { for (k=0;(kn[k]==s[k]);k++); - if (cll_fl == CHEAP) { + if ( (j == k) && cll_fl == CHEAP) { if (ltp->blk == cll_getcur()) { er=E_OK; break; diff --git a/xa/src/xat.c b/xa/src/xat.c index 4a71e11..7f1d77e 100644 --- a/xa/src/xat.c +++ b/xa/src/xat.c @@ -834,12 +834,12 @@ printf("reloc: er=%d, l=%d, segment=%d, pc[%d]=%04x, pc[abs(%d)]=%04x, pc[text(% t[0]=Kdsb; i=1; bl=tmp=(tmp - (pc[segment] & (tmp-1))) & (tmp-1); - wval(i,tmp, 0); + wval(i,tmp, 0); // 5 byte t[i++]=','; tmp2= 0xea; - wval(i,tmp2, 0); /* nop opcode */ + wval(i,tmp2, 0); /* nop opcode, another 5 byte */ t[i++]=T_END; - *ll=9; + *ll=wval_len * 2 + 3; //13; //9; er=E_OKDEF; } else { *ll=0; /* ignore if aligned right */ @@ -1324,7 +1324,7 @@ int t_p2(signed char *t, int *ll, int fl, int *al) } else { er = E_SYNTAX; } - /* get filename. + /* get error string. the tokenizer can either see it as a multichar string ... */ if (!er) { int k; @@ -1344,7 +1344,7 @@ int t_p2(signed char *t, int *ll, int fl, int *al) have been caught by the above) */ } else if(!(er=a_term(t+i,&c,&l,pc[segment],&afl,&label,1))) { - if (!result) fprintf(stderr, "%c", c); + if (!result) fprintf(stderr, "Assertion failed: %c", c); i += l; } } @@ -1838,7 +1838,10 @@ fprintf(stderr, "Kdsb E_DSB %i\n", j); if(tolower(t[inp])=='s') sy=12; else + if(tolower(t[inp])=='x') sy=5; + else + er=E_SYNTAX; } else er=E_SYNTAX; } @@ -1965,7 +1968,9 @@ fprintf(stderr, "byte length is now %d, am=%d, er=%d\n", bl, am, er); } else { n65816++; if(!w65816) { -fprintf(stderr,"n=%d, am=%d\n", n, am); +#ifdef DEBUG_AM +fprintf(stderr,"not 65816 n=%d, am=%d\n", n, am); +#endif er=E_65816; } } @@ -2335,7 +2340,7 @@ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk, } 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)) + if(isalpha(s[p]) || s[p]=='_' || (s[p]==':' && collab) || ((s[p]==':' || s[p]=='@') && ca65)) { int p2 = 0; @@ -2770,7 +2775,7 @@ fprintf(stderr, "tg_asc token = %i\n", n); 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 */ + } else if(ca65 || (!xa23 && !mask) || 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]; diff --git a/xa/tests/README b/xa/tests/README index ad2405d..b79003f 100644 --- a/xa/tests/README +++ b/xa/tests/README @@ -44,6 +44,7 @@ relmode/ tests concerning switches between segments and absolute mode mvnmvp/ Test MVN MVP unusual addressing mode ('816) dos51/ Regression test, label scoping, "real world code" cpktest/ Regression test, label listing, "real world code" +usb65/ Unusual macro and scoping, "real world code" listing/ Test of listing feature op816/ Regression test for '816 opcodes (thanks Alessandro Gatti) branch/ Branch range test diff --git a/xa/tests/align/Makefile b/xa/tests/align/Makefile new file mode 100644 index 0000000..87055a6 --- /dev/null +++ b/xa/tests/align/Makefile @@ -0,0 +1,100 @@ + +XA=../../xa + +default: all +all: t01 t02 t03 t11 t12 t13 t21 t22 t23 t31 t32 t33 t41 t42 t43 + +# BSD only has suffix rules + +.SUFFIXES: .o65 .hex .a65 + +#%.o65: %.s +.a65.o65: + ${XA} -R -c -o $@ $? + +#%.hex: %.o65 +.o65.hex: + ../hextool $? > $@ + +############################################### +# text segment correctly aligned + +t01: t01.o65 + ../hextool -cmp=$@.ok $@.o65 + +t02: t02.o65 + ../hextool -cmp=$@.ok $@.o65 + +t03: t03.o65 + ../hextool -cmp=$@.ok $@.o65 + +############################################### +# data segment correctly aligned + +t11: t11.o65 + ../hextool -cmp=$@.ok $@.o65 + +t12: t12.o65 + ../hextool -cmp=$@.ok $@.o65 + +t13: t13.o65 + ../hextool -cmp=$@.ok $@.o65 + +############################################### +# text segment incorrectly aligned + +t21: t01.a65 + ${XA} -R -c -bt 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t22: t02.a65 + ${XA} -R -c -bt 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t23: t03.a65 + ${XA} -R -c -bt 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +############################################### +# text segment correctly aligned, but data segment not (even if empty) + +t31: t01.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t32: t02.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t33: t03.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +############################################### +# data segment incorrectly aligned + +t41: t11.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t42: t12.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + +t43: t13.a65 + ${XA} -R -c -bd 1025 -o $@.o65 $? 2> $@.msg + ../hextool -cmp=$@.mok $@.msg + ../hextool -cmp=$@.ok $@.o65 + + +clean: + rm -f *.o65 *.hex + diff --git a/xa/tests/align/t01.a65 b/xa/tests/align/t01.a65 new file mode 100644 index 0000000..0cb893e --- /dev/null +++ b/xa/tests/align/t01.a65 @@ -0,0 +1,10 @@ + + .text + + tay + + .align 2 + + tay + + diff --git a/xa/tests/align/t01.ok b/xa/tests/align/t01.ok new file mode 100644 index 0000000000000000000000000000000000000000..d985cf3cb252043cddf865abd44add735212f8d1 GIT binary patch literal 36 jcmZQ%$Tu@(U=&~wU}j)oVPIfzfKWizidQRuBoF`qH?#wS literal 0 HcmV?d00001 diff --git a/xa/tests/align/t02.a65 b/xa/tests/align/t02.a65 new file mode 100644 index 0000000..21605cc --- /dev/null +++ b/xa/tests/align/t02.a65 @@ -0,0 +1,10 @@ + + .text + + tay + + .align 4 + + tay + + diff --git a/xa/tests/align/t02.ok b/xa/tests/align/t02.ok new file mode 100644 index 0000000000000000000000000000000000000000..2838a66af02092f17f8d9d9971aca6fa1e2daf8d GIT binary patch literal 38 lcmZQ%$Tu@(U=m;uU}a!nVPIfzfKWizidU~*tpL(M002!&1z7+9 literal 0 HcmV?d00001 diff --git a/xa/tests/align/t03.a65 b/xa/tests/align/t03.a65 new file mode 100644 index 0000000..69e4fe1 --- /dev/null +++ b/xa/tests/align/t03.a65 @@ -0,0 +1,10 @@ + + .text + + tay + + .align 256 + + tay + + diff --git a/xa/tests/align/t03.ok b/xa/tests/align/t03.ok new file mode 100644 index 0000000000000000000000000000000000000000..6eeab056e406901dd6cec958fc50b245c9a65b83 GIT binary patch literal 290 ncmZQ%$Tu@(U>0ByU}R)qVPIfzU;tA<){0jn8>|3^0T2KH50LAx literal 0 HcmV?d00001 diff --git a/xa/tests/align/t11.a65 b/xa/tests/align/t11.a65 new file mode 100644 index 0000000..81ecca1 --- /dev/null +++ b/xa/tests/align/t11.a65 @@ -0,0 +1,10 @@ + + .data + + tay + + .align 2 + + tay + + diff --git a/xa/tests/align/t11.ok b/xa/tests/align/t11.ok new file mode 100644 index 0000000000000000000000000000000000000000..2e3002e781e048393c6c91d211d08739ea7ef2c3 GIT binary patch literal 36 jcmZQ%$Tu@(U=&~wU|?WiVP;@(08&6E5UhB$0>S_QH>d-G literal 0 HcmV?d00001 diff --git a/xa/tests/align/t12.a65 b/xa/tests/align/t12.a65 new file mode 100644 index 0000000..2c9b98e --- /dev/null +++ b/xa/tests/align/t12.a65 @@ -0,0 +1,10 @@ + + .data + + tay + + .align 4 + + tay + + diff --git a/xa/tests/align/t12.ok b/xa/tests/align/t12.ok new file mode 100644 index 0000000000000000000000000000000000000000..51b7e8036a16b0bb5646aafbf3f5f852b0e9c44e GIT binary patch literal 38 lcmZQ%$Tu@(U=m;uU|?WiVP#-&08&6E5UhCh>eUJe697#%1z7+9 literal 0 HcmV?d00001 diff --git a/xa/tests/align/t13.a65 b/xa/tests/align/t13.a65 new file mode 100644 index 0000000..fc4a388 --- /dev/null +++ b/xa/tests/align/t13.a65 @@ -0,0 +1,10 @@ + + .data + + tay + + .align 256 + + tay + + diff --git a/xa/tests/align/t13.ok b/xa/tests/align/t13.ok new file mode 100644 index 0000000000000000000000000000000000000000..01f08622dc4aaa23156966a14210f412660e4053 GIT binary patch literal 290 mcmZQ%$Tu@(U>0ByU|?WiVPs@*08&6E5UhALvcU>SFaQ7#i0iKa literal 0 HcmV?d00001 diff --git a/xa/tests/align/t21.mok b/xa/tests/align/t21.mok new file mode 100644 index 0000000..7d5c4f8 --- /dev/null +++ b/xa/tests/align/t21.mok @@ -0,0 +1 @@ +Warning: text segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t21.msg b/xa/tests/align/t21.msg new file mode 100644 index 0000000..7d5c4f8 --- /dev/null +++ b/xa/tests/align/t21.msg @@ -0,0 +1 @@ +Warning: text segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t21.ok b/xa/tests/align/t21.ok new file mode 100644 index 0000000000000000000000000000000000000000..8eb258714fdb59fc9e53c0cbfdc2c915753614d6 GIT binary patch literal 35 hcmZQ%$Tu@(U=(0vVParlVPIfzfKWiziWNWt2mmcU0*n9v literal 0 HcmV?d00001 diff --git a/xa/tests/align/t22.mok b/xa/tests/align/t22.mok new file mode 100644 index 0000000..d00c961 --- /dev/null +++ b/xa/tests/align/t22.mok @@ -0,0 +1 @@ +Warning: text segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t22.msg b/xa/tests/align/t22.msg new file mode 100644 index 0000000..d00c961 --- /dev/null +++ b/xa/tests/align/t22.msg @@ -0,0 +1 @@ +Warning: text segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t22.ok b/xa/tests/align/t22.ok new file mode 100644 index 0000000000000000000000000000000000000000..5cc8ec6c5ab9d6c0dafe7ac8fb459befd87b1015 GIT binary patch literal 37 icmZQ%$Tu@(U=m0s;U)0CxVPIrnVPIfzU;tA<){0jn8ms^Y0T2KH5ccZ1 literal 0 HcmV?d00001 diff --git a/xa/tests/align/t31.mok b/xa/tests/align/t31.mok new file mode 100644 index 0000000..27b0e24 --- /dev/null +++ b/xa/tests/align/t31.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t31.msg b/xa/tests/align/t31.msg new file mode 100644 index 0000000..27b0e24 --- /dev/null +++ b/xa/tests/align/t31.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t31.ok b/xa/tests/align/t31.ok new file mode 100644 index 0000000000000000000000000000000000000000..8131eb027f94964eab833fd2139dcd8bd066b12b GIT binary patch literal 36 jcmZQ%$Tu@(U=&~wU}j)sVPIfzU|;}IK(OM~3J3!LH_QWr literal 0 HcmV?d00001 diff --git a/xa/tests/align/t32.mok b/xa/tests/align/t32.mok new file mode 100644 index 0000000..d91c7a2 --- /dev/null +++ b/xa/tests/align/t32.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t32.msg b/xa/tests/align/t32.msg new file mode 100644 index 0000000..d91c7a2 --- /dev/null +++ b/xa/tests/align/t32.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t32.ok b/xa/tests/align/t32.ok new file mode 100644 index 0000000000000000000000000000000000000000..05890a991c8bfa1fd7fdbcc7805e6c8c8da84d94 GIT binary patch literal 38 lcmZQ%$Tu@(U=m;uU}a!rVPIfzU|;}IK(OM~t5+)^OaM(}1zG?A literal 0 HcmV?d00001 diff --git a/xa/tests/align/t33.mok b/xa/tests/align/t33.mok new file mode 100644 index 0000000..0ea3c00 --- /dev/null +++ b/xa/tests/align/t33.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 256! diff --git a/xa/tests/align/t33.msg b/xa/tests/align/t33.msg new file mode 100644 index 0000000..0ea3c00 --- /dev/null +++ b/xa/tests/align/t33.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 256! diff --git a/xa/tests/align/t33.ok b/xa/tests/align/t33.ok new file mode 100644 index 0000000000000000000000000000000000000000..ededf6677ed7ee172e875d59ff78dd88de6f7ca7 GIT binary patch literal 290 mcmZQ%$Tu@(U>0ByU}R)uVPIfzU|;}IK(OM~$ObDQ!2kddrt7c( literal 0 HcmV?d00001 diff --git a/xa/tests/align/t41.mok b/xa/tests/align/t41.mok new file mode 100644 index 0000000..27b0e24 --- /dev/null +++ b/xa/tests/align/t41.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t41.msg b/xa/tests/align/t41.msg new file mode 100644 index 0000000..27b0e24 --- /dev/null +++ b/xa/tests/align/t41.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 2! diff --git a/xa/tests/align/t41.ok b/xa/tests/align/t41.ok new file mode 100644 index 0000000000000000000000000000000000000000..b834fbc1bdc60778ca4613afe6f2bb8ae100c059 GIT binary patch literal 35 icmZQ%$Tu@(U=&~wU|?WmVPar#U|?Wj0D~1PAT$6jY66%5 literal 0 HcmV?d00001 diff --git a/xa/tests/align/t42.mok b/xa/tests/align/t42.mok new file mode 100644 index 0000000..d91c7a2 --- /dev/null +++ b/xa/tests/align/t42.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t42.msg b/xa/tests/align/t42.msg new file mode 100644 index 0000000..d91c7a2 --- /dev/null +++ b/xa/tests/align/t42.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 4! diff --git a/xa/tests/align/t42.ok b/xa/tests/align/t42.ok new file mode 100644 index 0000000000000000000000000000000000000000..bdd3cc0baa2b365c6027ec50ed4f4c565968dacb GIT binary patch literal 37 kcmZQ%$Tu@(U=m;uU|?WmVPRl!U|;}}Ah6=qs}&Fy074-IZvX%Q literal 0 HcmV?d00001 diff --git a/xa/tests/align/t43.mok b/xa/tests/align/t43.mok new file mode 100644 index 0000000..0ea3c00 --- /dev/null +++ b/xa/tests/align/t43.mok @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 256! diff --git a/xa/tests/align/t43.msg b/xa/tests/align/t43.msg new file mode 100644 index 0000000..0ea3c00 --- /dev/null +++ b/xa/tests/align/t43.msg @@ -0,0 +1 @@ +Warning: data segment ($0401) start address doesn't align to 256! diff --git a/xa/tests/align/t43.ok b/xa/tests/align/t43.ok new file mode 100644 index 0000000000000000000000000000000000000000..1384ef4cf997462fa72ff48b5f14a5108746b5bb GIT binary patch literal 289 mcmZQ%$Tu@(U>0ByU|?WmVPIr%U|?Wj0D~2;Ml@If2?YQi4(i1K literal 0 HcmV?d00001 diff --git a/xa/tests/ca65/Makefile b/xa/tests/ca65/Makefile index bbe4fa6..cb0fef0 100644 --- a/xa/tests/ca65/Makefile +++ b/xa/tests/ca65/Makefile @@ -6,7 +6,7 @@ XA=../../xa CA65=ca65 LD65=ld65 -OBJS=unnamed1 unnamed2 escape2 +OBJS=unnamed1 unnamed2 escape1 escape2 lll # escape1 test only relevant if xa23 mode is on #tests: unnamed1 unnamed2 escape1 escape2 clean @@ -18,15 +18,23 @@ unnamed1: unnamed1.a65 #${CA65} unnamed1.a65; ${LD65} -t none -o unnamed1.ca65 unnamed1.o; rm unnamed1.o ${XA} -XCA65 unnamed1.a65 -o $@ ../hextool -cmp=unnamed1.ca65 < $@ + ${XA} -a unnamed1.a65 -o $@ + ../hextool -cmp=unnamed1.ca65 < $@ unnamed2: unnamed2.a65 #${CA65} unnamed2.a65; ${LD65} -t none -o unnamed2.ca65 unnamed2.o; rm unnamed2.o ${XA} -XCA65 unnamed2.a65 -o $@ 2>a.err || true ../hextool -cmp=unnamed2.ca65 < $@ + ${XA} -a unnamed2.a65 -o $@ 2>a.err || true + ../hextool -cmp=unnamed2.ca65 < $@ # add -XXA23 to actually test this escape1: escape1.a65 - ${XA} escape1.a65 -o $@ + # shouldn't work by default + ${XA} escape1.a65 -o $@ || exit 0 && exit 1 + ${XA} -XXA23 escape1.a65 -o $@ + ../hextool -cmp=escape1.out < $@ + ${XA} -k escape1.a65 -o $@ ../hextool -cmp=escape1.out < $@ escape2: escape2.a65 @@ -34,6 +42,15 @@ escape2: escape2.a65 ${XA} -XCA65 escape2.a65 -o $@ 2>a.err || true ../hextool -cmp=escape2.ca65 < $@ +lll: lll.a65 + # shouldn't work + ${XA} lll.a65 -o $@ || exit 0 && exit 1 + ${XA} -a lll.a65 -o $@ || exit 0 && exit 1 + ${XA} -w lll.a65 -o $@ || exit 0 && exit 1 + # should work + ${XA} -XCA65 lll.a65 -o $@ + ../hextool -cmp=lll.out < $@ + clean: rm -f *.err a.o65 $(OBJS) diff --git a/xa/tests/ca65/escape1.a65 b/xa/tests/ca65/escape1.a65 index 74e8c09..492cf84 100644 --- a/xa/tests/ca65/escape1.a65 +++ b/xa/tests/ca65/escape1.a65 @@ -2,5 +2,6 @@ *=$1000 lda #"^^" + .asc "^m^j" diff --git a/xa/tests/ca65/escape1.out b/xa/tests/ca65/escape1.out index 8943227..6ca240c 100644 --- a/xa/tests/ca65/escape1.out +++ b/xa/tests/ca65/escape1.out @@ -1 +1 @@ -©^ \ No newline at end of file +©^ diff --git a/xa/tests/ca65/lll.a65 b/xa/tests/ca65/lll.a65 new file mode 100644 index 0000000..3030975 --- /dev/null +++ b/xa/tests/ca65/lll.a65 @@ -0,0 +1,28 @@ +; As extracted from https://codebase64.org/doku.php?id=base:256_bytes_tune_player + * = $326 + +@musicdata: +; errs +@Voc0start: + .byte $00 + .byte <(@Voc0komp-@musicdata) +; errs +@Voc1start: + .byte $40 + .byte <(@Voc1melody-@musicdata) +; errs +@Voc2start: + ;- + ;- + .byte $50 +@Voc2loop: + .byte $60 + .byte <(@Voc2loop-@musicdata) +; errs +@Voc0komp: + .byte $10 + .byte <(@Voc0start-@musicdata) +@Voc1melody: + .byte $20 + .byte <(@Voc1start-@musicdata) + diff --git a/xa/tests/ca65/lll.out b/xa/tests/ca65/lll.out new file mode 100644 index 0000000000000000000000000000000000000000..ff67b7e7d8d51dbe147214c80834d736bfad4139 GIT binary patch literal 11 ScmZQzci;?2U=?6cU;+RK + +clean: + rm -f *.o65 + rm -f test1 + diff --git a/xa/tests/cll/test1.a65 b/xa/tests/cll/test1.a65 new file mode 100644 index 0000000..10ff933 --- /dev/null +++ b/xa/tests/cll/test1.a65 @@ -0,0 +1,30 @@ +; As extracted from https://codebase64.org/doku.php?id=base:256_bytes_tune_player +.org $326 + +foo: + +@musicdata: +; errs +@Voc0start: +.byte $00 +; .byte <(@Voc0komp-@musicdata) +; errs +@Voc1start: +.byte $40 +.byte <(@Voc1melody-@musicdata) +; errs +@Voc2start: +;- +;- +.byte $50 +@Voc2loop: +.byte $60 +.byte <(@Voc2loop-@musicdata) +; errs +@Voc0komp: +.byte $10 +.byte <(@Voc0start-@musicdata) +@Voc1melody: +.byte $20 +.byte <(@Voc1start-@musicdata) + diff --git a/xa/tests/comcom/816com.asm b/xa/tests/comcom/816com.asm new file mode 100644 index 0000000..56fd438 --- /dev/null +++ b/xa/tests/comcom/816com.asm @@ -0,0 +1,6 @@ +: + lda @$123456 + beq :+ + bne :- +: + sta @$654321 diff --git a/xa/tests/comcom/816com.ok b/xa/tests/comcom/816com.ok new file mode 100644 index 0000000..80ea72f --- /dev/null +++ b/xa/tests/comcom/816com.ok @@ -0,0 +1 @@ +¯V4ðÐø!Ce \ No newline at end of file diff --git a/xa/tests/comcom/Makefile b/xa/tests/comcom/Makefile index 1442e0a..6723b37 100644 --- a/xa/tests/comcom/Makefile +++ b/xa/tests/comcom/Makefile @@ -1,13 +1,21 @@ default: # this should fail. ../../xa scomcom.asm || exit 0 && exit 1 + ../../xa -a 816com.asm || exit 0 && exit 1 + ../../xa -w 816com.asm || exit 0 && exit 1 # it did fail. these should now all succeed. - ../../xa -M scomcom.asm + ../../xa -XMASM scomcom.asm + ../hextool -cmp=scomcomm.ok < a.o65 + ../../xa -a scomcom.asm ../hextool -cmp=scomcomm.ok < a.o65 ../../xa comcom.asm ../hextool -cmp=comcom.ok < a.o65 - ../../xa -M comcom.asm + ../../xa -XMASM comcom.asm ../hextool -cmp=comcomm.ok < a.o65 + ../../xa -a comcom.asm + ../hextool -cmp=comcomm.ok < a.o65 + ../../xa -a -w 816com.asm + ../hextool -cmp=816com.ok < a.o65 clean: rm -f a.o65 diff --git a/xa/tests/masmcom/Makefile b/xa/tests/masmcom/Makefile index 6e85604..98e2021 100644 --- a/xa/tests/masmcom/Makefile +++ b/xa/tests/masmcom/Makefile @@ -1,6 +1,6 @@ default: # compile with masm mode on. - ../../xa -M -o test.o test.s + ../../xa -XMASM -o test.o test.s ../hextool -cmp=okmasm < test.o # compile without ../../xa -o test.o test.s diff --git a/xa/tests/mode/Makefile b/xa/tests/mode/Makefile new file mode 100644 index 0000000..284fbc9 --- /dev/null +++ b/xa/tests/mode/Makefile @@ -0,0 +1,149 @@ + +FILES=at1.o65 at2.o65 at4.o65 at256.o65 ad1.o65 ad2.o65 ad4.o65 ad256.o65 ab1.o65 ab2.o65 ab4.o65 ab256.o65 + +VERBOSE= +#VERBOSE=-v + +XA=../../xa +LDO=../../ldo65 +RELOC=../../reloc65 +FILE=../../file65 + +all: test1.o65 test2.o65 test3.o65 test4 cpus relocsame overwrite linkup1.tmp linkup2 + +.SUFFIXES: .a65 .o65 + +.a65.o65: + ${XA} -R -o $@ $? + +# test with files in order of increasing align +test1.o65: ${FILES} + ${LDO} ${VERBOSE} -o $@ ${FILES} + ../hextool -cmp=$@.ok $@ + +# test with files in order of decreasing align +test2.o65: ${FILES} + ${LDO} ${VERBOSE} -o $@ ab256.o65 ab4.o65 ab2.o65 ab1.o65 ad256.o65 ad4.o65 ad2.o65 ad1.o65 at256.o65 at4.o65 at2.o65 at1.o65 + ../hextool -cmp=$@.ok $@ + +# test with files in order of increasing align, not starting at align=1 +test3.o65: ${FILES} + ${LDO} ${VERBOSE} -o $@ ab2.o65 at2.o65 ad2.o65 ab4.o65 at4.o65 ad4.o65 ad256.o65 at256.o65 ab256.o65 + ../hextool -cmp=$@.ok $@ + +# test with files in order of increasing align, with non-aligned segment addresses +test4: ${FILES} + ${LDO} ${VERBOSE} -bt 1025 -bd 1025 -o $@.o65 ab2.o65 at2.o65 ad2.o65 ab4.o65 at4.o65 ad4.o65 ad256.o65 at256.o65 ab256.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -bt 1026 -bd 1026 -o $@.o65 ab2.o65 at2.o65 ad2.o65 ab4.o65 at4.o65 ad4.o65 ad256.o65 at256.o65 ab256.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -bt 1027 -bd 1027 -o $@.o65 ab2.o65 at2.o65 ad2.o65 ab4.o65 at4.o65 ad4.o65 ad256.o65 at256.o65 ab256.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -bt 1028 -bd 1028 -o $@.o65 ab2.o65 at2.o65 ad2.o65 ab4.o65 at4.o65 ad4.o65 ad256.o65 at256.o65 ab256.o65 || exit 0 && exit 1 + +#c6502: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C 6502 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +c6502: c6502-at2.o65 c6502-ad4.o65 +c6502-at2.o65: at2.o65 + ${RELOC} -C 6502 -o $@ $? + ../hextool -cmp=$@.ok $@ +c6502-ad4.o65: ad4.o65 + ${RELOC} -C 6502 -o $@ $? + ../hextool -cmp=$@.ok $@ + +#c65c02: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C 65C02 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +c65c02: c65c02-at2.o65 c65c02-ad4.o65 +c65c02-at2.o65: at2.o65 + ${RELOC} -C 65C02 -o $@ $? + ../hextool -cmp=$@.ok $@ +c65c02-ad4.o65: ad4.o65 + ${RELOC} -C 65C02 -o $@ $? + ../hextool -cmp=$@.ok $@ + +#c65ce02: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C 65CE02 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +c65ce02: c65ce02-at2.o65 c65ce02-ad4.o65 +c65ce02-at2.o65: at2.o65 + ${RELOC} -C 65CE02 -o $@ $? + ../hextool -cmp=$@.ok $@ +c65ce02-ad4.o65: ad4.o65 + ${RELOC} -C 65CE02 -o $@ $? + ../hextool -cmp=$@.ok $@ + +#c65sc02: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C 65SC02 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +c65sc02: c65sc02-at2.o65 c65sc02-ad4.o65 +c65sc02-at2.o65: at2.o65 + ${RELOC} -C 65SC02 -o $@ $? + ../hextool -cmp=$@.ok $@ +c65sc02-ad4.o65: ad4.o65 + ${RELOC} -C 65SC02 -o $@ $? + ../hextool -cmp=$@.ok $@ + +#c65816: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C 65816 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +c65816: c65816-at2.o65 c65816-ad4.o65 +c65816-at2.o65: at2.o65 + ${RELOC} -C 65816 -o $@ $? + ../hextool -cmp=$@.ok $@ +c65816-ad4.o65: ad4.o65 + ${RELOC} -C 65816 -o $@ $? + ../hextool -cmp=$@.ok $@ + +#n6502: at2.o65 ad4.o65 +# for i in $^; do ${RELOC} -C NMOS6502 -o $@-$$i $$i; done +# cmp $@-at2.o65 $@-at2.ok +# cmp $@-ad4.o65 $@-ad4.ok +n6502: n6502-at2.o65 n6502-ad4.o65 +n6502-at2.o65: at2.o65 + ${RELOC} -C NMOS6502 -o $@ $? + ../hextool -cmp=$@.ok $@ +n6502-ad4.o65: ad4.o65 + ${RELOC} -C NMOS6502 -o $@ $? + ../hextool -cmp=$@.ok $@ + +cpus: c65816 c6502 n6502 c65sc02 c65c02 c65ce02 + # prereq for the following + +relocsame: cpus + ${RELOC} -o $@.o65 c65816-ad4.o65 + ../hextool -cmp=c65816-ad4.o65 $@.o65 + ${RELOC} -o $@.o65 c65sc02-at2.o65 + ../hextool -cmp=c65sc02-at2.o65 $@.o65 + +overwrite: cpus + # overwrite 65816 with nmos 6502 + ${RELOC} -C NMOS6502 -o $@-1.o65 c65816-at2.o65 + ../hextool -cmp=n6502-at2.o65 $@-1.o65 + # overwrite 65sc02 with 65c02 + ${RELOC} -C 65C02 -o $@-2.o65 c65sc02-ad4.o65 + ../hextool -cmp=c65c02-ad4.o65 $@-2.o65 + +linkup1.tmp: cpus + ${LDO} -v -o $@.tmp c6502-ad4.o65 c65c02-at2.o65 c65sc02-ad4.o65 + ${FILE} $@.tmp > $@ + ../hextool -cmp=$@.ok $@ + +linkup2: + # incompatible links + ${LDO} ${VERBOSE} -o $@.o65 c6502-ad4.o65 c65c02-at2.o65 c65816-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 c6502-ad4.o65 c65ce02-at2.o65 c65816-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 c6502-ad4.o65 c65816-at2.o65 c65c02-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 c6502-ad4.o65 c65816-at2.o65 c65ce02-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 c65816-at2.o65 c65ce02-ad4.o65 c65c02-at2.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 n6502-at2.o65 c65ce02-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 n6502-at2.o65 c65c02-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 n6502-at2.o65 c65sc02-ad4.o65 || exit 0 && exit 1 + ${LDO} ${VERBOSE} -o $@.o65 n6502-at2.o65 c65816-ad4.o65 || exit 0 && exit 1 + +clean: + rm -f *.o65 *.tmp + diff --git a/xa/tests/mode/ab1.a65 b/xa/tests/mode/ab1.a65 new file mode 100644 index 0000000..c6813b6 --- /dev/null +++ b/xa/tests/mode/ab1.a65 @@ -0,0 +1,6 @@ + + .align 1 + + .bss + .byt 0 + diff --git a/xa/tests/mode/ab2.a65 b/xa/tests/mode/ab2.a65 new file mode 100644 index 0000000..f37a452 --- /dev/null +++ b/xa/tests/mode/ab2.a65 @@ -0,0 +1,6 @@ + + .align 2 + + .bss + .byt 0 + diff --git a/xa/tests/mode/ab256.a65 b/xa/tests/mode/ab256.a65 new file mode 100644 index 0000000..826ef49 --- /dev/null +++ b/xa/tests/mode/ab256.a65 @@ -0,0 +1,6 @@ + + .align 256 + + .bss + .byt 0 + diff --git a/xa/tests/mode/ab4.a65 b/xa/tests/mode/ab4.a65 new file mode 100644 index 0000000..a25eab6 --- /dev/null +++ b/xa/tests/mode/ab4.a65 @@ -0,0 +1,6 @@ + + .align 4 + + .bss + .byt 0 + diff --git a/xa/tests/mode/ad1.a65 b/xa/tests/mode/ad1.a65 new file mode 100644 index 0000000..6df4a2d --- /dev/null +++ b/xa/tests/mode/ad1.a65 @@ -0,0 +1,6 @@ + + .align 1 + + .data + .byt 0 + diff --git a/xa/tests/mode/ad2.a65 b/xa/tests/mode/ad2.a65 new file mode 100644 index 0000000..3b64eb2 --- /dev/null +++ b/xa/tests/mode/ad2.a65 @@ -0,0 +1,6 @@ + + .align 2 + + .data + .byt 0 + diff --git a/xa/tests/mode/ad256.a65 b/xa/tests/mode/ad256.a65 new file mode 100644 index 0000000..8942365 --- /dev/null +++ b/xa/tests/mode/ad256.a65 @@ -0,0 +1,6 @@ + + .align 256 + + .data + .byt 0 + diff --git a/xa/tests/mode/ad4.a65 b/xa/tests/mode/ad4.a65 new file mode 100644 index 0000000..e684f4c --- /dev/null +++ b/xa/tests/mode/ad4.a65 @@ -0,0 +1,6 @@ + + .align 4 + + .data + .byt 0 + diff --git a/xa/tests/mode/at1.a65 b/xa/tests/mode/at1.a65 new file mode 100644 index 0000000..844ae6e --- /dev/null +++ b/xa/tests/mode/at1.a65 @@ -0,0 +1,4 @@ + + .align 1 + iny + diff --git a/xa/tests/mode/at2.a65 b/xa/tests/mode/at2.a65 new file mode 100644 index 0000000..5c68441 --- /dev/null +++ b/xa/tests/mode/at2.a65 @@ -0,0 +1,4 @@ + + .align 2 + iny + diff --git a/xa/tests/mode/at256.a65 b/xa/tests/mode/at256.a65 new file mode 100644 index 0000000..ee5839d --- /dev/null +++ b/xa/tests/mode/at256.a65 @@ -0,0 +1,4 @@ + + .align 256 + iny + diff --git a/xa/tests/mode/at4.a65 b/xa/tests/mode/at4.a65 new file mode 100644 index 0000000..3fc1448 --- /dev/null +++ b/xa/tests/mode/at4.a65 @@ -0,0 +1,4 @@ + + .align 4 + iny + diff --git a/xa/tests/mode/c6502-ad4.o65.ok b/xa/tests/mode/c6502-ad4.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..e3d425548bf4c058cea1d0621a0de7faa75565d7 GIT binary patch literal 34 ecmZQ%$Tu@(U}9hpU|?WiVPs%%08&6E0ssIZi~%wU}RumVPIfzfKWiz2_Oan06i=M&Hw-a literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65c02-ad4.o65.ok b/xa/tests/mode/c65c02-ad4.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..580ef61c8b3ad698bef00217a6793779d8e29232 GIT binary patch literal 34 ecmZQ%$Tu@(5Mp2uU|?WiVPs%%08&6E0ssIbOaVs# literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65c02-at2.o65.ok b/xa/tests/mode/c65c02-at2.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..e4e0f7fc5cf2ada759aa740e37e61c5e885df705 GIT binary patch literal 34 gcmZQ%$Tu@(5M*EwU}RumVPIfzfKWiz2_Oan04S^i4gdfE literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65ce02-ad4.o65.ok b/xa/tests/mode/c65ce02-ad4.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..b2b721399d6c19b9b06c1ab1c54e60bde884621f GIT binary patch literal 34 ecmZQ%$Tu@(Fk)a3U|?WiVPs%%08&6E0ssIe%mHTr literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65ce02-at2.o65.ok b/xa/tests/mode/c65ce02-at2.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..a19d3efe4462a9ee9de2feb163a2e91f657e09eb GIT binary patch literal 34 gcmZQ%$Tu@(Fl1m5U}RumVPIfzfKWiz2_Oan04yv5E&u=k literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65sc02-ad4.o65.ok b/xa/tests/mode/c65sc02-ad4.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..ba08ed70407451bff7e9e0efb6e22e1fca0acc88 GIT binary patch literal 34 ecmZQ%$Tu@(P-0*ZU|?WiVPs%%08&6E0ssId3;|aF literal 0 HcmV?d00001 diff --git a/xa/tests/mode/c65sc02-at2.o65.ok b/xa/tests/mode/c65sc02-at2.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..19d8e6d55816f941810df735917831e395bdf30d GIT binary patch literal 34 gcmZQ%$Tu@(P-I{bU}RumVPIfzfKWiz2_Oan04i((9smFU literal 0 HcmV?d00001 diff --git a/xa/tests/mode/linkup1.tmp.ok b/xa/tests/mode/linkup1.tmp.ok new file mode 100644 index 0000000..433920f --- /dev/null +++ b/xa/tests/mode/linkup1.tmp.ok @@ -0,0 +1,7 @@ +linkup1.tmp.tmp: o65 version 0 executable file + mode: 0012 =[executable][16bit][byte relocation][CPU 6502][CPU2 65C02][align 4] + text segment @ $0400 - $0401 [$0001 bytes] + data segment @ $1000 - $1005 [$0005 bytes] + bss segment @ $4000 - $4000 [$0000 bytes] + zero segment @ $0002 - $0002 [$0000 bytes] + stack size $0000 bytes (i.e. unknown) diff --git a/xa/tests/mode/n6502-ad4.o65.ok b/xa/tests/mode/n6502-ad4.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..346fa6983c25708cc3b67edc245ed551b585db3e GIT binary patch literal 34 ecmZQ%$Tu@(aAIH(U|?WiVPs%%08&6E0ssIgi~)B5 literal 0 HcmV?d00001 diff --git a/xa/tests/mode/n6502-at2.o65.ok b/xa/tests/mode/n6502-at2.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..10fec82f429e5e73c1ad308ba9ae58b86eb96afd GIT binary patch literal 34 gcmZQ%$Tu@(aAaT*U}RumVPIfzfKWiz2_Oan04?kSJ^%m! literal 0 HcmV?d00001 diff --git a/xa/tests/mode/test1.o65.ok b/xa/tests/mode/test1.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..03b83ca7ea37d8f2ff3d8f1af1fa1d963fc38a84 GIT binary patch literal 547 tcmZQ%$Tu@(U}j)oVPs?w0AdG5MkWR@IPnSuM=m(Q@CpP+E`THh1^|g%((V8N literal 0 HcmV?d00001 diff --git a/xa/tests/mode/test2.o65.ok b/xa/tests/mode/test2.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..8efbac142e99bf5489b4247ed3f2519fa719bd48 GIT binary patch literal 49 ucmZQ%$Tu@(U}j)o;b3480AdFY1||kDIPvP$s}rwIoL~Ub46h(!3=9C>rwhFR literal 0 HcmV?d00001 diff --git a/xa/tests/mode/test3.o65.ok b/xa/tests/mode/test3.o65.ok new file mode 100644 index 0000000000000000000000000000000000000000..ef0bc1859080b3bd8b19df58821ad410ff7ae8ec GIT binary patch literal 547 xcmZQ%$Tu@(U}j)oVPs?w0AdG5MkWR@IPvP$D-a&3-~%0VEkP006wn)A|4a literal 0 HcmV?d00001