--- /dev/null
+/*****************************************************************************/
+/* */
+/* ea65.h */
+/* */
+/* Effective address structure definition */
+/* */
+/* */
+/* */
+/* (C) 1998-2004 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef EA_H
+#define EA_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* GetEA result struct */
+typedef struct EffAddr EffAddr;
+struct EffAddr {
+ /* First three fields get filled when calling GetEA */
+ unsigned long AddrModeSet; /* Possible addressing modes */
+ struct ExprNode* Expr; /* Expression if any (NULL otherwise) */
+ unsigned Reg; /* Register number in sweet16 mode */
+
+ /* The following fields are used inside instr.c */
+ unsigned AddrMode; /* Actual addressing mode used */
+ unsigned long AddrModeBit; /* Addressing mode as bit mask */
+ unsigned char Opcode; /* Opcode */
+};
+
+
+
+/* End of ea.h */
+
+#endif
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* ea65.c */
+/* */
+/* 65XX effective address parsing for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 1998-2004 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+/* ca65 */
+#include "ea.h"
+#include "ea65.h"
+#include "error.h"
+#include "expr.h"
+#include "instr.h"
+#include "nexttok.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void GetEA (EffAddr* A)
+/* Parse an effective address, return the result in A */
+{
+ unsigned long Restrictions;
+
+ /* Clear the output struct */
+ A->AddrModeSet = 0;
+ A->Expr = 0;
+
+ /* Handle an addressing size override */
+ switch (Tok) {
+ case TOK_OVERRIDE_ZP:
+ Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y;
+ NextTok ();
+ break;
+
+ case TOK_OVERRIDE_ABS:
+ Restrictions = AM65_ABS | AM65_ABS_X | AM65_ABS_Y;
+ NextTok ();
+ break;
+
+ case TOK_OVERRIDE_FAR:
+ Restrictions = AM65_ABS_LONG | AM65_ABS_LONG_X;
+ NextTok ();
+ break;
+
+ default:
+ Restrictions = ~0UL; /* None */
+ break;
+ }
+
+ /* Parse the effective address */
+ if (TokIsSep (Tok)) {
+
+ A->AddrModeSet = AM65_IMPLICIT;
+
+ } else if (Tok == TOK_HASH) {
+
+ /* #val */
+ NextTok ();
+ A->Expr = Expression ();
+ A->AddrModeSet = AM65_IMM;
+
+ } else if (Tok == TOK_A) {
+
+ NextTok ();
+ A->AddrModeSet = AM65_ACCU;
+
+ } else if (Tok == TOK_LBRACK) {
+
+ /* [dir] or [dir],y */
+ NextTok ();
+ A->Expr = Expression ();
+ Consume (TOK_RBRACK, "']' expected");
+ if (Tok == TOK_COMMA) {
+ /* [dir],y */
+ NextTok ();
+ Consume (TOK_Y, "`Y' expected");
+ A->AddrModeSet = AM65_DIR_IND_LONG_Y;
+ } else {
+ /* [dir] */
+ A->AddrModeSet = AM65_DIR_IND_LONG;
+ }
+
+ } else if (Tok == TOK_LPAREN) {
+
+ /* One of the indirect modes */
+ NextTok ();
+ A->Expr = Expression ();
+
+ if (Tok == TOK_COMMA) {
+
+ /* (expr,X) or (rel,S),y */
+ NextTok ();
+ if (Tok == TOK_X) {
+ /* (adr,x) */
+ NextTok ();
+ A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
+ ConsumeRParen ();
+ } else if (Tok == TOK_S) {
+ /* (rel,s),y */
+ NextTok ();
+ A->AddrModeSet = AM65_STACK_REL_IND_Y;
+ ConsumeRParen ();
+ ConsumeComma ();
+ Consume (TOK_Y, "`Y' expected");
+ } else {
+ Error ("Syntax error");
+ }
+
+ } else {
+
+ /* (adr) or (adr),y */
+ ConsumeRParen ();
+ if (Tok == TOK_COMMA) {
+ /* (adr),y */
+ NextTok ();
+ Consume (TOK_Y, "`Y' expected");
+ A->AddrModeSet = AM65_DIR_IND_Y;
+ } else {
+ /* (adr) */
+ A->AddrModeSet = AM65_ABS_IND | AM65_DIR_IND;
+ }
+ }
+
+ } else {
+
+ /* Remaining stuff:
+ *
+ * adr
+ * adr,x
+ * adr,y
+ * adr,s
+ */
+ A->Expr = Expression ();
+
+ if (Tok == TOK_COMMA) {
+
+ NextTok ();
+ switch (Tok) {
+
+ case TOK_X:
+ A->AddrModeSet = AM65_ABS_LONG_X | AM65_ABS_X | AM65_DIR_X;
+ NextTok ();
+ break;
+
+ case TOK_Y:
+ A->AddrModeSet = AM65_ABS_Y | AM65_DIR_Y;
+ NextTok ();
+ break;
+
+ case TOK_S:
+ A->AddrModeSet = AM65_STACK_REL;
+ NextTok ();
+ break;
+
+ default:
+ Error ("Syntax error");
+
+ }
+
+ } else {
+
+ A->AddrModeSet = AM65_ABS_LONG | AM65_ABS | AM65_DIR;
+
+ }
+ }
+
+ /* Apply addressing mode overrides */
+ A->AddrModeSet &= Restrictions;
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* ea65.h */
+/* */
+/* 65XX effective address parsing for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef EA65_H
+#define EA65_H
+
+
+
+/*****************************************************************************/
+/* Forwards */
+/*****************************************************************************/
+
+
+
+struct EffAddr;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void GetEA (EffAddr* A);
+/* Parse an effective address, return the result in A */
+
+
+
+/* End of ea65.h */
+
+#endif
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* easw16.c */
+/* */
+/* SWEET16 effective address parsing for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 2004 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+/* ca65 */
+#include "ea.h"
+#include "ea65.h"
+#include "error.h"
+#include "expr.h"
+#include "instr.h"
+#include "nexttok.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void GetSweet16EA (EffAddr* A)
+/* Parse an effective address, return the result in A */
+{
+ /* Clear the output struct */
+ A->AddrModeSet = 0;
+ A->Expr = 0;
+ A->Reg = 0;
+
+ /* Parse the effective address */
+ if (TokIsSep (Tok)) {
+
+ A->AddrModeSet = AMSW16_IMP;
+
+ } else if (Tok == TOK_AT) {
+
+ /* @reg */
+ A->AddrModeSet = AMSW16_IND;
+ NextTok ();
+ if (Tok != TOK_REG) {
+ ErrorSkip ("Register expected");
+ A->Reg = 0;
+ } else {
+ A->Reg = (unsigned) IVal;
+ NextTok ();
+ }
+
+ } else if (Tok == TOK_REG) {
+
+ A->Reg = (unsigned) IVal;
+ NextTok ();
+
+ if (Tok == TOK_COMMA) {
+
+ /* Rx, Constant */
+ NextTok ();
+ A->Expr = Expression ();
+
+ A->AddrModeSet = AMSW16_IMM;
+
+ } else {
+
+ A->AddrModeSet = AMSW16_REG;
+
+ }
+
+ } else {
+
+ /* OPC ea */
+ A->Expr = Expression ();
+ A->AddrModeSet = AMSW16_BRA;
+
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* easw16.h */
+/* */
+/* SWEET16 effective address parsing for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 2004 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef EASW16_H
+#define EASW16_H
+
+
+
+/*****************************************************************************/
+/* Forwards */
+/*****************************************************************************/
+
+
+
+struct EffAddr;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void GetSweet16EA (EffAddr* A);
+/* Parse an effective address, return the result in A */
+
+
+
+/* End of easw16.h */
+
+#endif
+
+
+
+
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
+/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* ca65 */
#include "asserts.h"
#include "ea.h"
+#include "ea65.h"
+#include "easw16.h"
#include "error.h"
#include "expr.h"
#include "global.h"
static void PutJMP (const InsDesc* Ins);
static void PutRTS (const InsDesc* Ins);
static void PutAll (const InsDesc* Ins);
+static void PutSweet16 (const InsDesc* Ins);
+static void PutSweet16Branch (const InsDesc* Ins);
unsigned Count;
InsDesc Ins[INS_COUNT_65816];
} InsTab65816 = {
- INS_COUNT_65816,
+ INS_COUNT_65816,
{
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
{ "AND", 0x0b8f6fc, 0x20, 0, PutAll },
#include "sunplus.inc"
#endif
+/* Instruction table for the SWEET16 pseudo CPU */
+#define INS_COUNT_SWEET16 27
+static const struct {
+ unsigned Count;
+ InsDesc Ins[INS_COUNT_SWEET16];
+} InsTabSweet16 = {
+ INS_COUNT_SWEET16,
+ {
+ { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
+ { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
+ { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
+ { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch },
+ { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch },
+ { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch },
+ { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch },
+ { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch },
+ { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch },
+ { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch },
+ { "BS", AMSW16_BRA, 0x0B, 0, PutSweet16Branch },
+ { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch },
+ { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 },
+ { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 },
+ { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 },
+ { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
+ { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 },
+ { "POP", AMSW16_IND, 0x80, 0, PutSweet16 },
+ { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 },
+ { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 },
+ { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 },
+ { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 },
+ { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
+ { "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
+ { "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
+ { "SUB", AMSW16_IMM, 0xB0, 0, PutSweet16 },
+ }
+};
+
/* An array with instruction tables */
(const InsTable*) &InsTab65816,
#ifdef SUNPLUS
(const InsTable*) &InsTabSunPlus,
+#else
+ NULL,
#endif
+ (const InsTable*) &InsTabSweet16,
};
const InsTable* InsTab = (const InsTable*) &InsTab6502;
-/* Table to build the effective opcode from a base opcode and an addressing
- * mode.
+/* Table to build the effective 65xx opcode from a base opcode and an
+ * addressing mode.
*/
-unsigned char EATab [9][AMI_COUNT] = {
+static unsigned char EATab[9][AM65I_COUNT] = {
{ /* Table 0 */
0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
},
};
-/* Table that encodes the additional bytes for each instruction */
-unsigned char ExtBytes [AMI_COUNT] = {
+/* Table to build the effective SWEET16 opcode from a base opcode and an
+ * addressing mode.
+ */
+static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
+ { /* Table 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Table 1 */
+ 0x00, 0x00, 0x00, 0x40, 0x20,
+ },
+};
+
+/* Table that encodes the additional bytes for each 65xx instruction */
+unsigned char ExtBytes[AM65I_COUNT] = {
0, /* Implicit */
0, /* Accu */
1, /* Direct */
2 /* Blockmove */
};
+/* Table that encodes the additional bytes for each SWEET16 instruction */
+static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
+ 0, /* AMSW16_IMP */
+ 1, /* AMSW16_BRA */
+ 2, /* AMSW16_IMM */
+ 0, /* AMSW16_IND */
+ 0, /* AMSW16_REG */
+};
+
/*****************************************************************************/
-/* Handler functions */
+/* Handler functions for 6502 derivates */
/*****************************************************************************/
switch (ED.AddrSize) {
case ADDR_SIZE_ABS:
- A->AddrModeSet &= ~AM_SET_ZP;
+ A->AddrModeSet &= ~AM65_SET_ZP;
break;
case ADDR_SIZE_FAR:
- A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS);
+ A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
break;
}
* emit a warning. This warning protects against a typo, where the '#'
* for the immediate operand is omitted.
*/
- if (A->Expr && (Ins->AddrMode & AM_IMM) &&
- (A->AddrModeSet & (AM_DIR | AM_ABS | AM_ABS_LONG)) &&
+ if (A->Expr && (Ins->AddrMode & AM65_IMM) &&
+ (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
ExtBytes[A->AddrMode] == 1) {
/* Found, check the expression */
break;
case 2:
- if (CPU == CPU_65816 && (A->AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
+ if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
/* This is a 16 bit mode that uses an address. If in 65816,
* mode, force this address into 16 bit range to allow
* addressing inside a 64K segment.
} else {
if (Val & 0x10) {
/* Index registers to 16 bit */
- ExtBytes[AMI_IMM_INDEX] = 2;
+ ExtBytes[AM65I_IMM_INDEX] = 2;
}
if (Val & 0x20) {
/* Accu to 16 bit */
- ExtBytes[AMI_IMM_ACCU] = 2;
+ ExtBytes[AM65I_IMM_ACCU] = 2;
}
}
}
} else {
if (Val & 0x10) {
/* Index registers to 8 bit */
- ExtBytes [AMI_IMM_INDEX] = 1;
+ ExtBytes[AM65I_IMM_INDEX] = 1;
}
if (Val & 0x20) {
/* Accu to 8 bit */
- ExtBytes [AMI_IMM_ACCU] = 1;
+ ExtBytes[AM65I_IMM_ACCU] = 1;
}
}
}
if (EvalEA (Ins, &A)) {
/* Check for indirect addressing */
- if (A.AddrModeBit & AM_ABS_IND) {
+ if (A.AddrModeBit & AM65_ABS_IND) {
/* Compare the low byte of the expression to 0xFF to check for
* a page cross. Be sure to use a copy of the expression otherwise
/*****************************************************************************/
-/* Code */
+/* Handler functions for SWEET16 */
+/*****************************************************************************/
+
+
+
+static void PutSweet16 (const InsDesc* Ins)
+/* Handle a generic sweet16 instruction */
+{
+ EffAddr A;
+
+ /* Evaluate the addressing mode used */
+ GetSweet16EA (&A);
+
+ /* From the possible addressing modes, remove the ones that are invalid
+ * for this instruction or CPU.
+ */
+ A.AddrModeSet &= Ins->AddrMode;
+
+ /* Check if we have any adressing modes left */
+ if (A.AddrModeSet == 0) {
+ Error ("Illegal addressing mode");
+ return;
+ }
+ A.AddrMode = BitFind (A.AddrModeSet);
+ A.AddrModeBit = (0x01UL << A.AddrMode);
+
+ /* Build the opcode */
+ A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
+
+ /* Check how many extension bytes are needed and output the instruction */
+ switch (Sweet16ExtBytes[A.AddrMode]) {
+
+ case 0:
+ Emit0 (A.Opcode);
+ break;
+
+ case 1:
+ Emit1 (A.Opcode, A.Expr);
+ break;
+
+ case 2:
+ Emit2 (A.Opcode, A.Expr);
+ break;
+
+ default:
+ Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
+
+ }
+}
+
+
+
+static void PutSweet16Branch (const InsDesc* Ins)
+/* Handle a sweet16 branch instruction */
+{
+ EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
+}
+
+
+
+/*****************************************************************************/
+/* Code */
/*****************************************************************************/
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
+/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/*****************************************************************************/
-/* Data */
+/* Data for 6502 and successors */
/*****************************************************************************/
* When assembling for the 6502 or 65C02, all addressing modes that are not
* available on these CPUs are removed before doing any checks.
*/
-#define AM_IMPLICIT 0x00000003UL
-#define AM_ACCU 0x00000002UL
-#define AM_DIR 0x00000004UL
-#define AM_ABS 0x00000008UL
-#define AM_ABS_LONG 0x00000010UL
-#define AM_DIR_X 0x00000020UL
-#define AM_ABS_X 0x00000040UL
-#define AM_ABS_LONG_X 0x00000080UL
-#define AM_DIR_Y 0x00000100UL
-#define AM_ABS_Y 0x00000200UL
-#define AM_DIR_IND 0x00000400UL
-#define AM_ABS_IND 0x00000800UL
-#define AM_DIR_IND_LONG 0x00001000UL
-#define AM_DIR_IND_Y 0x00002000UL
-#define AM_DIR_IND_LONG_Y 0x00004000UL
-#define AM_DIR_X_IND 0x00008000UL
-#define AM_ABS_X_IND 0x00010000UL
-#define AM_REL 0x00020000UL
-#define AM_REL_LONG 0x00040000UL
-#define AM_STACK_REL 0x00080000UL
-#define AM_STACK_REL_IND_Y 0x00100000UL
-#define AM_IMM_ACCU 0x00200000UL
-#define AM_IMM_INDEX 0x00400000UL
-#define AM_IMM_IMPLICIT 0x00800000UL
-#define AM_IMM (AM_IMM_ACCU | AM_IMM_INDEX | AM_IMM_IMPLICIT)
-#define AM_BLOCKMOVE 0x01000000UL
+#define AM65_IMPLICIT 0x00000003UL
+#define AM65_ACCU 0x00000002UL
+#define AM65_DIR 0x00000004UL
+#define AM65_ABS 0x00000008UL
+#define AM65_ABS_LONG 0x00000010UL
+#define AM65_DIR_X 0x00000020UL
+#define AM65_ABS_X 0x00000040UL
+#define AM65_ABS_LONG_X 0x00000080UL
+#define AM65_DIR_Y 0x00000100UL
+#define AM65_ABS_Y 0x00000200UL
+#define AM65_DIR_IND 0x00000400UL
+#define AM65_ABS_IND 0x00000800UL
+#define AM65_DIR_IND_LONG 0x00001000UL
+#define AM65_DIR_IND_Y 0x00002000UL
+#define AM65_DIR_IND_LONG_Y 0x00004000UL
+#define AM65_DIR_X_IND 0x00008000UL
+#define AM65_ABS_X_IND 0x00010000UL
+#define AM65_REL 0x00020000UL
+#define AM65_REL_LONG 0x00040000UL
+#define AM65_STACK_REL 0x00080000UL
+#define AM65_STACK_REL_IND_Y 0x00100000UL
+#define AM65_IMM_ACCU 0x00200000UL
+#define AM65_IMM_INDEX 0x00400000UL
+#define AM65_IMM_IMPLICIT 0x00800000UL
+#define AM65_IMM (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT)
+#define AM65_BLOCKMOVE 0x01000000UL
/* Bitmask for all ZP operations that have correspondent ABS ops */
-#define AM_SET_ZP (AM_DIR | AM_DIR_X | AM_DIR_Y | AM_DIR_IND | AM_DIR_X_IND)
+#define AM65_SET_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND)
/* Bitmask for all ABS operations that have correspondent FAR ops */
-#define AM_SET_ABS (AM_ABS | AM_ABS_X)
+#define AM65_SET_ABS (AM65_ABS | AM65_ABS_X)
/* Bit numbers and count */
-#define AMI_IMM_ACCU 21
-#define AMI_IMM_INDEX 22
-#define AMI_COUNT 25
+#define AM65I_IMM_ACCU 21
+#define AM65I_IMM_INDEX 22
+#define AM65I_COUNT 25
/* The instruction table for the currently active CPU */
extern const InsTable* InsTab;
-/* Table to build the effective opcode from a base opcode and an addressing
- * mode.
- */
-extern unsigned char EATab [9][AMI_COUNT];
-
/* Table that encodes the additional bytes for each instruction */
-extern unsigned char ExtBytes [AMI_COUNT];
+extern unsigned char ExtBytes[AM65I_COUNT];
+
+
+
+/*****************************************************************************/
+/* Data for the SWEET16 pseudo CPU */
+/*****************************************************************************/
+
+
+
+/* SWEET16 addressing modes */
+#define AMSW16_IMP 0x0001 /* Implicit */
+#define AMSW16_BRA 0x0002 /* A branch */
+#define AMSW16_IMM 0x0004 /* Immediate */
+#define AMSW16_IND 0x0008 /* Indirect */
+#define AMSW16_REG 0x0010 /* Register */
+
+#define AMSW16I_COUNT 5 /* Number of addressing modes */
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
asserts.o \
condasm.o \
dbginfo.o \
- ea.o \
+ ea65.o \
+ easw16.o \
enum.o \
error.o \
expr.o \
asserts.obj \
condasm.obj \
dbginfo.obj \
- ea.obj \
+ ea65.obj \
+ easw16.obj \
enum.obj \
error.obj \
expr.obj \
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
- ExtBytes [AMI_IMM_ACCU] = 2;
+ ExtBytes [AM65I_IMM_ACCU] = 2;
}
}
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
- ExtBytes [AMI_IMM_ACCU] = 1;
+ ExtBytes [AM65I_IMM_ACCU] = 1;
}
}
{
static const char* Keys[] = {
"CONSTRUCTOR",
- "DESTRUCTOR",
+ "DESTRUCTOR",
"INTERRUPTOR",
};
char Name [sizeof (SVal)];
/* Parse the remainder of the line and export the symbol */
ConDes (Name, (unsigned) Type);
}
-
+
static void DoConstructor (void)
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
- ExtBytes [AMI_IMM_INDEX] = 2;
+ ExtBytes [AM65I_IMM_INDEX] = 2;
}
}
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
- ExtBytes [AMI_IMM_INDEX] = 1;
+ ExtBytes [AM65I_IMM_INDEX] = 1;
}
}
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
- /* Try to find the CPU, then skip the identifier */
+ /* Try to find the CPU */
cpu_t CPU = FindCPU (SVal);
- NextTok ();
/* Switch to the new CPU */
SetCPU (CPU);
+
+ /* Skip the identifier. If the CPU switch was successful, the scanner
+ * will treat the input now correctly for the new CPU.
+ */
+ NextTok ();
}
}
+static int Sweet16Reg (const char* Ident)
+/* Check if the given identifier is a sweet16 register. Return -1 if this is
+ * not the case, return the register number otherwise.
+ */
+{
+ unsigned RegNum;
+ char Check;
+
+ if (Ident[0] != 'r' && Ident[0] != 'R') {
+ return -1;
+ }
+ if (!IsDigit (Ident[1])) {
+ return -1;
+ }
+
+ if (sscanf (Ident+1, "%u%c", &RegNum, &Check) != 1 || RegNum > 15) {
+ /* Invalid register */
+ return -1;
+ }
+
+ /* The register number is valid */
+ return (int) RegNum;
+}
+
+
+
void NextRawTok (void)
/* Read the next raw token from the input stream */
{
return;
}
+ /* Indirect op for sweet16 cpu. Must check this before checking for local
+ * symbols, because these may also use the '@' symbol.
+ */
+ if (CPU == CPU_SWEET16 && C == '@') {
+ NextChar ();
+ Tok = TOK_AT;
+ return;
+ }
+
/* Local symbol? */
if (C == LocalStart) {
if (C == ':') {
NextChar ();
Tok = TOK_OVERRIDE_FAR;
- return;
+ return;
}
break;
if (C == ':') {
NextChar ();
Tok = TOK_OVERRIDE_ZP;
- return;
+ return;
}
break;
default:
break;
}
- }
+
+ } else if (CPU == CPU_SWEET16 && (IVal = Sweet16Reg (SVal)) >= 0) {
+
+ /* A sweet16 register number in sweet16 mode */
+ Tok = TOK_REG;
+ return;
+
+ }
/* Check for define style macro */
if (IsDefine (SVal)) {
int TokHasIVal (enum Token Tok)
/* Return true if the given token has an attached IVal */
{
- return (Tok == TOK_INTCON || Tok == TOK_CHARCON);
+ return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
}
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
- TOK_A, /* A)ccu */
+ TOK_A, /* A)ccumulator */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_S, /* S register */
+ TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* :++ or :-- */
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
+ TOK_AT, /* @ - in Sweet16 mode */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
TOK_LINECONT,
TOK_LIST,
TOK_LISTBYTES,
- TOK_LOBYTE,
+ TOK_LOBYTE,
TOK_LOCAL,
TOK_LOCALCHAR,
TOK_LOWORD,
"65C02",
"65816",
"sunplus",
+ "sweet16",
};
/* Tables with CPU instruction sets */
CPU_ISET_6502 | CPU_ISET_65SC02,
CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02,
CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_65816,
- CPU_ISET_SUNPLUS
+ CPU_ISET_SUNPLUS,
+ CPU_ISET_SWEET16,
};
CPU_65C02,
CPU_65816,
CPU_SUNPLUS, /* Not in the freeware version - sorry */
+ CPU_SWEET16,
CPU_COUNT /* Number of different CPUs */
} cpu_t;
CPU_ISET_65SC02 = 1 << CPU_65SC02,
CPU_ISET_65C02 = 1 << CPU_65C02,
CPU_ISET_65816 = 1 << CPU_65816,
- CPU_ISET_SUNPLUS = 1 << CPU_SUNPLUS
+ CPU_ISET_SUNPLUS = 1 << CPU_SUNPLUS,
+ CPU_ISET_SWEET16 = 1 << CPU_SWEET16,
};
/* CPU used */
/* Code */
/*****************************************************************************/
-
+
cpu_t FindCPU (const char* Name);
/* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if