]> Shamusworld >> Repos - rmac/blobdiff - 6502.c
EOY minor update.
[rmac] / 6502.c
diff --git a/6502.c b/6502.c
index 8141abea67a5e0d1e09f47213738c0e74d7612f3..55eab740115446b4f1b3ad63437be70403bab82e 100644 (file)
--- a/6502.c
+++ b/6502.c
@@ -1,5 +1,9 @@
 //
 //
-// 6502 Assembler
+// RMAC - Reboot's Macro Assembler for all Atari computers
+// 6502.C - 6502 Assembler
+// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
 //
 //    Init6502 initialization
 //    d_6502    handle ".6502" directive
 //
 //    Init6502 initialization
 //    d_6502    handle ".6502" directive
@@ -17,6 +21,9 @@
 #include "sect.h"
 #include "token.h"
 
 #include "sect.h"
 #include "token.h"
 
+#define DEF_KW
+#include "kwtab.h"
+
 #define        UPSEG_SIZE      0x10010L // size of 6502 code buffer, 64K+16bytes
 
 // Internal vars
 #define        UPSEG_SIZE      0x10010L // size of 6502 code buffer, 64K+16bytes
 
 // Internal vars
@@ -46,83 +53,83 @@ char strtoa8[128];  // ASCII to Atari 800 internal conversion table
 #define A65_IMMEDH  12
 #define A65_IMMEDL  13
 
 #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
+#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[] =
 {
 
 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_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, 0x90, END65,
-       A65_REL, 0xb0, END65,
-       A65_REL, 0xf0, END65,
-       A65_REL, 0xd0, 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_REL, 0x30, END65,
        A65_REL, 0x10, END65,
        A65_REL, 0x50, END65,
        A65_REL, 0x70, END65,
-       A65_ABS, 0x2c, A65_ZP, 0x24, END65,
+       A65_ABS, 0x2C, A65_ZP, 0x24, END65,
        A65_IMPL, 0x00, END65,
        A65_IMPL, 0x18, END65,
        A65_IMPL, 0x00, END65,
        A65_IMPL, 0x18, END65,
-       A65_IMPL, 0xd8, END65,
+       A65_IMPL, 0xD8, END65,
        A65_IMPL, 0x58, 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, 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_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_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_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_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_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_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_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_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, 0x38, END65,
-       A65_IMPL, 0xf8, END65,
+       A65_IMPL, 0xF8, END65,
        A65_IMPL, 0x78, 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_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
 };
 
        A65_IMPL, 0x98, END65
 };
 
@@ -243,7 +250,7 @@ void m6502cg(int op)
 {
        register int amode;             // (Parsed) addressing mode
        register int i;
 {
        register int amode;             // (Parsed) addressing mode
        register int i;
-       VALUE eval;                             // Expression value
+       uint64_t eval;                  // Expression value
        WORD eattr;                             // Expression attributes
        int zpreq;                              // 1, optimize instr to zero-page form
        register char * p;              // (Temp) string usage
        WORD eattr;                             // Expression attributes
        int zpreq;                              // 1, optimize instr to zero-page form
        register char * p;              // (Temp) string usage
@@ -254,18 +261,27 @@ void m6502cg(int op)
        //
        zpreq = 0;
 
        //
        zpreq = 0;
 
-       switch ((int)*tok)
+       switch (tok[0])
        {
        case EOL:
                amode = A65_IMPL;
                break;
 
        {
        case EOL:
                amode = A65_IMPL;
                break;
 
+       case KW_A:
+               if (tok[1] != EOL)
+                       goto badmode;
+
+               amode = A65_IMPL;
+               tok++;
+               break;
+
        case '#':
                tok++;
 
                if (*tok == '>')
                {
                        tok++;
        case '#':
                tok++;
 
                if (*tok == '>')
                {
                        tok++;
+
                        if (expr(exprbuf, &eval, &eattr, NULL) < 0)
                                return;
 
                        if (expr(exprbuf, &eval, &eattr, NULL) < 0)
                                return;
 
@@ -275,6 +291,7 @@ void m6502cg(int op)
                else if (*tok == '<')
                {
                        tok++;
                else if (*tok == '<')
                {
                        tok++;
+
                        if (expr(exprbuf, &eval, &eattr, NULL) < 0)
                                return;
 
                        if (expr(exprbuf, &eval, &eattr, NULL) < 0)
                                return;
 
@@ -301,13 +318,24 @@ void m6502cg(int op)
                        {
                                // (foo),y
                                tok++;
                        {
                                // (foo),y
                                tok++;
+#if 0
                                p = string[tok[1]];
 
                                p = string[tok[1]];
 
-                               if (*tok != SYMBOL || p[1] != EOS || (*p | 0x20) != 'y') // Sleazo tolower()
+                               // Sleazo tolower() -----------------vvvvvvvvvvv
+                               if (*tok != SYMBOL || p[1] != EOS || (*p | 0x20) != 'y')
                                        goto badmode;
 
                                tok += 2;
                                amode = A65_INDY;
                                        goto badmode;
 
                                tok += 2;
                                amode = A65_INDY;
+#else
+                               if (tok[0] == KW_Y)
+                                       amode = A65_INDY;
+
+                               if (tok[1] != EOL)
+                                       goto badmode;
+
+                               tok++;
+#endif
                        }
                        else
                                amode = A65_IND;
                        }
                        else
                                amode = A65_IND;
@@ -316,23 +344,35 @@ void m6502cg(int op)
                {
                        // (foo,x)
                        tok++;
                {
                        // (foo,x)
                        tok++;
+#if 0
                        p = string[tok[1]];
 
                        p = string[tok[1]];
 
-                       if (*tok != SYMBOL || p[1] != EOS || (*p | 0x20) != 'x') // Sleazo tolower()
+                       // Sleazo tolower() -----------------vvvvvvvvvvv
+                       if (*tok != SYMBOL || p[1] != EOS || (*p | 0x20) != 'x')
                                goto badmode;
 
                        tok += 2;
                                goto badmode;
 
                        tok += 2;
-
                        if (*tok++ != ')')
                                goto badmode;
 
                        amode = A65_INDX;
                        if (*tok++ != ')')
                                goto badmode;
 
                        amode = A65_INDX;
+#else
+                       if (tok[0] == KW_X)
+                               amode = A65_INDX;
+
+                       if ((tok[1] != ')') || (tok[2] != EOL))
+                               goto badmode;
+
+                       tok += 2;
+#endif
                }
                else
                        goto badmode;
 
                break;
 
                }
                else
                        goto badmode;
 
                break;
 
+       // I'm guessing that the form of this is @<expr>(X) or @<expr>(Y), which
+       // I've *never* seen before.  :-/
        case '@':
                tok++;
 
        case '@':
                tok++;
 
@@ -342,6 +382,7 @@ void m6502cg(int op)
                if (*tok == '(')
                {
                        tok++;
                if (*tok == '(')
                {
                        tok++;
+#if 0
                        p = string[tok[1]];
 
                        if (*tok != SYMBOL || p[1] != EOS || tok[2] != ')' || tok[3] != EOL)
                        p = string[tok[1]];
 
                        if (*tok != SYMBOL || p[1] != EOS || tok[2] != ')' || tok[3] != EOL)
@@ -357,6 +398,19 @@ void m6502cg(int op)
                                goto badmode;
 
                        tok += 3;               // Past SYMBOL <string> ')' EOL
                                goto badmode;
 
                        tok += 3;               // Past SYMBOL <string> ')' EOL
+#else
+                       if ((tok[1] != ')') || (tok[2] != EOL))
+                               goto badmode;
+
+                       if (tok[0] == KW_X)
+                               amode = A65_INDX;
+                       else if (tok[0] == KW_Y)
+                               amode = A65_INDY;
+                       else
+                               goto badmode;
+
+                       tok += 2;
+#endif
                        zpreq = 1;              // Request zeropage optimization
                }
                else if (*tok == EOL)
                        zpreq = 1;              // Request zeropage optimization
                }
                else if (*tok == EOL)
@@ -413,6 +467,7 @@ not_coinop:
                else if (*tok == ',')
                {
                        tok++;
                else if (*tok == ',')
                {
                        tok++;
+#if 0
                        p = string[tok[1]];
 
                        if (*tok != SYMBOL || p[1] != EOS)
                        p = string[tok[1]];
 
                        if (*tok != SYMBOL || p[1] != EOS)
@@ -433,6 +488,21 @@ not_coinop:
                                amode = A65_ABSY;
                        else
                                goto badmode;
                                amode = A65_ABSY;
                        else
                                goto badmode;
+#else
+                       if (tok[0] == KW_X)
+                       {
+                               amode = A65_ABSX;
+                               tok++;
+                       }
+                       else if (tok[0] == KW_Y)
+                       {
+                               amode = A65_ABSY;
+                               tok++;
+                       }
+
+                       if (tok[0] != EOL)
+                               goto badmode;
+#endif
                }
                else
                        goto badmode;
                }
                else
                        goto badmode;
@@ -560,9 +630,9 @@ badmode:
                        D_rword(eval);
                        break;
 
                        D_rword(eval);
                        break;
 
-                       //
-                       // Deposit 3 NOPs for illegal things
-                       //
+               //
+               // Deposit 3 NOPs for illegal things (why 3? why not 30? or zero?)
+               //
                default:
                case ILLEGAL:
                        for(i=0; i<3; i++)
                default:
                case ILLEGAL:
                        for(i=0; i<3; i++)
@@ -575,42 +645,39 @@ badmode:
        if (sloc > 0x10000L)
                fatal("6502 code pointer > 64K");
 
        if (sloc > 0x10000L)
                fatal("6502 code pointer > 64K");
 
-       if (*tok != EOL)
-               error(extra_stuff);
+       ErrorIfNotAtEOL();
 }
 
 
 //
 // Generate 6502 object output file.
 }
 
 
 //
 // Generate 6502 object output file.
+// ggn: Converted to COM/EXE/XEX output format
 //
 //
-// ggn: converted into a com/exe/xex output format
 void m6502obj(int ofd)
 {
 void m6502obj(int ofd)
 {
-       uint16_t exeheader[3];
-       int headsize = 6;
-       uint16_t * headpoint = exeheader;
+       uint8_t header[4];
 
        CHUNK * ch = sect[M6502].scode;
 
 
        CHUNK * ch = sect[M6502].scode;
 
-       // If no 6502 code was generated, forget it
+       // If no 6502 code was generated, bail out
        if ((ch == NULL) || (ch->challoc == 0))
                return;
 
        if ((ch == NULL) || (ch->challoc == 0))
                return;
 
-       exeheader[0] = 0xFFFF;          // Mandatory for first segment
        register uint8_t * p = ch->chptr;
 
        register uint8_t * p = ch->chptr;
 
+       // Write out mandatory $FFFF header
+       header[0] = header[1] = 0xFF;
+       uint32_t unused = write(ofd, header, 2);
+
        for(uint16_t * l=&orgmap[0][0]; l<currentorg; l+=2)
        {
        for(uint16_t * l=&orgmap[0][0]; l<currentorg; l+=2)
        {
-               exeheader[1] = l[0];
-               exeheader[2] = l[1] - 1;
+               SETLE16(header, 0, l[0]);
+               SETLE16(header, 2, l[1] - 1);
 
 
-               // Write header
-               size_t unused = write(ofd, headpoint, headsize);
+               // Write header for segment
+               unused = write(ofd, header, 4);
+               // Write the segment data
                unused = write(ofd, p + l[0], l[1] - l[0]);
                unused = write(ofd, p + l[0], l[1] - l[0]);
-
-               // Skip the $FFFF after first segment, it's not mandatory
-               headpoint = &exeheader[1];
-               headsize = 4;
        }
 }
 
        }
 }