6502 support added back from original Madmac sources!
authorggn <ggn.dbug@gmail.com>
Wed, 19 Apr 2017 16:42:26 +0000 (19:42 +0300)
committerShamus Hammons <jlhamm@acm.org>
Thu, 20 Apr 2017 14:26:42 +0000 (09:26 -0500)
- Source fixed to work with current rmac implementation
- Removed ultra kludgy output mode and replaced it with .com/.exe./.xex output module (activated using -fx)
- Added #< and #> to give low and high bytes off an immediate word
- Included tester in "tests" folder.
- Updated docs.

17 files changed:
6502.c [new file with mode: 0644]
6502.tbl [new file with mode: 0644]
direct.c
direct.h
docs/rmac.rst
listing.c
makefile
object.c
object.h
procln.c
procln.h
riscasm.c
rmac.c
rmac.h
sect.c
sect.h
tests/6502tester.s [new file with mode: 0644]

diff --git a/6502.c b/6502.c
new file mode 100644 (file)
index 0000000..823263a
--- /dev/null
+++ b/6502.c
@@ -0,0 +1,559 @@
+/*
+ *  6502 Assembler
+ *
+ *    Init6502 initialization
+ *    d_6502    handle ".6502" directive
+ *    m6502cg  generate code for a 6502 mnemonic
+ *    d_org    handle 6502 section's ".org" directive
+ *    m6502obj generate 6502 object file
+ *
+ */
+#include "rmac.h"
+#include "sect.h"
+#include "expr.h"
+#include "error.h"
+
+#define        UPSEG_SIZE      0x10010L /* size of 6502 code buffer, 64K+16bytes */
+
+
+/*
+ *  Imports
+ */
+extern TOKEN *tok;             /* -> current token */
+extern int debug;              /* >0, in debug mode (-x) */
+extern int m6502;              /* 1, in 6502 mode */
+extern TOKEN exprbuf[];                /* "universal" postfix expression buffer */
+extern LONG lsloc;             /* `sloc' at start of line */
+extern unsigned orgactive;             // RISC/6502 org directive active
+extern unsigned orgaddr;               // Org'd address
+extern char * string[];
+
+extern char extra_stuff[];     /* needed-eol error message */
+extern char *range_error;      /* value-out-of-range error message */
+
+
+/*
+ *  Exports
+ */
+char in_6502mode[] = "directive illegal in .6502 section";
+static uint16_t orgmap[1024][2]; /* mark all 6502 org changes */
+uint16_t *currentorg = (uint16_t *)orgmap; /* current org range */
+
+/*
+ *  6502 addressing modes;
+ *  do not change these values.
+ *
+ */
+#define        A65_ABS         0
+#define        A65_ABSX        1
+#define        A65_ABSY        2
+#define        A65_IMPL        3
+#define        A65_IMMED       4
+#define        A65_INDX        5
+#define        A65_INDY        6
+#define        A65_IND         7
+#define        A65_REL         8
+#define        A65_ZP          9
+#define        A65_ZPX         10
+#define        A65_ZPY         11
+#define A65_IMMEDH  12
+#define A65_IMMEDL  13
+
+#define        NMACHOPS 56             /* number of machine ops */
+#define        NMODES  14              /* number of addressing modes */
+#define        NOP     0xea            /* 6502 NOP instruction */
+#define        ILLEGAL 0xff            /* 'illegal instr' marker */
+#define END65  0xff            /* end-of-an-instr-list */
+
+static char imodes[] =
+{
+       A65_IMMED, 0x69, A65_ABS, 0x6d, A65_ZP, 0x65, A65_INDX, 0x61, A65_INDY, 0x71,
+       A65_ZPX, 0x75, A65_ABSX, 0x7d, A65_ABSY, 0x79, END65,
+       A65_IMMED, 0x29, A65_ABS, 0x2d, A65_ZP, 0x25, A65_INDX, 0x21, A65_INDY, 0x31,
+       A65_ZPX, 0x35, A65_ABSX, 0x3d, A65_ABSY, 0x39, END65,
+       A65_ABS, 0x0e, A65_ZP, 0x06, A65_IMPL, 0x0a, A65_ZPX, 0x16, A65_ABSX,
+       0x1e, END65,
+       A65_REL, 0x90, END65,
+       A65_REL, 0xb0, END65,
+       A65_REL, 0xf0, END65,
+       A65_REL, 0xd0, END65,
+       A65_REL, 0x30, END65,
+       A65_REL, 0x10, END65,
+       A65_REL, 0x50, END65,
+       A65_REL, 0x70, END65,
+       A65_ABS, 0x2c, A65_ZP, 0x24, END65,
+       A65_IMPL, 0x00, END65,
+       A65_IMPL, 0x18, END65,
+       A65_IMPL, 0xd8, END65,
+       A65_IMPL, 0x58, END65,
+       A65_IMPL, 0xb8, END65,
+       A65_IMMED, 0xc9, A65_ABS, 0xcd, A65_ZP, 0xc5, A65_INDX, 0xc1, A65_INDY, 0xd1,
+       A65_ZPX, 0xd5, A65_ABSX, 0xdd, A65_ABSY, 0xd9, END65,
+       A65_IMMED, 0xe0, A65_ABS, 0xec, A65_ZP, 0xe4, END65,
+       A65_IMMED, 0xc0, A65_ABS, 0xcc, A65_ZP, 0xc4, END65,
+       A65_ABS, 0xce, A65_ZP, 0xc6, A65_ZPX, 0xd6, A65_ABSX, 0xde, END65,
+       A65_IMPL, 0xca, END65,
+       A65_IMPL, 0x88, END65,
+       A65_IMMED, 0x49, A65_ABS, 0x4d, A65_ZP, 0x45, A65_INDX, 0x41, A65_INDY, 0x51,
+       A65_ZPX, 0x55, A65_ABSX, 0x5d, A65_ABSY, 0x59, END65,
+       A65_ABS, 0xee, A65_ZP, 0xe6, A65_ZPX, 0xf6, A65_ABSX, 0xfe, END65,
+       A65_IMPL, 0xe8, END65,
+       A65_IMPL, 0xc8, END65,
+       A65_ABS, 0x4c, A65_IND, 0x6c, END65,
+       A65_ABS, 0x20, END65,
+       A65_IMMED, 0xa9, A65_ABS, 0xad, A65_ZP, 0xa5, A65_INDX, 0xa1, A65_INDY, 0xb1,
+       A65_ZPX, 0xb5, A65_ABSX, 0xbd, A65_ABSY, 0xb9, A65_IMMEDH, 0xa9, A65_IMMEDL, 0xa9, END65,
+       A65_IMMED, 0xa2, A65_ABS, 0xae, A65_ZP, 0xa6, A65_ABSY, 0xbe,
+       A65_ZPY, 0xb6, A65_IMMEDH, 0xa2, A65_IMMEDL, 0xa2, END65,
+       A65_IMMED, 0xa0, A65_ABS, 0xac, A65_ZP, 0xa4, A65_ZPX, 0xb4,
+       A65_ABSX, 0xbc, A65_IMMEDH, 0xa0, A65_IMMEDL, 0xa0, END65,
+       A65_ABS, 0x4e, A65_ZP, 0x46, A65_IMPL, 0x4a, A65_ZPX, 0x56,
+       A65_ABSX, 0x5e, END65,
+       A65_IMPL, 0xea, END65,
+       A65_IMMED, 0x09, A65_ABS, 0x0d, A65_ZP, 0x05, A65_INDX, 0x01, A65_INDY, 0x11,
+       A65_ZPX, 0x15, A65_ABSX, 0x1d, A65_ABSY, 0x19, END65,
+       A65_IMPL, 0x48, END65,
+       A65_IMPL, 0x08, END65,
+       A65_IMPL, 0x68, END65,
+       A65_IMPL, 0x28, END65,
+       A65_ABS, 0x2e, A65_ZP, 0x26, A65_IMPL, 0x2a, A65_ZPX, 0x36,
+       A65_ABSX, 0x3e, END65,
+       A65_ABS, 0x6e, A65_ZP, 0x66, A65_IMPL, 0x6a, A65_ZPX, 0x76,
+       A65_ABSX, 0x7e, END65,
+       A65_IMPL, 0x40, END65,
+       A65_IMPL, 0x60, END65,
+       A65_IMMED, 0xe9, A65_ABS, 0xed, A65_ZP, 0xe5, A65_INDX, 0xe1, A65_INDY, 0xf1,
+       A65_ZPX, 0xf5, A65_ABSX, 0xfd, A65_ABSY, 0xf9, END65,
+       A65_IMPL, 0x38, END65,
+       A65_IMPL, 0xf8, END65,
+       A65_IMPL, 0x78, END65,
+       A65_ABS, 0x8d, A65_ZP, 0x85, A65_INDX, 0x81, A65_INDY, 0x91, A65_ZPX, 0x95,
+       A65_ABSX, 0x9d, A65_ABSY, 0x99, END65,
+       A65_ABS, 0x8e, A65_ZP, 0x86, A65_ZPY, 0x96, END65,
+       A65_ABS, 0x8c, A65_ZP, 0x84, A65_ZPX, 0x94, END65,
+       A65_IMPL, 0xaa, END65,
+       A65_IMPL, 0xa8, END65,
+       A65_IMPL, 0xba, END65,
+       A65_IMPL, 0x8a, END65,
+       A65_IMPL, 0x9a, END65,
+       A65_IMPL, 0x98, END65
+};
+
+static char ops[NMACHOPS][NMODES]; /* opcodes */
+static unsigned char inf[NMACHOPS][NMODES]; /* construction info */
+
+static int abs2zp[] =
+{                              /* absolute-to-zeropage trans table */
+       A65_ZP,                 /* ABS */
+       A65_ZPX,                        /* ABSX */
+       A65_ZPY,                        /* ABSY */
+       -1,                             /* IMPL */
+       -1,                             /* IMMED */
+       -1,                             /* INDX */
+       -1,                             /* INDY */
+       -1,                             /* IND */
+       -1,                             /* REL */
+       -1,                             /* ZP */
+       -1,                             /* ZPX */
+       -1                              /* ZPY */
+};
+
+
+/*
+ *  initialize 6502 assembler
+ *
+ */
+void Init6502()
+{
+       register int i;
+       register int j;
+       register char *s;
+
+       s = imodes;
+
+       /* set all instruction slots to illegal */
+       for (i = 0; i < NMACHOPS; ++i)
+               for (j = 0; j < NMODES; ++j)
+                       inf[i][j] = ILLEGAL;
+
+       /* uncompress legal instructions into their slots */
+       for (i = 0; i < NMACHOPS; ++i)
+       {
+               do {
+                       j = *s & 0xff;
+                       inf[i][j] = *s;
+                       ops[i][j] = s[1];
+
+                       /* hack A65_REL mode */
+                       if (*s == A65_REL)
+                       {
+                               inf[i][A65_ABS] = A65_REL;
+                               ops[i][A65_ABS] = s[1];
+                               inf[i][A65_ZP] = A65_REL;
+                               ops[i][A65_ZP] = s[1];
+                       }
+               } while(*(s += 2) != (char)END65);
+               ++s;
+       }
+
+    /* set up first org section (set to zero) */
+    orgmap[0][0] = 0;
+}
+
+
+/*
+ *  .6502 --- enter 6502 mode
+ *
+ */
+int d_6502()
+{
+       SaveSection();                  /* save curent section */
+       SwitchSection(M6502);   /* switch to 6502 section */
+    if (challoc == 0) {
+        /*
+         *  Allocate and clear 64K of space for the 6502 section
+         */
+        chcheck(UPSEG_SIZE);
+        memset(sect[M6502].scode->chptr, 0, UPSEG_SIZE);
+    }
+    return 0;
+}
+
+
+/*
+ *  Do 6502 code generation
+ *
+ */
+VOID m6502cg(int op)
+{
+       register int amode;             /* (parsed) addressing mode */
+       register int i;
+       VALUE eval;                     /* expression value */
+       WORD eattr;                     /* expression attributes */
+       int zpreq;                      /* 1, optimize instr to zero-page form */
+       register char *p;               /* (temp) string usage */
+
+
+       ch_size = 0;            /* reset chunk size on every instruction */
+
+       /*
+        *  Parse 6502 addressing mode
+        *
+        */
+       zpreq = 0;
+       switch ((int)*tok)
+       {
+               case EOL:
+                       amode = A65_IMPL;
+                       break;
+
+               case '#':
+                       ++tok;
+            if (*tok == '>')
+            {
+                ++tok;
+                if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+                amode = A65_IMMEDH;
+                break;
+            }
+            else if (*tok == '<')
+            {
+                ++tok;
+                if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+                amode = A65_IMMEDL;
+                break;
+            }
+                       if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+                       amode = A65_IMMED;
+                       break;
+
+               case '(':
+                       ++tok;
+                       if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+
+                       if (*tok == ')')
+                       {                       /* (foo) or (foo),y */
+                               if (*++tok == ',')
+                               {                       /* (foo),y */
+                                       ++tok;
+                                       p = string[tok[1]];
+                                       if (*tok != SYMBOL ||
+                                                 p[1] != EOS ||
+                                                 (*p | 0x20) != 'y') /* sleazo tolower() */
+                                               goto badmode;
+                                       tok += 2;
+                                       amode = A65_INDY;
+                               }
+                               else amode = A65_IND;
+                       }
+                       else if (*tok == ',')
+                       {                       /* (foo,x) */
+                               ++tok;
+                               p = string[tok[1]];
+                               if (*tok != SYMBOL ||
+                                         p[1] != EOS ||
+                                         (*p | 0x20) != 'x') /* sleazo tolower() */
+                                       goto badmode;
+                               tok += 2;
+                               if (*tok++ != ')')
+                                       goto badmode;
+                               amode = A65_INDX;
+                       }
+                       else goto badmode;
+                       break;
+
+               case '@':
+                       ++tok;
+                       if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+
+                       if (*tok == '(')
+                       {
+                               ++tok;
+                               p = string[tok[1]];
+                               if (*tok != SYMBOL ||
+                                         p[1] != EOS ||
+                                         tok[2] != ')' ||
+                                         tok[3] != EOL)
+                                       goto badmode;
+
+                               i = (*p | 0x20);        /* sleazo tolower */
+                               if (i == 'x')
+                                       amode = A65_INDX;
+                               else if (i == 'y')
+                                       amode = A65_INDY;
+                               else goto badmode;
+                               tok += 3;               /* past SYMBOL <string> ')' EOL */
+                               zpreq = 1;              /* request zeropage optimization */
+                       }
+                       else if (*tok == EOL)
+                               amode = A65_IND;
+                       else goto badmode;
+                       break;
+
+               default:
+                       /*
+                        *  Short-circuit
+                        *    x,foo
+                        *    y,foo
+                        *
+                        */
+                       p = string[tok[1]];
+                       if (*tok == SYMBOL &&
+                                 p[1] == EOS &&
+                                 tok[2] == ',')
+                       {
+                               tok += 3;               /* past: SYMBOL <string> ',' */
+                               i = (*p | 0x20);
+
+                               if (i == 'x')
+                                       amode = A65_ABSX;
+                               else if (i == 'y')
+                                       amode = A65_ABSY;
+                               else goto not_coinop;
+
+                               if (expr(exprbuf, &eval, &eattr, NULL) < 0)
+                                       return;
+                               if (*tok != EOL)
+                                       goto badmode;
+
+                               zpreq = 1;
+                               break;
+                       }
+
+not_coinop:
+                       if (expr(exprbuf, &eval, &eattr, NULL) < 0) return;
+                       zpreq = 1;
+
+                       if (*tok == EOL)
+                               amode = A65_ABS;
+                       else if (*tok == ',')
+                       {
+                               ++tok;
+                               p = string[tok[1]];
+                               if (*tok != SYMBOL ||
+                                         p[1] != EOS)
+                                       goto badmode;
+                               tok += 2;
+
+                               /*
+                                *  Check for X or Y index register;
+                                *  the OR with 0x20 is a sleazo conversion
+                                *  to lower-case that actually works.
+                                */
+                               i = *p | 0x20;  /* oooh, this is slimey (but fast!) */
+                               if (i == 'x')
+                                       amode = A65_ABSX;
+                               else if (i == 'y')
+                                       amode = A65_ABSY;
+                               else goto badmode;
+                       }
+                       else goto badmode;
+                       break;
+
+badmode:
+                       error("bad 6502 addressing mode");
+            return;
+       }
+
+       /*
+        *  Optimize ABS modes to zero-page when possible
+        *    o  ZPX or ZPY is illegal, or
+        *    o  expr is zeropage && zeropageRequest && expression is defined
+        */
+       if (inf[op][amode] == ILLEGAL || /* if current op is illegal, or */
+                 (eval < 0x100 &&              /* expr must be zero-page */
+                  zpreq != 0 &&                /* amode must request zero-page opt. */
+                  (eattr & DEFINED)))  /* and the expression must be defined */
+       {
+               i = abs2zp[amode];      /* i = zero-page translation of amode */
+#ifdef DO_DEBUG
+               DEBUG printf(" OPT: op=%d amode=%d i=%d inf[op][i]=%d\n",
+                                        op, amode, i, inf[op][i]);
+#endif
+               if (i >= 0 &&
+                         (inf[op][i] & 0xff) != ILLEGAL) /* use it if it's legal */
+                       amode = i;
+       }
+
+#ifdef DO_DEBUG
+       DEBUG printf("6502: op=%d amode=%d ", op, amode);
+       DEBUG printf("inf[op][amode]=%d\n", (int)inf[op][amode]);
+#endif
+
+       switch (inf[op][amode])
+       {
+               case A65_IMPL:          /* just leave the instruction */
+                       D_byte(ops[op][amode]);
+                       break;
+
+        case A65_IMMEDH:
+            D_byte(ops[op][amode]);
+            if (!(eattr & DEFINED))
+            {
+                AddFixup(FU_BYTEH, sloc, exprbuf);
+                eval = 0;
+            }
+            eval = (eval >> 8) & 0xff; /* bring high byte to low */
+            D_byte(eval);              /* deposit byte following instr */
+            break;
+
+        case A65_IMMEDL:
+            D_byte(ops[op][amode]);
+            if (!(eattr & DEFINED))
+            {
+                AddFixup(FU_BYTEL, sloc, exprbuf);
+                eval = 0;
+            }
+            eval = eval & 0xff; /* mask high byte */
+            D_byte(eval);              /* deposit byte following instr */
+            break;
+
+               case A65_IMMED:
+               case A65_INDX:
+               case A65_INDY:
+               case A65_ZP:
+               case A65_ZPX:
+               case A65_ZPY:
+                       D_byte(ops[op][amode]);
+                       if (!(eattr & DEFINED))
+                       {
+                               AddFixup(FU_BYTE, sloc, exprbuf);
+                               eval = 0;
+                       }
+                       else if (eval + 0x100 >= 0x200)
+                       {
+                               error(range_error);
+                               eval = 0;
+                       }
+                       D_byte(eval);           /* deposit byte following instr */
+                       break;
+
+               case A65_REL:
+                       D_byte(ops[op][amode]);
+                       if (eattr & DEFINED)
+                       {
+                               eval -= (sloc + 1);
+                               if (eval + 0x80 >= 0x100)
+                               {
+                                       error(range_error);
+                                       eval = 0;
+                               }
+                               D_byte(eval);
+                       }
+                       else
+                       {
+                               AddFixup(FU_6BRA, sloc, exprbuf);
+                               D_byte(0);
+                       }
+                       break;
+
+               case A65_ABS:
+               case A65_ABSX:
+               case A65_ABSY:
+               case A65_IND:
+                       D_byte(ops[op][amode]);
+                       if (!(eattr & DEFINED))
+                       {
+                               AddFixup(FU_WORD, sloc, exprbuf);
+                               eval = 0;
+                       }
+                       D_rword(eval);
+                       break;
+
+                       /*
+                        *  Deposit 3 NOPs for illegal things
+                        */
+               default:
+               case ILLEGAL:
+                       for (i = 0; i < 3; ++i) {
+                               D_byte(NOP);
+                       }
+                       error("illegal 6502 addressing mode");
+       }
+
+       /*
+        *  Check for overflow of code region
+        */
+       if (sloc > 0x10000L) fatal("6502 code pointer > 64K");
+       if (*tok != EOL) error(extra_stuff);
+}
+
+
+/*
+ *  Generate 6502 object output file.
+ *
+ */
+// ggn: converted into a com/exe/xex output format
+//      Notes: 1. The $ffff is only mandatory for the first segment, but let's dump it everywhere for now
+//             2. It's still dumping pages instead of more fine grained stuff. Should look into this - a8 people don't like waste so much ;)
+VOID m6502obj(ofd)
+int ofd;
+{
+       register CHUNK *ch;
+       register char *p;
+    uint16_t exeheader[3];
+    uint16_t *l;
+    int headsize = 6;
+    uint16_t *headpoint = (uint16_t *)exeheader;
+
+       /*
+        *  If no 6502 code was generated, forget it
+        */
+       if ((ch = sect[M6502].scode) == NULL ||
+                 ch->challoc == 0)
+               return;
+
+    exeheader[0] = 0xffff;  // mandatory for first segment
+    p = ch->chptr;
+
+    for (l = (uint16_t *)orgmap;l < currentorg;l+=2)
+    {
+        exeheader[1] = l[0];
+        exeheader[2] = l[1]-1;
+        write(ofd, headpoint, headsize);   // Write header 
+        write(ofd, p + l[0], l[1] - l[0]);
+        headpoint = &exeheader[1];            // skip the $ffff after first segment, it's not mandatory
+        headsize = 4;
+    }
+
+}
diff --git a/6502.tbl b/6502.tbl
new file mode 100644 (file)
index 0000000..52cfdca
--- /dev/null
+++ b/6502.tbl
@@ -0,0 +1,59 @@
+#
+#  6502 mnemonics
+#
+adc    2000
+and    2001
+asl    2002
+bcc    2003
+bcs    2004
+beq    2005
+bne    2006
+bmi    2007
+bpl    2008
+bvc    2009
+bvs    2010
+bit    2011
+brk    2012
+clc    2013
+cld    2014
+cli    2015
+clv    2016
+cmp    2017
+cpx    2018
+cpy    2019
+dec    2020
+dex    2021
+dey    2022
+eor    2023
+inc    2024
+inx    2025
+iny    2026
+jmp    2027
+jsr    2028
+lda    2029
+ldx    2030
+ldy    2031
+lsr    2032
+nop    2033
+ora    2034
+pha    2035
+php    2036
+pla    2037
+plp    2038
+rol    2039
+ror    2040
+rti    2041
+rts    2042
+sbc    2043
+sec    2044
+sed    2045
+sei    2046
+sta    2047
+stx    2048
+sty    2049
+tax    2050
+tay    2051
+tsx    2052
+txa    2053
+txs    2054
+tya    2055
index e9eb8ac3aa6b8dde78fffae0ddc943893a59f64c..15ce236287200236f9ce403ef7db7c5055144f65 100644 (file)
--- a/direct.c
+++ b/direct.c
@@ -21,7 +21,6 @@
 #define DEF_KW
 #include "kwtab.h"
 
-
 TOKEN exprbuf[128];                    // Expression buffer
 SYM * symbolPtr[1000000];      // Symbol pointers table
 static long unused;                    // For supressing 'write' warnings
@@ -32,7 +31,7 @@ char buffer[256];                     // Scratch buffer for messages
 int (*dirtab[])() = {
        d_org,                          // 0 org
        d_even,                         // 1 even
-       d_unimpl,                       // 2 .6502
+       d_6502,                     // 2 .6502
        d_68000,                        // 3 .68000
        d_bss,                          // 4 bss
        d_data,                         // 5 data
@@ -139,24 +138,53 @@ int d_warn(char *str)
 //
 int d_org(void)
 {
-       VALUE address;
-
-       if (!rgpu && !rdsp)
-               return error(".org permitted only in gpu/dsp section");
-
-       orgaddr = 0;
-
-       if (abs_expr(&address) == ERROR)
-       {
-               error("cannot determine org'd address");
-               return ERROR;
-       }
-
-       orgaddr = address;
-       orgactive = 1;
-//printf("ORG: address = $%08X...\n", orgaddr);
-
-       return 0;
+    VALUE address;
+    
+    if (!rgpu && !rdsp && !m6502)
+       return error(".org permitted only in gpu/dsp and 6502 sections");
+    
+    if (rgpu | rdsp)
+    {
+        orgaddr = 0;
+
+        if (abs_expr(&address) == ERROR)
+        {
+            error("cannot determine org'd address");
+            return ERROR;
+        }
+
+        orgaddr = address;
+        orgactive = 1;
+        //printf("ORG: address = $%08X...\n", orgaddr);
+
+        return 0;
+    }
+    else
+    {
+        // 6502
+        // We also kludge `lsloc' so the listing generator doesn't
+        // try to spew out megabytes.
+           VALUE eval;
+
+           //if (m6502 == 0) return error(".org permitted only in .6502 section");
+           if (abs_expr(&eval) < 0) return 0;
+           if (eval >= 0x10000L) return error(range_error);
+
+        if (sloc != currentorg[0])
+        {
+            currentorg[1] = sloc;
+            currentorg += 2;
+        }
+
+        currentorg[0] = eval;
+           ch_size = 0;
+           lsloc = sloc = eval;
+           chptr = scode->chptr + eval;
+       orgactive = 1;
+       orgaddr = eval;
+           at_eol();
+        return 0;
+    }
 }
 
 
@@ -467,6 +495,9 @@ static inline void SkipBytes(unsigned bytesToSkip)
 //
 int d_even(void)
 {
+    if (m6502)
+        return error(in_6502mode);
+
        unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01;
 
        if (skip)
@@ -562,6 +593,8 @@ int d_qphrase(void)
 //
 void auto_even(void)
 {
+  if (cursect != M6502)
+  {    
        if (scattr & SBSS)
                sloc++;                         // Bump BSS section
        else
@@ -569,6 +602,7 @@ void auto_even(void)
 
        if (lab_sym != NULL)    // Bump label if we have to
                lab_sym->svalue++;
+  }
 }
 
 
@@ -737,6 +771,9 @@ int globl1(char * p)
 
 int d_globl(void)
 {
+  if (m6502)
+    return error(in_6502mode);
+
        symlist(globl1);
        return 0;
 }
@@ -770,6 +807,9 @@ int d_abs(void)
 {
        VALUE eval;
 
+    if (m6502)
+        return error(in_6502mode);
+    
        SaveSection();
 
        if (*tok == EOL)
@@ -790,6 +830,8 @@ int d_text(void)
 {
        if (rgpu || rdsp)
                return error("directive forbidden in gpu/dsp mode");
+    if (m6502)
+        return error(in_6502mode);
 
        if (cursect != TEXT)
        {
@@ -805,6 +847,8 @@ int d_data(void)
 {
        if (rgpu || rdsp)
                return error("directive forbidden in gpu/dsp mode");
+    if (m6502)
+        return error(in_6502mode);
 
        if (cursect != DATA)
        {
@@ -820,6 +864,8 @@ int d_bss(void)
 {
        if (rgpu || rdsp)
                return error("directive forbidden in gpu/dsp mode");
+    if (m6502)
+        return error(in_6502mode);
 
        if (cursect != BSS)
        {
@@ -840,8 +886,11 @@ int d_ds(WORD siz)
 
        VALUE eval;
 
-       if ((siz != SIZB) && (sloc & 1))        // Automatic .even
-               auto_even();
+    if (cursect != M6502)
+    {
+           if ((siz != SIZB) && (sloc & 1))    // Automatic .even
+                   auto_even();
+    }
 
        if (abs_expr(&eval) != OK)
                return 0;
@@ -854,11 +903,12 @@ int d_ds(WORD siz)
        // In non-TDB section (BSS, ABS and M6502) just advance the location
        // counter appropriately. In TDB sections, deposit (possibly large) chunks
        // of zeroed memory....
-       if (scattr & SBSS)
+       if ((scattr & SBSS) || cursect == M6502)
        {
                listvalue(eval);
                eval *= siz;
                sloc += eval;
+        if (cursect == M6502) chptr += eval;
                just_bss = 1;                                   // No data deposited (8-bit CPU mode)
        }
        else
@@ -884,7 +934,7 @@ int d_dc(WORD siz)
                return error("illegal initialization of section");
 
        // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
-       if ((siz != SIZB) && (sloc & 1))
+       if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
                auto_even();
 
        // Check to see if we're trying to set LONGS on a non 32-bit aligned
@@ -971,11 +1021,22 @@ int d_dc(WORD siz)
                                        MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
 
                                // Deposit 68000 or 6502 (byte-reversed) word
-                               D_word(eval);
+                   if (cursect != M6502)
+                       {
+                           D_word(eval);
+                       }
+                   else
+                       {
+                           D_rword(eval);
+                       }
+        
                        }
 
                        break;
                case SIZL:
+               if (m6502)
+                   return error(in_6502mode);
+
                        if (!defined)
                        {
                                if (movei)
@@ -1030,7 +1091,7 @@ int d_dcb(WORD siz)
        if (expr(exprbuf, &eval, &eattr, NULL) < 0)
                return 0;
 
-       if ((siz != SIZB) && (sloc & 1))
+       if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
                auto_even();
 
        dep_block(evalc, siz, eval, eattr, exprbuf);
@@ -1160,11 +1221,22 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf)
                                        return error(range_error);
 
                                // Deposit 68000 or 6502 (byte-reversed) word
-                               D_word(eval);
+                               if (cursect != M6502)
+                               {
+                                       D_word(eval);
+                               }
+                               else
+                               {
+                                       D_rword(eval);
+                               }
+
                        }
 
                        break;
                case SIZL:
+                       if (m6502)
+                               return error(in_6502mode);
+            
                        if (!defined)
                        {
                                AddFixup(FU_LONG, sloc, exprbuf);
@@ -1195,6 +1267,9 @@ int d_comm(void)
        char * p;
        VALUE eval;
 
+       if (m6502)
+               return error(in_6502mode);
+
        if (*tok != SYMBOL)
                return error("missing symbol");
 
index 6ce7d4519c3efd8518a4520d24099e2737723f7a..57cdd631cfdfbd145c7d93a7fcc0737cad3cab1a 100644 (file)
--- a/direct.h
+++ b/direct.h
 extern TOKEN exprbuf[];
 extern SYM * symbolPtr[];
 extern int (* dirtab[])();
+extern int as68_flag;          /* 1, AS68 kludge mode for Alcyon back-end */
+extern int m6502;              /* 1, assembler in 6502 mode */
+extern char in_6502mode[];
+extern uint16_t *currentorg;
 
 // Prototypes
 int d_even(void);
index 91571d9211d6284ee86edd5b8b7095f6f0d63a41..f6f445eca2726ee47b86465209be56fbb9164fd3 100644 (file)
@@ -15,7 +15,7 @@ the accuracy of printed or duplicated material after the date of publication and
 disclaims liability for changes, errors or omissions.*
 
 
-*Copyright © 2011-2015, Reboot*
+*Copyright © 2011-2017, Reboot*
 
 *All rights reserved.*
 
@@ -52,10 +52,6 @@ with an editor should allow you to assemble your current source files. If you ar
 AS68 user, before you leap into the unknown please read the section on Notes for
 AS68 Users.
 
-This manual was typeset with TEX and the Computer Modern fonts, and it
-was printed on the Atari SLM-804 laser printer with a MEGA ST. Except for 200
-lines of assembly language, the assembler is written entirely in C.
-
 .. [1] It processes 30,000 lines a minute on a lightly loaded VAX 11/780; maybe 40,000 on a 520-ST with an SH-204 hard disk. Yet it could be sped up even more with some effort and without resorting to assembly language; C doesn't have to be slow!
 
 `Getting Started`_
@@ -968,6 +964,53 @@ described in the chapter on `6502 Support`_.
            INTIE:  ds.l     1
            PTSIN:  ds.l     1
 
+   Another interesting example worth mentioning is the emulation of "C"'s "union" keyword
+   using *.abs*. For example, the following "C" code:
+
+          ::
+
+           struct spritesheet
+           {
+                short spf_w;
+                short spf_h;
+                short spf_xo;
+                short spf_yo;
+                union { int spf_em_colour;     int spf_emx_colour;    };
+                union { int spf_em_psmask[16]; int spf_emx_colouropt; };
+           }
+
+   can be expressed as:
+
+          ::
+
+           .abs
+           *-------------------------------------------------------*
+           spf_w:          ds.w    1   ;<- common
+           spf_h:          ds.w    1
+           spf_xo:         ds.w    1
+           spf_yo:         ds.w    1
+           spf_data:       ds.l    0
+           *-------------------------------------------------------*
+           ;           .union  set
+           spf_em_colour:      ds.l    1   ;<- union #1
+           spf_em_psmask:      ds.l    16
+           *-------------------------------------------------------*
+           .68000
+                       .abs spf_em_colour
+           ;           .union  reset
+           spf_emx_colour:     ds.l    1   ;<- union #2
+           spf_emx_colouropt:  ds.l    1
+           spf_emx_psmask:     ds.l    16
+           spf_emx_psmaskopt:  ds.l    16
+           
+           .68000
+           ;*-------------------------------------------------------*
+           
+               move #spf_em_colour,d0
+               move #spf_emx_colour,d0
+
+   In this example, *spf_em_colour* and *spf_emx_colour* will have the same value.
+           
 **.comm** *symbol*, *expression*
    Specifies a label and the size of a common region. The label is made global,
    thus confined symbols cannot be made common. The linker groups all common
@@ -1588,6 +1631,8 @@ the Atari Coinop assembler.
 *empty*        implied or accumulator (e.g. tsx or ror)
 *expr*         absolute or zeropage
 #\ *expr*      immediate
+#<\ *expr*     immediate low byte of a word
+#>\ *expr*     immediate high byte of a word
 (*expr*,x)     indirect X
 (*expr*),y     indirect Y
 (*expr*)       indirect
@@ -1600,10 +1645,6 @@ x,\ *expr*     indexed X
 y,\ *expr*     indexed Y
 ============== ========================================
 
-While RMAC lacks "high" and "low" operators, high bytes of words may
-be extracted with the shift (``>>``) or divide (``/``) operators, and low bytes may be
-extracted with the bitwise AND (``&``) operator.
-
 `6502 Directives`_
 ''''''''''''''''''
 **.6502**
@@ -1643,43 +1684,17 @@ extracted with the bitwise AND (``&``) operator.
 
 `6502 Object Code Format`_
 ''''''''''''''''''''''''''
-This is a little bit of a kludge. An object file consists of a page map, followed by
-one or more page images, followed by a normal Alcyon 68000 object file. If the page
-map is all zero, it is not written.
+Traditionally Madmac had a very kludgy way of storing object files. This has been
+replaced with a more standard *.exe* (or *.com* or *.xex* if you prefer). Briefly,
+the *.exe* format consists of chunks of this format (one after the other):
 
-The page map contains a byte for each of the 256 256-byte pages in the 6502's
-64K address space. The byte is zero (``$00``) if the page contained only zero bytes, or
-one (``$01``) if the page contained any non-zero bytes. If a page is flagged with a one,
-then it is written (in order) following the page map.
-
-The following code:
-
-     ::
-
-      .6502
-      .org  $8000
-      .dc.b 1
-      .org  $8100
-      .dc.b 1
-      .org  $8300
-      .dc.b 1
-      .end
-
-will generate a page map that looks (to a programmer) something like:
-
-     ::
+    ::
 
-      <80 bytes of zero>
-      01 01 00 01
-      <$7c more bytes of zero, for $100 total>
-      <image of page $80>
-      <image of page $81>
-      <image of page $83>
-
-Following the last page image is an Alcyon-format object file, starting with
-the magic number ``$601a``. It may contain 68000 code (although that is probably
-useless), but the symbol table is valid and available for debugging purposes. 6502
-symbols will be absolute (not in text, data or bss).
+     Offset     Description
+     00-01      $FFFF - Indicates a binary load file. Mandatory for first segment, optional for any other segment
+     02-03      Start Address. The segment will load at this address
+     04-05      End Address. The last byte to load for this segment
+     06-..      The actual segment data to load (End Address-Start Address + 1 bytes)
 
 `Error Messages`_
 =================
index 3d632560ab89ccf8ce561a29b8d9fb6e10628f74..68d6c6f42141ad952bb4d841e94c8eb2693d3b52 100644 (file)
--- a/listing.c
+++ b/listing.c
@@ -301,11 +301,14 @@ void listeol(void)
        {
                ch = sect[lcursect].sfcode;
 
+               if (lcursect != M6502)
+        {
                for(; ch!=NULL; ch=ch->chnext)
                {
                        if (lsloc >= ch->chloc && lsloc < (ch->chloc + ch->ch_size))
                                break;
                }
+        }
 
                // Fatal: Can't find chunk holding code
                if (ch == NULL)
@@ -331,7 +334,8 @@ nochunk:
                                strncpy(lnimage + LOC_COL, buf, 8);
                        }
 
-                       if (lsloc >= (ch->chloc + ch->ch_size))
+                       if (lcursect != M6502 &&
+                    lsloc >= (ch->chloc + ch->ch_size))
                        {
                                if ((ch = ch->chnext) == NULL)
                                        goto nochunk;
index c9260ff7af714b2c322fb9c0a9246089f06f19fe..99325d6c78473d043a0e9b4a2e3f0ce3ab9451c5 100644 (file)
--- a/makefile
+++ b/makefile
@@ -26,15 +26,15 @@ HOSTCC = gcc
 
 CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2
 
-SRCS = amode.c debug.c direct.c eagen.c error.c expr.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
+SRCS = amode.c debug.c direct.c eagen.c error.c expr.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c 6502.c
 
-OBJS = amode.o debug.o direct.o eagen.o error.o expr.o listing.o mach.o macro.o mark.o object.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
+OBJS = amode.o debug.o direct.o eagen.o error.o expr.o listing.o mach.o macro.o mark.o object.o procln.o riscasm.o rmac.o sect.o symbol.o token.o 6502.o
 
 #
 # Build everything
 #
 
-all : mntab.h 68ktab.h kwtab.h risckw.h rmac
+all : mntab.h 68ktab.h kwtab.h risckw.h 6502.h rmac
        @echo
        @echo "Don't forget to bump the version number before commiting!"
        @echo
@@ -53,6 +53,9 @@ mntab.h : mntab 68kmn kwgen
 kwtab.h : kwtab kwgen
        ./kwgen kw <kwtab >kwtab.h
 
+6502.h : 6502.tbl kwgen
+       ./kwgen mp <6502.tbl >6502.h
+
 risckw.h : kwtab kwgen
        ./kwgen mr <risctab >risckw.h
 
@@ -124,6 +127,9 @@ sect.o : sect.c
 symbol.o : symbol.c
        $(CC) $(CFLAGS) -c symbol.c
 
+6502.o : 6502.c
+       $(CC) $(CFLAGS) -c 6502.c
+
 token.o : token.c
        $(CC) $(CFLAGS) -c token.c
 
index cbedaab6b0b2cdf5907af53d377a42cb4dc5b8ab..3cae5479de5cbfca362f74ba6537720e661db3e8 100644 (file)
--- a/object.c
+++ b/object.c
@@ -12,7 +12,7 @@
 #include "riscasm.h"
 #include "sect.h"
 #include "symbol.h"
-
+extern void m6502obj(int ofd);
 
 //#define DEBUG_ELF
 
@@ -752,6 +752,11 @@ for(int j=0; j<i; j++)
                        free(strtable);
                }
        }
+    else if (obj_format == XEX)
+    {
+        // Just write the object file
+        m6502obj(fd);
+    }
 
        return 0;
 }
index f3e79d23603ed147afbf9cd4fb2af1490e8f1b4b..c15e7bebd306a2529599e729966efdfe3a052466 100644 (file)
--- a/object.h
+++ b/object.h
@@ -9,7 +9,7 @@
 #ifndef __OBJECT_H__
 #define __OBJECT_H__
 
-#include <rmac.h>
+#include "rmac.h"
 
 #define BSDHDRSIZE  0x20       // Size of BSD header
 #define HDRSIZE     0x1C       // Size of Alcyon header
index dd8980622be2eb42d4f4ebd7e3dd75ab3572c9f7..4afd5388c092035de15310389b7bf7156dded649 100644 (file)
--- a/procln.c
+++ b/procln.c
 #define DECL_MR
 #include "risckw.h"
 
+#define DEF_MP                 /* include 6502 keyword definitions */
+#define DECL_MP                        /* include 6502 keyword state machine tables */
+#include "6502.h"
+extern int m6502;              /* 1, assembler in .6502 mode */
+extern VOID m6502cg();         /* 6502 code generator */
+extern VOID m6502obj(int ofd);
 
 IFENT * ifent;                                 // Current ifent
 static IFENT ifent0;                   // Root ifent
@@ -566,6 +572,44 @@ When checking to see if it's already been equated, issue a warning.
        if (state == -3)
                goto loop;
 
+       /*
+        *  If we're in 6502 mode and are still in need
+        *  of a mnemonic, then search for valid 6502 mnemonic.
+        */
+       if (m6502 &&
+                 (state < 0 || state >= 1000))
+       {
+#ifdef ST
+               state = kmatch(opname, mpbase, mpcheck, mptab, mpaccept);
+#else
+               for (state = 0, p = opname; state >= 0;)
+               {
+                       j = mpbase[state] + tolowertab[*p];
+                       if (mpcheck[j] != state)        /* reject, character doesn't match */
+                       {
+                               state = -1;             /* no match */
+                               break;
+                       }
+
+                       if (!*++p)
+                       {                       /* must accept or reject at EOS */
+                               state = mpaccept[j];    /* (-1 on no terminal match) */
+                               break;
+                       }
+                       state = mptab[j];
+               }
+#endif
+
+               /*
+                *  Call 6502 code generator if we found a mnemonic
+                */
+               if (state >= 2000)
+               {
+                       m6502cg(state - 2000);
+                       goto loop;
+               }
+       }
+    
        // If we are in GPU or DSP mode and still in need of a mnemonic then search
        // for one
        if ((rgpu || rdsp) && (state < 0 || state >= 1000))
index c645722702ba6350b0163f6512489cd557ca1987..4acf8560aa65e4af8c5ee12bdf693ffea98e62d3 100644 (file)
--- a/procln.h
+++ b/procln.h
@@ -22,6 +22,7 @@ extern int just_bss;
 extern VALUE pcloc;
 extern SYM * lab_sym;
 extern LONG amsktab[];
+extern char in_6502mode[];
 
 // Prototypes
 void InitLineProcessor(void);
index 2c291ffe9daad4b687f938dc35509312c044771b..fb29b5a3ed5fee45f67f4efdd45ecdc34dea60ca 100644 (file)
--- a/riscasm.c
+++ b/riscasm.c
@@ -23,7 +23,7 @@
 
 
 unsigned altbankok = 0;                // Ok to use alternate register bank
-unsigned orgactive = 0;                // RISC org directive active
+unsigned orgactive = 0;                // RISC/6502 org directive active
 unsigned orgaddr = 0;          // Org'd address
 unsigned orgwarning = 0;       // Has an ORG warning been issued
 int lastOpcode = -1;           // Last RISC opcode assembled
diff --git a/rmac.c b/rmac.c
index 084f898aa09fd760cb89ba89315342f9230b79d2..6bf5a5060fb8a23e109d308bc0a0109e9a1992ed 100644 (file)
--- a/rmac.c
+++ b/rmac.c
@@ -25,6 +25,7 @@
 int perm_verb_flag;                            // Permanently verbose, interactive mode
 int list_flag;                                 // "-l" listing flag on command line
 int verb_flag;                                 // Be verbose about what's going on
+int m6502;                                             // 1, assembling 6502 code
 int as68_flag;                                 // as68 kludge mode
 int glob_flag;                                 // Assume undefined symbols are global
 int lsym_flag;                                 // Include local symbols in object file
@@ -129,6 +130,7 @@ void DisplayHelp(void)
                "                    a: ALCYON (use this for ST)\n"
                "                    b: BSD (use this for Jaguar)\n"
                "                    e: ELF\n"
+        "                    x: com/exe/xex (Atari 800)\n"
                "  -i[path]          Directory to search for include files\n"
                "  -l[filename]      Create an output listing file\n"
                "  -n                Don't do things behind your back in RISC assembler\n"
@@ -250,6 +252,7 @@ int Process(int argc, char ** argv)
        orgactive = 0;                                  // Not in RISC org section
        orgwarning = 0;                                 // No ORG warning issued
        segpadsize = 2;                                 // Initialise segment padding size
+    m6502 = 0;                      // 6502 mode off by default
 
        // Initialise modules
        InitSymbolTable();                              // Symbol table
@@ -260,6 +263,7 @@ int Process(int argc, char ** argv)
        InitMark();                                             // Mark tape-recorder
        InitMacro();                                    // Macro processor
        InitListing();                                  // Listing generator
+    Init6502();                                                // 6502 assembler
 
        // Process command line arguments and assemble source files
        for(argno=0; argno<argc; ++argno)
@@ -318,6 +322,10 @@ int Process(int argc, char ** argv)
                                case 'E':
                                        obj_format = ELF;
                                        break;
+                case 'x':           // -fx = COM/EXE/XEX
+                case 'X':
+                    obj_format = XEX;
+                    break;
                                default:
                                        printf("-f: unknown object format specified\n");
                                        errcnt++;
@@ -492,6 +500,8 @@ int Process(int argc, char ** argv)
        // o  save current section (no more code generation)
        // o  do auto-even of all sections (or boundary alignment as requested
        //    through '-r')
+    // o  save the last pc value for 6502 (if we used 6502 at all) and
+    //    detemine if the last section contains anything
        // o  determine name of object file:
        //    -  "foo.o" for linkable output;
        //    -  "foo.prg" for GEMDOS executable (-p flag).
@@ -513,6 +523,13 @@ int Process(int argc, char ** argv)
                SaveSection();
        }
 
+    SwitchSection(M6502);
+    if (sloc != currentorg[0])
+    {
+        currentorg[1] = sloc;
+        currentorg += 2;
+    }
+
        if (objfname == NULL)
        {
                if (firstfname == NULL)
diff --git a/rmac.h b/rmac.h
index ee252efd5473fbb4664b2752b0ce157cdd60ab71..5b17d4b97631e15f3b02c94e19544ad3e70b459e 100644 (file)
--- a/rmac.h
+++ b/rmac.h
 #define MWC          1                         // Mark Williams object format
 #define BSD          2                         // BSD object format
 #define ELF          3                         // ELF object format
+#define XEX          4              // COM/EXE/XEX/whatever a8 object format
 
 // Pointer type that can point to (almost) anything
 #define PTR union _ptr
@@ -221,7 +222,7 @@ PTR
 #define TEXT         0x0001                    // Relative to text
 #define DATA         0x0002                    // Relative to data
 #define BSS          0x0004                    // Relative to BSS
-//#define M6502        0x0008          // 6502/microprocessor (absolute)
+#define M6502        0x0008                // 6502/microprocessor (absolute)
 #define TDB          (TEXT|DATA|BSS)   // Mask for text+data+bss
 
 // Sizes
@@ -261,6 +262,7 @@ extern int regbank;
 extern char * firstfname;
 extern int list_fd;
 extern int as68_flag;
+extern int m6502;
 extern int list_flag;
 extern int glob_flag;
 extern int lsym_flag;
@@ -270,6 +272,7 @@ extern int legacy_flag;
 extern int prg_flag;   // 1 = write ".PRG" relocatable executable
 extern LONG PRGFLAGS;
 extern int optim_flags[OPT_COUNT];
+extern void Init6502();
 
 // Exported functions
 char * fext(char *, char *, int);
diff --git a/sect.c b/sect.c
index b58d441709681244e395a0bb2683d607cf4e00f1..965fcf0dfeb24c12e5095457f72d320eb5be382d 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -16,6 +16,7 @@
 #include "riscasm.h"
 #include "symbol.h"
 #include "token.h"
+extern int m6502;              /* 1, assembler in .6502 mode */
 
 
 // Function prototypes
@@ -85,7 +86,7 @@ void InitSection(void)
        MakeSection(TEXT, SUSED | TEXT       );         // TEXT
        MakeSection(DATA, SUSED | DATA       );         // DATA
        MakeSection(BSS,  SUSED | BSS  | SBSS);         // BSS
-//     MakeSection(M6502, SUSED | TEXT       );                // 6502 code section
+       MakeSection(M6502, SUSED | TEXT      );         // 6502 code section
 
        // Switch to TEXT for starters
        SwitchSection(TEXT);
@@ -115,6 +116,8 @@ void SwitchSection(int sno)
        cursect = sno;
        SECT * p = &sect[sno];
 
+    m6502 = (sno == M6502);    /* set 6502-mode */
+
        // Copy section vars
        scattr = p->scattr;
        sloc = p->sloc;
@@ -409,6 +412,12 @@ int ResolveFixups(int sno)
        if (cch == NULL)
                return 0;
 
+       /*
+        *  Wire the 6502 segment's size to its allocated size (64K)
+        */
+       if (sno == M6502)
+               cch->ch_size = cch->challoc;
+    
        do
        {
                fup.cp = ch->chptr;                                     // fup -> start of chunk
@@ -583,6 +592,25 @@ int ResolveFixups(int sno)
 
                                *locp = (uint8_t)eval;
                                break;
+            // Fixup high/low byte off word for 6502
+            case FU_BYTEH:
+                if (!(eattr & DEFINED))
+                {
+                    error("external byte reference");
+                    continue;
+                }
+
+                *locp = (uint8_t)((eval >> 8) & 0xff);
+                break;
+            case FU_BYTEL:
+                if (!(eattr & DEFINED))
+                {
+                    error("external byte reference");
+                    continue;
+                }
+
+                *locp = (uint8_t)(eval & 0xff);
+                break;
                        // Fixup WORD forward references;
                        // the word could be unaligned in the section buffer, so we have to
                        // be careful.
@@ -713,7 +741,15 @@ int ResolveFixups(int sno)
                                        }
                                }
 
-                               SETBE16(locp, 0, eval);
+                               if (sno != M6502)
+                               {
+                                       *locp++ = (char)(eval >> 8);
+                                       *locp = (char)eval;
+                               }
+                               else
+                               {
+                                   SETBE16(locp, 0, eval);
+                }
                                break;
                        // Fixup LONG forward references;
                        // the long could be unaligned in the section buffer, so be careful
@@ -793,6 +829,8 @@ int ResolveAllFixups(void)
        ResolveFixups(TEXT);
        DEBUG printf("Resolving DATA sections...\n");
        ResolveFixups(DATA);
+       DEBUG printf("Resolving 6502 sections...\n");
+       ResolveFixups(M6502);           /* fixup 6502 section (if any) */
 
        return 0;
 }
diff --git a/sect.h b/sect.h
index b4c3733cab4c4aac1f560620f880d33d1fafe3c8..d34dec23317413802052636e48fbfd9bbba93764 100644 (file)
--- a/sect.h
+++ b/sect.h
@@ -24,8 +24,8 @@
                                                *chptr++=(uint8_t)((lw)>>8); \
                                                *chptr++=(uint8_t)(lw); \
                                                sloc += 4; ch_size += 4; if(orgactive) orgaddr += 4;}
-//#define D_rword(w)   {*chptr++=(uint8_t)w; *chptr++=(uint8_t)(w>>8); \
-//                                             sloc+=2; ch_size+=2;if(orgactive) orgaddr += 2;}
+#define D_rword(w)     {*chptr++=(uint8_t)w; *chptr++=(uint8_t)(w>>8); \
+                                               sloc+=2; ch_size+=2;if(orgactive) orgaddr += 2;}
 //#define D_rlong(lw)  {*chptr++=(uint8_t)(lw>>16);*chptr++=(uint8_t)(lw>>24);\
 //                                             *chptr++=(uint8_t)lw;*chptr++=(uint8_t)(lw>>8); \
 //                                             sloc+=4; ch_size += 4;if(orgactive) orgaddr += 4;}
@@ -67,6 +67,8 @@
 #define FU_LONG      004               // Fixup long
 #define FU_BBRA      005               // Fixup byte branch
 #define FU_6BRA      007               // Fixup 6502-format branch offset
+#define FU_BYTEH     050        // Fixup 6502 high byte of immediate word
+#define FU_BYTEL     051        // Fixup 6502 low byte of immediate word
 #define FU_SEXT      010               // Ok to sign extend
 #define FU_PCREL     020               // Subtract PC first
 #define FU_EXPR      040               // Expression (not symbol) follows
diff --git a/tests/6502tester.s b/tests/6502tester.s
new file mode 100644 (file)
index 0000000..852b4fb
--- /dev/null
@@ -0,0 +1,279 @@
+; Compile me using "rmac -l6502tester.lst 6502tester.s" and open
+; 6502tester.lst to see and compare the output opcodes
+
+    .6502
+
+label:
+
+;ADC (ADd with Carry)
+
+;   SYNTAX     HEX LEN   MODE        
+ ADC #$44      ;$69  2   Immediate    
+ ADC $44       ;$65  2   Zero Page    
+ ADC $44,X     ;$75  2   Zero Page,X  
+ ADC $4400     ;$6D  3   Absolute     
+ ADC $4400,X   ;$7D  3   Absolute,X   
+ ADC $4400,Y   ;$79  3   Absolute,Y   
+ ADC ($44,X)   ;$61  2   Indirect,X   
+ ADC ($44),Y   ;$71  2   Indirect,Y   
+
+;AND (bitwise AND with accumulator) 
+
+;  SYNTAX       HEX LEN  MODE
+ AND #$44      ;$29  2   Immediate
+ AND $44       ;$25  2   Zero Page
+ AND $44,X     ;$35  2   Zero Page,X
+ AND $4400     ;$2D  3   Absolute
+ AND $4400,X   ;$3D  3   Absolute,X
+ AND $4400,Y   ;$39  3   Absolute,Y
+ AND ($44,X)   ;$21  2   Indirect,X
+ AND ($44),Y   ;$31  2   Indirect,Y
+
+;ASL (Arithmetic Shift Left) 
+
+;  SYNTAX       HEX LEN         MODE        
+ ASL           ;$0A  1    Accumulator (Implied)
+ ASL $44       ;$06  2    Zero Page    
+ ASL $44,X     ;$16  2    Zero Page,X  
+ ASL $4400     ;$0E  3    Absolute     
+ ASL $4400,X   ;$1E  3    Absolute,X   
+
+;BIT (test BITs) 
+
+;   SYNTAX       HEX LEN       MODE        
+ BIT $44       ;$24  2      Zero Page    
+ BIT $4400     ;$2C  3      Absolute     
+
+;Branch Instructions
+
+;MNEMONIC   HEX
+BPL label              ;$10  (Branch on PLus)          
+BMI label              ;$30  (Branch on MInus)         
+BVC label              ;$50  (Branch on oVerflow Clear)
+BVS label              ;$70  (Branch on oVerflow Set)  
+BCC label              ;$90  (Branch on Carry Clear)   
+BCS label              ;$B0  (Branch on Carry Set)     
+BNE label              ;$D0  (Branch on Not Equal)     
+BEQ label              ;$F0  (Branch on EQual)         
+
+;BRK (BReaK) 
+;  SYNTAX       HEX LEN        ;MODE         
+ BRK           ;$00  1   ;Implied      
+
+;CMP (CoMPare accumulator) 
+
+;  SYNTAX       HEX LEN MODE         
+ CMP #$44      ;$C9  2   Immediate    
+ CMP $44       ;$C5  2   Zero Page    
+ CMP $44,X     ;$D5  2   Zero Page,X  
+ CMP $4400     ;$CD  3   Absolute     
+ CMP $4400,X   ;$DD  3   Absolute,X   
+ CMP $4400,Y   ;$D9  3   Absolute,Y   
+ CMP ($44,X)   ;$C1  2   Indirect,X   
+ CMP ($44),Y   ;$D1  2   Indirect,Y   
+
+;CPX (ComPare X register) 
+
+;  SYNTAX       HEX LEN MODE         
+ CPX #$44      ;$E0  2  Immediate    
+ CPX $44       ;$E4  2  Zero Page    
+ CPX $4400     ;$EC  3  Absolute     
+
+;CPY (ComPare Y register) 
+
+;  SYNTAX       HEX LEN MODE         
+ CPY #$44      ;$C0  2  Immediate    
+ CPY $44       ;$C4  2  Zero Page    
+ CPY $4400     ;$CC  3  Absolute     
+
+;DEC (DECrement memory) 
+
+;  SYNTAX       HEX LEN MODE         
+ DEC $44       ;$C6  2  Zero Page    
+ DEC $44,X     ;$D6  2  Zero Page,X  
+ DEC $4400     ;$CE  3  Absolute     
+ DEC $4400,X   ;$DE  3  Absolute,X   
+
+;EOR (bitwise Exclusive OR) 
+
+;  SYNTAX       HEX LEN MODE         
+ EOR #$44      ;$49  2  Immediate    
+ EOR $44       ;$45  2  Zero Page    
+ EOR $44,X     ;$55  2  Zero Page,X  
+ EOR $4400     ;$4D  3  Absolute     
+ EOR $4400,X   ;$5D  3  Absolute,X   
+ EOR $4400,Y   ;$59  3  Absolute,Y   
+ EOR ($44,X)   ;$41  2  Indirect,X   
+ EOR ($44),Y   ;$51  2  Indirect,Y   
+
+;Flag (Processor Status) Instructions
+
+;MNEMONIC                       HEX
+CLC ;(CLear Carry)              $18
+SEC ;(SEt Carry)                $38
+CLI ;(CLear Interrupt)          $58
+SEI ;(SEt Interrupt)            $78
+CLV ;(CLear oVerflow)           $B8
+CLD ;(CLear Decimal)            $D8
+SED ;(SEt Decimal)              $F8
+
+;INC (INCrement memory) 
+
+;  SYNTAX       HEX LEN MODE         
+ INC $44       ;$E6  2  ;Zero Page    
+ INC $44,X     ;$F6  2  ;Zero Page,X  
+ INC $4400     ;$EE  3  ;Absolute     
+ INC $4400,X   ;$FE  3  ;Absolute,X   
+;JMP (JuMP) 
+
+;  SYNTAX       HEX LEN MODE         
+ JMP $5597     ;$4C  3  Absolute     
+ JMP ($5597)   ;$6C  3  Indirect     
+
+;JSR (Jump to SubRoutine) 
+
+;  SYNTAX       HEX LEN MODE         
+ JSR $5597     ;$20  3  Absolute     
+
+;LDA (LoaD Accumulator) 
+
+;  SYNTAX       HEX LEN MODE         
+ LDA #$44      ;$A9  2  Immediate    
+ LDA $44       ;$A5  2  Zero Page    
+ LDA $44,X     ;$B5  2  Zero Page,X  
+ LDA $4400     ;$AD  3  Absolute     
+ LDA $4400,X   ;$BD  3  Absolute,X   
+ LDA $4400,Y   ;$B9  3  Absolute,Y   
+ LDA ($44,X)   ;$A1  2  Indirect,X   
+ LDA ($44),Y   ;$B1  2  Indirect,Y   
+
+;LDX (LoaD X register) 
+
+;  SYNTAX       HEX LEN MODE         
+ LDX #$44      ;$A2  2  Immediate    
+ LDX $44       ;$A6  2  Zero Page    
+ LDX $44,Y     ;$B6  2  Zero Page,Y  
+ LDX $4400     ;$AE  3  Absolute     
+ LDX $4400,Y   ;$BE  3  Absolute,Y   
+
+;LDY (LoaD Y register) 
+
+;  SYNTAX       HEX LEN MODE         
+ LDY #$44      ;$A0  2  Immediate    
+ LDY $44       ;$A4  2  Zero Page    
+ LDY $44,X     ;$B4  2  Zero Page,X  
+ LDY $4400     ;$AC  3  Absolute     
+ LDY $4400,X   ;$BC  3  Absolute,X   
+
+;LSR (Logical Shift Right) 
+
+;  SYNTAX       HEX LEN MODE         
+ LSR           ;$4A  1  Accumulator (Implied)
+ LSR $44       ;$46  2  Zero Page    
+ LSR $44,X     ;$56  2  Zero Page,X  
+ LSR $4400     ;$4E  3  Absolute     
+ LSR $4400,X   ;$5E  3  Absolute,X   
+
+;NOP (No OPeration) 
+
+;  SYNTAX       HEX LEN MODE         
+ NOP           ;$EA  1  Implied      
+
+;ORA (bitwise OR with Accumulator) 
+
+;  SYNTAX       HEX LEN MODE         
+ ORA #$44      ;$09  2  Immediate    
+ ORA $44       ;$05  2  Zero Page    
+ ORA $44,X     ;$15  2  Zero Page,X  
+ ORA $4400     ;$0D  3  Absolute     
+ ORA $4400,X   ;$1D  3  Absolute,X   
+ ORA $4400,Y   ;$19  3  Absolute,Y   
+ ORA ($44,X)   ;$01  2  Indirect,X   
+ ORA ($44),Y   ;$11  2  Indirect,Y   
+
+;Register Instructions 
+
+;MNEMONIC                 HEX
+TAX ;(Transfer A to X)    $AA
+TXA ;(Transfer X to A)    $8A
+DEX ;(DEcrement X)        $CA
+INX ;(INcrement X)        $E8
+TAY ;(Transfer A to Y)    $A8
+TYA ;(Transfer Y to A)    $98
+DEY ;(DEcrement Y)        $88
+INY ;(INcrement Y)        $C8
+  
+;ROL (ROtate Left) 
+
+;  SYNTAX       HEX LEN MODE         
+ ROL           ;$2A  1  Accumulator (Implied)
+ ROL $44       ;$26  2  Zero Page    
+ ROL $44,X     ;$36  2  Zero Page,X  
+ ROL $4400     ;$2E  3  Absolute     
+ ROL $4400,X   ;$3E  3  Absolute,X   
+
+;ROR (ROtate Right) 
+
+;  SYNTAX       HEX LEN MODE         
+ ROR           ;$6A  1  Accumulator (Implied)
+ ROR $44       ;$66  2  Zero Page    
+ ROR $44,X     ;$76  2  Zero Page,X  
+ ROR $4400     ;$6E  3  Absolute     
+ ROR $4400,X   ;$7E  3  Absolute,X   
+
+;RTI (ReTurn from Interrupt) 
+
+;  SYNTAX       HEX LEN MODE         
+ RTI           ;$40  1  Implied      
+
+;RTS (ReTurn from Subroutine) 
+
+;  SYNTAX       HEX LEN MODE         
+ RTS           ;$60  1  Implied      
+
+;SBC (SuBtract with Carry)
+
+;  SYNTAX       HEX LEN MODE         
+ SBC #$44      ;$E9  2  Immediate    
+ SBC $44       ;$E5  2  Zero Page    
+ SBC $44,X     ;$F5  2  Zero Page,X  
+ SBC $4400     ;$ED  3  Absolute     
+ SBC $4400,X   ;$FD  3  Absolute,X   
+ SBC $4400,Y   ;$F9  3  Absolute,Y   
+ SBC ($44,X)   ;$E1  2  Indirect,X   
+ SBC ($44),Y   ;$F1  2  Indirect,Y   
+
+;STA (STore Accumulator) 
+
+;  SYNTAX       HEX LEN MODE         
+ STA $44       ;$85  2  Zero Page    
+ STA $44,X     ;$95  2  Zero Page,X  
+ STA $4400     ;$8D  3  Absolute     
+ STA $4400,X   ;$9D  3  Absolute,X   
+ STA $4400,Y   ;$99  3  Absolute,Y   
+ STA ($44,X)   ;$81  2  Indirect,X   
+ STA ($44),Y   ;$91  2  Indirect,Y   
+
+;Stack Instructions
+;MNEMONIC                        HEX 
+TXS ;(Transfer X to Stack ptr)   $9A 
+TSX ;(Transfer Stack ptr to X)   $BA 
+PHA ;(PusH Accumulator)          $48 
+PLA ;(PuLl Accumulator)          $68 
+PHP ;(PusH Processor status)     $08 
+PLP ;(PuLl Processor status)     $28 
+
+;STX (STore X register)
+
+;  SYNTAX       HEX LEN MODE         
+ STX $44       ;$86  2  ;Zero Page    
+ STX $44,Y     ;$96  2  ;Zero Page,Y  
+ STX $4400     ;$8E  3  ;Absolute     
+  
+;STY (STore Y register)
+
+;  SYNTAX       HEX LEN MODE         
+ STY $44       ;$84  2  ;Zero Page    
+ STY $44,X     ;$94  2  ;Zero Page,X  
+ STY $4400     ;$8C  3  ;Absolute