]> git.sur5r.net Git - cc65/commitdiff
Add 4510 support for C65/C64DX
authorSven Oliver Moll <svolli@svolli.de>
Mon, 29 Aug 2016 08:45:18 +0000 (10:45 +0200)
committerSven Oliver Moll <svolli@svolli.de>
Mon, 29 Aug 2016 08:45:18 +0000 (10:45 +0200)
15 files changed:
doc/ca65.sgml
src/ca65/ea65.c
src/ca65/instr.c
src/ca65/instr.h
src/ca65/main.c
src/ca65/scanner.c
src/ca65/token.h
src/common/cpu.c
src/common/cpu.h
src/common/target.c
src/common/target.h
testcode/assembler/.gitignore
testcode/assembler/4510all.ref [new file with mode: 0644]
testcode/assembler/4510all.s [new file with mode: 0644]
testcode/assembler/Makefile

index 050e75628fec6543728c16c7aa3e0a30ecb97050..f59ce44cb4b59aeb8a14805e988eb0d194c21448 100644 (file)
@@ -152,7 +152,7 @@ Here is a description of all the command line options:
   Set the default for the CPU type. The option takes a parameter, which
   may be one of
 
-               6502, 65SC02, 65C02, 65816, sweet16, HuC6280
+       6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
 
 
   <label id="option-create-dep">
@@ -434,16 +434,16 @@ The assembler accepts
 In 65816 mode, several aliases are accepted, in addition to the official
 mnemonics:
 
-<tscreen><verb>
-CPA is an alias for CMP
-DEA is an alias for DEC A
-INA is an alias for INC A
-SWA is an alias for XBA
-TAD is an alias for TCD
-TAS is an alias for TCS
-TDA is an alias for TDC
-TSA is an alias for TSC
-</verb></tscreen>
+<itemize>
+<item><tt>CPA</tt> is an alias for <tt>CMP</tt>
+<item><tt>DEA</tt> is an alias for <tt>DEC A</tt>
+<item><tt>INA</tt> is an alias for <tt>INC A</tt>
+<item><tt>SWA</tt> is an alias for <tt>XBA</tt>
+<item><tt>TAD</tt> is an alias for <tt>TCD</tt>
+<item><tt>TAS</tt> is an alias for <tt>TCS</tt>
+<item><tt>TDA</tt> is an alias for <tt>TDC</tt>
+<item><tt>TSA</tt> is an alias for <tt>TSC</tt>
+</itemize>
 
 
 <sect1>6502X mode<label id="6502X-mode"><p>
@@ -473,6 +473,23 @@ from the mentioned web page, for more information, see there.
 </itemize>
 
 
+<sect1>4510 mode<p>
+
+The 4510 is a microcontroller that is the core of the Commodore C65 aka C64DX.
+It contains among other functions a slightly modified 65CE02 CPU, to allow
+address mapping for 20 bits of address space (1 megabyte addressable area).
+As compared to the description of the CPU in the System Specification of the
+Commodore C65 aka C64DX prototypes ca65 uses these changes:
+<itemize>
+<item><tt>LDA (d,SP),Y</tt> may also be written as <tt>LDA (d,S),Y</tt>
+(matching the 65816 notataion).
+<item>All branch instruction allow now 16 bit offsets. To use a 16 bit
+branch you have to prefix these with an "L" (e.g. "<tt>LBNE</tt>" instead of
+"<tt>BNE</tt>"). This might change at a later implementation of the assember.
+</itemize>
+For more information about the Commodore C65/C64DX and the 4510 CPU, see
+<url url="http://www.zimmers.net/anonftp/pub/cbm/c65/c65manualupdated.txt.gz">.
+
 
 <sect1>sweet16 mode<label id="sweet16-mode"><p>
 
index 69468c072102c1465e53c448f6fe5972edf5f182..e146ab8c91a6af91d38fffcd8c8dc98685396da1 100644 (file)
@@ -140,16 +140,27 @@ void GetEA (EffAddr* A)
 
         } else {
 
-            /* (adr) or (adr),y */
+            /* (adr), (adr),y or (adr),z */
             Consume (IndirectLeave, IndirectExpect);
             if (CurTok.Tok == TOK_COMMA) {
                 /* (adr),y */
                 NextTok ();
-                Consume (TOK_Y, "`Y' expected");
-                A->AddrModeSet = AM65_DIR_IND_Y;
+                switch(CurTok.Tok) {
+                case TOK_Z:
+                    if (CPU == CPU_4510) {
+                        NextTok ();
+                        A->AddrModeSet = AM65_DIR_IND;
+                    }
+                    break;
+                default:
+                    Consume (TOK_Y, "`Y' expected");
+                    A->AddrModeSet = AM65_DIR_IND_Y;
+                    break;
+                }
             } else {
                 /* (adr) */
-                A->AddrModeSet = AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
+                A->AddrModeSet = (CPU == CPU_4510) ? AM65_ABS_IND
+                                                   : AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
             }
         }
 
index 966a5cd98b9c7fcca5b9bceea3aa9b27c85f21d8..a4365402d09e9fd549ad00a06e37b10e354da443 100644 (file)
@@ -73,6 +73,9 @@ static void PutPCRel8 (const InsDesc* Ins);
 static void PutPCRel16 (const InsDesc* Ins);
 /* Handle branches with an 16 bit distance and PER */
 
+static void PutPCRel4510 (const InsDesc* Ins);
+/* Handle branches with a 16 bit distance for 4510 */
+
 static void PutBlockMove (const InsDesc* Ins);
 /* Handle the blockmove instructions (65816) */
 
@@ -125,6 +128,9 @@ static void PutRTS (const InsDesc* Ins attribute ((unused)));
 static void PutAll (const InsDesc* Ins);
 /* Handle all other instructions */
 
+static void Put4510 (const InsDesc* Ins);
+/* Handle instructions of 4510 not matching any EATab */
+
 static void PutSweet16 (const InsDesc* Ins);
 /* Handle a generic sweet16 instruction */
 
@@ -483,6 +489,149 @@ static const struct {
     }
 };
 
+/* Instruction table for the 4510 */
+static const struct {
+    unsigned Count;
+    InsDesc  Ins[133];
+} InsTab4510 = {
+    sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
+    {
+        { "ADC",  0x080A66C, 0x60, 0, PutAll },
+        { "AND",  0x080A66C, 0x20, 0, PutAll },
+        { "ASL",  0x000006e, 0x02, 1, PutAll },
+        { "ASR",  0x0000026, 0x43, 0, Put4510 },
+        { "ASW",  0x0000008, 0xcb, 6, PutAll },
+        { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
+        { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
+        { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
+        { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
+        { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
+        { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
+        { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
+        { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
+        { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
+        { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
+        { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
+        { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
+        { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
+        { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
+        { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
+        { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
+        { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
+        { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
+        { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
+        { "BIT",  0x0A0006C, 0x00, 2, PutAll },
+        { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
+        { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
+        { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
+        { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
+        { "BRK",  0x0000001, 0x00, 0, PutAll },
+        { "BSR",  0x0040000, 0x63, 0, PutPCRel4510 },
+        { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
+        { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
+        { "CLC",  0x0000001, 0x18, 0, PutAll },
+        { "CLD",  0x0000001, 0xd8, 0, PutAll },
+        { "CLE",  0x0000001, 0x02, 0, PutAll },
+        { "CLI",  0x0000001, 0x58, 0, PutAll },
+        { "CLV",  0x0000001, 0xb8, 0, PutAll },
+        { "CMP",  0x080A66C, 0xc0, 0, PutAll },
+        { "CPX",  0x080000C, 0xe0, 1, PutAll },
+        { "CPY",  0x080000C, 0xc0, 1, PutAll },
+        { "CPZ",  0x080000C, 0xd0, 1, Put4510 },
+        { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
+        { "DEC",  0x000006F, 0x00, 3, PutAll },
+        { "DEW",  0x0000004, 0xc3, 7, PutAll }, /* trial'n'error */
+        { "DEX",  0x0000001, 0xca, 0, PutAll },
+        { "DEY",  0x0000001, 0x88, 0, PutAll },
+        { "DEZ",  0x0000001, 0x3B, 0, PutAll },
+        { "EOM",  0x0000001, 0xea, 0, PutAll },
+        { "EOR",  0x080A66C, 0x40, 0, PutAll },
+        { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
+        { "INC",  0x000006f, 0x00, 4, PutAll },
+        { "INW",  0x0000004, 0xe3, 7, PutAll }, /* trial'n'error */
+        { "INX",  0x0000001, 0xe8, 0, PutAll },
+        { "INY",  0x0000001, 0xc8, 0, PutAll },
+        { "INZ",  0x0000001, 0x1B, 0, PutAll },
+        { "JMP",  0x0010808, 0x4c, 6, PutAll },
+        { "JSR",  0x0010808, 0x20, 6, Put4510 },
+        { "LBCC", 0x0040000, 0x93, 0, PutPCRel4510 },
+        { "LBCS", 0x0040000, 0xb3, 0, PutPCRel4510 },
+        { "LBEQ", 0x0040000, 0xf3, 0, PutPCRel4510 },
+        { "LBMI", 0x0040000, 0x33, 0, PutPCRel4510 },
+        { "LBNE", 0x0040000, 0xd3, 0, PutPCRel4510 },
+        { "LBPL", 0x0040000, 0x13, 0, PutPCRel4510 },
+        { "LBRA", 0x0040000, 0x83, 0, PutPCRel4510 },
+        { "LBVC", 0x0040000, 0x53, 0, PutPCRel4510 },
+        { "LBVS", 0x0040000, 0x73, 0, PutPCRel4510 },
+        { "LDA",  0x090A66C, 0xa0, 0, Put4510 },
+        { "LDX",  0x080030C, 0xa2, 1, PutAll },
+        { "LDY",  0x080006C, 0xa0, 1, PutAll },
+        { "LDZ",  0x0800048, 0xa3, 1, Put4510 },
+        { "LSR",  0x000006F, 0x42, 1, PutAll },
+        { "MAP",  0x0000001, 0x5C, 0, PutAll },
+        { "NEG",  0x0000001, 0x42, 0, PutAll },
+        { "NOP",  0x0000001, 0xea, 0, PutAll }, /* == EOM */
+        { "ORA",  0x080A66C, 0x00, 0, PutAll },
+        { "PHA",  0x0000001, 0x48, 0, PutAll },
+        { "PHD",  0x8000008, 0xf4, 1, PutAll }, /* == PHW */
+        { "PHP",  0x0000001, 0x08, 0, PutAll },
+        { "PHW",  0x8000008, 0xf4, 1, PutAll },
+        { "PHX",  0x0000001, 0xda, 0, PutAll },
+        { "PHY",  0x0000001, 0x5a, 0, PutAll },
+        { "PHZ",  0x0000001, 0xdb, 0, PutAll },
+        { "PLA",  0x0000001, 0x68, 0, PutAll },
+        { "PLP",  0x0000001, 0x28, 0, PutAll },
+        { "PLX",  0x0000001, 0xfa, 0, PutAll },
+        { "PLY",  0x0000001, 0x7a, 0, PutAll },
+        { "PLZ",  0x0000001, 0xfb, 0, PutAll },
+        { "RMB0", 0x0000004, 0x07, 1, PutAll },
+        { "RMB1", 0x0000004, 0x17, 1, PutAll },
+        { "RMB2", 0x0000004, 0x27, 1, PutAll },
+        { "RMB3", 0x0000004, 0x37, 1, PutAll },
+        { "RMB4", 0x0000004, 0x47, 1, PutAll },
+        { "RMB5", 0x0000004, 0x57, 1, PutAll },
+        { "RMB6", 0x0000004, 0x67, 1, PutAll },
+        { "RMB7", 0x0000004, 0x77, 1, PutAll },
+        { "ROL",  0x000006F, 0x22, 1, PutAll },
+        { "ROR",  0x000006F, 0x62, 1, PutAll },
+        { "ROW",  0x0000008, 0xeb, 6, PutAll },
+        { "RTI",  0x0000001, 0x40, 0, PutAll },
+        { "RTN",  0x0800000, 0x62, 1, PutAll },
+        { "RTS",  0x0000001, 0x60, 0, PutAll },
+        { "SBC",  0x080A66C, 0xe0, 0, PutAll },
+        { "SEC",  0x0000001, 0x38, 0, PutAll },
+        { "SED",  0x0000001, 0xf8, 0, PutAll },
+        { "SEE",  0x0000001, 0x03, 0, PutAll },
+        { "SEI",  0x0000001, 0x78, 0, PutAll },
+        { "SMB0", 0x0000004, 0x87, 1, PutAll },
+        { "SMB1", 0x0000004, 0x97, 1, PutAll },
+        { "SMB2", 0x0000004, 0xA7, 1, PutAll },
+        { "SMB3", 0x0000004, 0xB7, 1, PutAll },
+        { "SMB4", 0x0000004, 0xC7, 1, PutAll },
+        { "SMB5", 0x0000004, 0xD7, 1, PutAll },
+        { "SMB6", 0x0000004, 0xE7, 1, PutAll },
+        { "SMB7", 0x0000004, 0xF7, 1, PutAll },
+        { "STA",  0x010A66C, 0x80, 0, Put4510 },
+        { "STX",  0x000030c, 0x82, 1, Put4510 },
+        { "STY",  0x000006c, 0x80, 1, Put4510 },
+        { "STZ",  0x000006c, 0x04, 5, PutAll },
+        { "TAB",  0x0000001, 0x5b, 0, PutAll },
+        { "TAX",  0x0000001, 0xaa, 0, PutAll },
+        { "TAY",  0x0000001, 0xa8, 0, PutAll },
+        { "TAZ",  0x0000001, 0x4b, 0, PutAll },
+        { "TBA",  0x0000001, 0x7b, 0, PutAll },
+        { "TRB",  0x000000c, 0x10, 1, PutAll },
+        { "TSB",  0x000000c, 0x00, 1, PutAll },
+        { "TSX",  0x0000001, 0xba, 0, PutAll },
+        { "TSY",  0x0000001, 0x0b, 0, PutAll },
+        { "TXA",  0x0000001, 0x8a, 0, PutAll },
+        { "TXS",  0x0000001, 0x9a, 0, PutAll },
+        { "TYA",  0x0000001, 0x98, 0, PutAll },
+        { "TYS",  0x0000001, 0x2b, 0, PutAll },
+        { "TZA",  0x0000001, 0x6b, 0, PutAll },
+    }
+};
+
 /* Instruction table for the 65816 */
 static const struct {
     unsigned Count;
@@ -786,6 +935,7 @@ static const InsTable* InsTabs[CPU_COUNT] = {
     (const InsTable*) &InsTabSweet16,
     (const InsTable*) &InsTabHuC6280,
     0,                                  /* Mitsubishi 740 */
+    (const InsTable*) &InsTab4510,
 };
 const InsTable* InsTab = (const InsTable*) &InsTab6502;
 
@@ -797,73 +947,73 @@ static unsigned char EATab[12][AM65I_COUNT] = {
         0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
         0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
         0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 1 */
         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x80
+        0x00, 0x00, 0x80, 0x00
     },
     {   /* Table 2 */
         0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 3 */
         0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 4 */
         0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 5 */
         0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 6 */
         0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
         0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x90
+        0x00, 0x00, 0x90, 0x00
     },
     {   /* Table 7 */
         0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 8 */
         0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
         0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 9 */
         0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 10 (NOPs) */
         0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-        0x00, 0x00, 0x00
+        0x00, 0x00, 0x00, 0x00
     },
     {   /* Table 11 (LAX) */
         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-        0x00, 0x00, 0x80
+        0x00, 0x00, 0x80, 0x00
     },
 };
 
@@ -908,6 +1058,7 @@ unsigned char ExtBytes[AM65I_COUNT] = {
     2,          /* Blockmove (65816) */
     7,          /* Block transfer (HuC6280) */
     2,          /* Absolute Indirect long */
+    2,          /* Immidiate word */
 };
 
 /* Table that encodes the additional bytes for each SWEET16 instruction */
@@ -1033,7 +1184,7 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
     ** limit the expression to the maximum possible value.
     */
     if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
-        A->AddrMode == AM65I_IMM_IMPLICIT) {
+        A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
         if (ForceRange && A->Expr) {
             A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
         }
@@ -1136,6 +1287,14 @@ static void PutPCRel16 (const InsDesc* Ins)
 
 
 
+static void PutPCRel4510 (const InsDesc* Ins)
+/* Handle branches with a 16 bit distance */
+{
+    /* 16 bit branch opcode is 8 bit branch opcode or 0x03 */
+    EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
+}
+
+
 static void PutBlockMove (const InsDesc* Ins)
 /* Handle the blockmove instructions (65816) */
 {
@@ -1383,6 +1542,55 @@ static void PutAll (const InsDesc* Ins)
 
 
 
+static void Put4510 (const InsDesc* Ins)
+/* Handle all other instructions */
+{
+    /* The 4510 uses all 256 possible opcodes, so the last ones were cramped
+     * in where an opcode was still undefined. As a result, some of those
+     * don't follow any rules for encoding the addressmodes. So the EATab
+     * approach does not work always. In this function, the wrongly calculated
+     * opcode is replaced by the correct one "on the fly". Suggestions for a
+     * better approach are welcome.
+     *
+     * These are:
+     * $20 -> $22 : JSR ($1234) NEED TO CHECK FOR ADDRESSING
+     * $30 -> $23 : JSR ($1234,X)
+     * $47 -> $44 : ASR $12
+     * $57 -> $54 : ASR $12,X
+     * $93 -> $82 : STA ($12,SP),Y
+     * $9c -> $8b : STY $1234,X
+     * $9e -> $9b : STX $1234,Y
+     * $af -> $ab : LDZ $1234
+     * $bf -> $bb : LDZ $1234,X
+     * $b3 -> $e2 : LDA ($12,SP),Y
+     * $d0 -> $c2 : CPZ #$00
+     */
+    EffAddr A;
+
+    /* Evaluate the addressing mode used */
+    if (EvalEA (Ins, &A)) {
+        switch(A.Opcode) {
+            case 0x20: if(A.AddrModeBit == AM65_ABS_IND) A.Opcode = 0x22; break;
+            case 0x30: A.Opcode = 0x23; break;
+            case 0x47: A.Opcode = 0x44; break;
+            case 0x57: A.Opcode = 0x54; break;
+            case 0x93: A.Opcode = 0x82; break;
+            case 0x9C: A.Opcode = 0x8B; break;
+            case 0x9E: A.Opcode = 0x9B; break;
+            case 0xAF: A.Opcode = 0xAB; break;
+            case 0xBF: A.Opcode = 0xBB; break;
+            case 0xB3: A.Opcode = 0xE2; break;
+            case 0xD0: A.Opcode = 0xC2; break;
+            default: /*nothing*/ break;
+        }
+
+        /* No error, output code */
+        EmitCode (&A);
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                       Handler functions for SWEET16                       */
 /*****************************************************************************/
index 1f2ce262b91cd4811bdf7a410771058a7dcb887d..0a1a5e13d18041dabfbe9266543f4afaf2124a6b 100644 (file)
@@ -85,6 +85,7 @@
 #define AM65_BLOCKMOVE          0x01000000UL
 #define AM65_BLOCKXFER          0x02000000UL
 #define AM65_ABS_IND_LONG       0x04000000UL
+#define AM65_IMM_IMPLICIT_WORD  0x08000000UL /* PHW #$1234 (4510 only) */
 
 /* Bitmask for all ZP operations that have correspondent ABS ops */
 #define AM65_SET_ZP     (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND)
 #define AM65_ALL_FAR    (AM65_ABS_LONG | AM65_ABS_LONG_X)
                         
 /* Bitmask for all immediate operations */
-#define AM65_ALL_IMM    (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT)
+#define AM65_ALL_IMM    (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT | AM65_IMM_IMPLICIT_WORD)
 
 /* Bit numbers and count */
 #define AM65I_IMM_ACCU          21
 #define AM65I_IMM_INDEX         22
 #define AM65I_IMM_IMPLICIT      23
-#define AM65I_COUNT             27
+#define AM65I_IMM_IMPLICIT_WORD 27
+#define AM65I_COUNT             28
 
 
 
index a67319747837e610d84f682eb3d3c26a1cf96608..d6c364e4b7c16dda27b387c46b260556c8373ceb 100644 (file)
@@ -226,6 +226,10 @@ static void SetSys (const char* Sys)
             CBMSystem ("__C64__");
             break;
 
+        case TGT_C65:
+            CBMSystem ("__C65__");
+            break;
+
         case TGT_VIC20:
             CBMSystem ("__VIC20__");
             break;
index 7993210669c713fb5af3e872de953fd13d6a0fb4..4fde5ac5e69e3cbd7f7e1e122cf39e1a1fa4c499 100644 (file)
@@ -1109,60 +1109,76 @@ Again:
         /* Check for special names. Bail out if we have identified the type of
         ** the token. Go on if the token is an identifier.
         */
-        if (SB_GetLen (&CurTok.SVal) == 1) {
-            switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
-
-                case 'A':
-                    if (C == ':') {
-                        NextChar ();
-                        CurTok.Tok = TOK_OVERRIDE_ABS;
-                    } else {
-                        CurTok.Tok = TOK_A;
-                    }
-                    return;
-
-                case 'F':
-                    if (C == ':') {
-                        NextChar ();
-                        CurTok.Tok = TOK_OVERRIDE_FAR;
+        switch (SB_GetLen (&CurTok.SVal)) {
+            case 1:
+                switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
+
+                    case 'A':
+                        if (C == ':') {
+                            NextChar ();
+                            CurTok.Tok = TOK_OVERRIDE_ABS;
+                        } else {
+                            CurTok.Tok = TOK_A;
+                        }
                         return;
-                    }
-                    break;
 
-                case 'S':
-                    if (CPU == CPU_65816) {
-                        CurTok.Tok = TOK_S;
-                        return;
-                    }
-                    break;
+                    case 'F':
+                        if (C == ':') {
+                            NextChar ();
+                            CurTok.Tok = TOK_OVERRIDE_FAR;
+                            return;
+                        }
+                        break;
 
-                case 'X':
-                    CurTok.Tok = TOK_X;
-                    return;
+                    case 'S':
+                        if ((CPU == CPU_4510) || (CPU == CPU_65816)) {
+                            CurTok.Tok = TOK_S;
+                            return;
+                        }
+                        break;
 
-                case 'Y':
-                    CurTok.Tok = TOK_Y;
-                    return;
+                    case 'X':
+                        CurTok.Tok = TOK_X;
+                        return;
 
-                case 'Z':
-                    if (C == ':') {
-                        NextChar ();
-                        CurTok.Tok = TOK_OVERRIDE_ZP;
+                    case 'Y':
+                        CurTok.Tok = TOK_Y;
                         return;
-                    }
-                    break;
 
-                default:
-                    break;
-            }
+                    case 'Z':
+                        if (C == ':') {
+                            NextChar ();
+                            CurTok.Tok = TOK_OVERRIDE_ZP;
+                           return;
+                        } else {
+                            if (CPU == CPU_4510) {
+                                CurTok.Tok = TOK_Z;
+                                return;
+                            }
+                        }
+                        break;
 
-        } else if (CPU == CPU_SWEET16 &&
-                  (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) {
+                    default:
+                        break;
+                }
+                break;
+            case 2:
+                if ((CPU == CPU_4510) &&
+                    (toupper (SB_AtUnchecked (&CurTok.SVal, 0)) == 'S') &&
+                    (toupper (SB_AtUnchecked (&CurTok.SVal, 1)) == 'P')) {
 
-            /* A sweet16 register number in sweet16 mode */
-            CurTok.Tok = TOK_REG;
-            return;
+                    CurTok.Tok = TOK_S;
+                    return;
+                }
+                /* fall through */
+            default:
+                if (CPU == CPU_SWEET16 &&
+                   (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) {
 
+                    /* A sweet16 register number in sweet16 mode */
+                    CurTok.Tok = TOK_REG;
+                    return;
+                }
         }
 
         /* Check for define style macro */
index bfc013a3ddc729f43dcd235e826194b451ca2534..93dfaa0920180c62c269b496ea21a3565541a06c 100644 (file)
@@ -66,6 +66,7 @@ typedef enum token_t {
     TOK_A,              /* A)ccumulator */
     TOK_X,              /* X register */
     TOK_Y,              /* Y register */
+    TOK_Z,              /* Z register */
     TOK_S,              /* S register */
     TOK_REG,            /* Sweet16 R.. register (in sweet16 mode) */
 
index 142d55258af54266c6abc7715eba6f25976d730d..b055fae88b3cad6eec8e4e4ec7dcbda3d71b5075 100644 (file)
@@ -61,6 +61,7 @@ const char* CPUNames[CPU_COUNT] = {
     "sweet16",
     "huc6280",
     "m740",
+    "4510",
 };
 
 /* Tables with CPU instruction sets */
@@ -74,6 +75,7 @@ const unsigned CPUIsets[CPU_COUNT] = {
     CPU_ISET_SWEET16,
     CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_HUC6280,
     CPU_ISET_6502 | CPU_ISET_M740,
+    CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_4510,
 };
 
 
index 5bdbdef8c0c77a20ace9e35586af0fbd5227e010..dcf1815db2d5ab9579f092cacd50ee532520d6de 100644 (file)
@@ -56,6 +56,7 @@ typedef enum {
     CPU_SWEET16,
     CPU_HUC6280,                /* Used in PC engine */
     CPU_M740,                   /* Mitsubishi 740 series MCUs */
+    CPU_4510,                   /* CPU of C65 */
     CPU_COUNT                   /* Number of different CPUs */
 } cpu_t;
 
@@ -70,6 +71,7 @@ enum {
     CPU_ISET_SWEET16    = 1 << CPU_SWEET16,
     CPU_ISET_HUC6280    = 1 << CPU_HUC6280,
     CPU_ISET_M740       = 1 << CPU_M740,
+    CPU_ISET_4510       = 1 << CPU_4510,
 };
 
 /* CPU used */
index c7b9a3d9861e4a6efa11947a2c7e3a4c25c9c303..99a134c43bc7aa92be692a8085248435562d43ed 100644 (file)
@@ -152,6 +152,7 @@ static const TargetEntry TargetMap[] = {
     {   "c128",         TGT_C128        },
     {   "c16",          TGT_C16         },
     {   "c64",          TGT_C64         },
+    {   "c65",          TGT_C65         },
     {   "cbm510",       TGT_CBM510      },
     {   "cbm610",       TGT_CBM610      },
     {   "gamate",       TGT_GAMATE      },
@@ -205,6 +206,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
     { "sim65c02",       CPU_65C02,      BINFMT_BINARY,      CTNone  },
     { "pce",            CPU_HUC6280,    BINFMT_BINARY,      CTNone  },
     { "gamate",         CPU_6502,       BINFMT_BINARY,      CTNone  },
+    { "c65",            CPU_4510,       BINFMT_BINARY,      CTPET   },
 };
 
 /* Target system */
index 6366b725f48bebda5bcf3b7fe8bc9c1ef16c7ce7..4115ae21a9d17593dab190bb8a47bacffa2e273e 100644 (file)
@@ -80,6 +80,7 @@ typedef enum {
     TGT_SIM65C02,
     TGT_PCENGINE,
     TGT_GAMATE,
+    TGT_C65,
     TGT_COUNT                   /* Number of target systems */
 } target_t;
 
index de179f4f347071af7ba59453375430218cd915c9..0f7f86d780a6150f8b3faebb863ebed12b8f3954 100644 (file)
@@ -1,6 +1,3 @@
-chkillegal.bin
-chklegal.bin
-chkall.bin
-legal.o
-illegal.o
-all.o
+*.bin
+*.o
+*.lst
diff --git a/testcode/assembler/4510all.ref b/testcode/assembler/4510all.ref
new file mode 100644 (file)
index 0000000..b65b12e
Binary files /dev/null and b/testcode/assembler/4510all.ref differ
diff --git a/testcode/assembler/4510all.s b/testcode/assembler/4510all.s
new file mode 100644 (file)
index 0000000..997ddd0
--- /dev/null
@@ -0,0 +1,278 @@
+   .setcpu "4510"
+
+   brk
+   ora ($05,x)
+   cle
+   see
+   tsb $02
+   ora $02
+   asl $02
+   rmb0 $02
+   php
+   ora #$01
+   asl
+   tsy
+   tsb $1234
+   ora $1234
+   asl $1234
+   bbr0 $02,*+$34
+
+   bpl *+$32
+   ora ($06),y
+   ora ($07),z
+   lbpl *+$3133 ; bpl *+$3133
+   trb $02
+   ora $03,x
+   asl $03,x
+   rmb1 $02
+   clc
+   ora $1456,y
+   inc
+   inz
+   trb $1234
+   ora $1345,x
+   asl $1345,x
+   bbr1 $02,*+$34
+
+   jsr $1234
+   and ($05,x)
+   jsr ($2345)
+   jsr ($2456,x)
+   bit $02
+   and $02
+   rol $02
+   rmb2 $02
+   plp
+   and #$01
+   rol
+   tys
+   bit $1234
+   and $1234
+   rol $1234
+   bbr2 $02,*+$34
+
+   bmi *+$32
+   and ($06),y
+   and ($07),z
+   lbmi *+$3133 ; bmi *+$3133
+   bit $03,x
+   and $03,x
+   rol $03,x
+   rmb3 $02
+   sec
+   and $1456,y
+   dec
+   dez
+   bit $1345,x
+   and $1345,x
+   rol $1345,x
+   bbr3 $02,*+$34
+
+   rti
+   eor ($05,x)
+   neg
+   asr
+   asr $02
+   eor $02
+   lsr $02
+   rmb4 $02
+   pha
+   eor #$01
+   lsr
+   taz
+   jmp $1234
+   eor $1234
+   lsr $1234
+   bbr4 $02,*+$34
+
+   bvc *+$32
+   eor ($06),y
+   eor ($07),z
+   lbvc *+$3133 ; bvc *+$3133
+   asr $03,x
+   eor $03,x
+   lsr $03,x
+   rmb5 $02
+   cli
+   eor $1456,y
+   phy
+   tab
+   map
+   eor $1345,x
+   lsr $1345,x
+   bbr5 $02,*+$34
+
+   rts
+   adc ($05,x)
+   rtn #$09
+   bsr *+$3133
+   stz $02
+   adc $02
+   ror $02
+   rmb6 $02
+   pla
+   adc #$01
+   ror
+   tza
+   jmp ($2345)
+   adc $1234
+   ror $1234
+   bbr6 $02,*+$34
+
+   bvs *+$32
+   adc ($06),y
+   adc ($07),z
+   lbvs *+$3133 ; bvs *+$3133
+   stz $03,x
+   adc $03,x
+   ror $03,x
+   rmb7 $02
+   sei
+   adc $1456,y
+   ply
+   tba
+   jmp ($2456,x)
+   adc $1345,x
+   ror $1345,x
+   bbr7 $02,*+$34
+
+   bra *+$32
+   sta ($05,x)
+   sta ($0f,s),y
+   sta ($0f,sp),y
+   lbra *+$3133 ; bra *+$3133
+   sty $02
+   sta $02
+   stx $02
+   smb0 $02
+   dey
+   bit #$01
+   txa
+   sty $1345,x
+   sty $1234
+   sta $1234
+   stx $1234
+   bbs0 $02,*+$34
+
+   bcc *+$32
+   sta ($06),y
+   sta ($07),z
+   lbcc *+$3133 ; bcc *+$3133
+   sty $03,x
+   sta $03,x
+   stx $04,y
+   smb1 $02
+   tya
+   sta $1456,y
+   txs
+   stx $1456,y
+   stz $1234
+   sta $1345,x
+   stz $1345,x
+   bbs1 $02,*+$34
+
+   ldy #$01
+   lda ($05,x)
+   ldx #$01
+   ldz #$01
+   ldy $02
+   lda $02
+   ldx $02
+   smb2 $02
+   tay
+   lda #$01
+   tax
+   ldz $1234
+   ldy $1234
+   lda $1234
+   ldx $1234
+   bbs2 $02,*+$34
+
+   bcs *+$32
+   lda ($06),y
+   lda ($07),z
+   lbcs *+$3133 ; bcs *+$3133
+   ldy $03,x
+   lda $03,x
+   ldx $04,y
+   smb3 $02
+   clv
+   lda $1456,y
+   tsx
+   ldz $1345,x
+   ldy $1345,x
+   lda $1345,x
+   ldx $1456,y
+   bbs3 $02,*+$34
+
+   cpy #$01
+   cmp ($05,x)
+   cpz #$01
+   dew $02
+   cpy $02
+   cmp $02
+   dec $02
+   smb4 $02
+   iny
+   cmp #$01
+   dex
+   asw $1234
+   cpy $1234
+   cmp $1234
+   dec $1234
+   bbs4 $02,*+$34
+
+   bne *+$32
+   cmp ($06),y
+   cmp ($07),z
+   lbne *+$3133 ; bne *+$3133
+   cpz $02
+   cmp $03,x
+   dec $03,x
+   smb5 $02
+   cld
+   cmp $1456,y
+   phx
+   phz
+   cpz $1234
+   cmp $1345,x
+   dec $1345,x
+   bbs5 $02,*+$34
+
+   cpx #$01
+   sbc ($05,x)
+   lda ($0f,s),y
+   lda ($0f,sp),y
+   inw $02
+   cpx $02
+   sbc $02
+   inc $02
+   smb6 $02
+   inx
+   sbc #$01
+   eom
+   nop
+   row $1234
+   cpx $1234
+   sbc $1234
+   inc $1234
+   bbs6 $02,*+$34
+
+   beq *+$32
+   sbc ($06),y
+   sbc ($07),z
+   lbeq *+$3133 ; beq *+$3133
+   phd #$089a
+   phw #$089a
+   sbc $03,x
+   inc $03,x
+   smb7 $02
+   sed
+   sbc $1456,y
+   plx
+   plz
+   phd $1234
+   phw $1234
+   sbc $1345,x
+   inc $1345,x
+   bbs7 $02,*+$34
index a9257ce7519690925204815ce4d750927b8f522e..35c34235a7e1e3314205d3c871f6cfa395a1fa0e 100644 (file)
@@ -1,8 +1,13 @@
 
-all: chklegal.bin chkillegal.bin chkall.bin
+all: chklegal.bin chkillegal.bin chkall.bin chk4510.bin
        @#
 
-.PHONY: chklegal.bin chkillegal.bin chkall.bin
+.PHONY: chklegal.bin chkillegal.bin chkall.bin chk4510.bin
+
+chk4510.bin: 4510all.s
+       $(MAKE) -C ../../src all
+       ../../bin/cl65 --target none --cpu 4510 --listing 4510all.lst -o $@ $<
+       diff -q 4510all.ref $@ || cat 4510all.lst
 
 chklegal.bin: legal.s
        ../../bin/cl65 --target none --cpu 6502X -o chklegal.bin legal.s
@@ -23,3 +28,5 @@ clean:
        rm -f legal.o chklegal.bin
        rm -f illegal.o chkillegal.bin
        rm -f all.o chkall.bin
+       rm -f 4510all.o chk4510.bin 4510all.lst
+