1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 22:29:35 +00:00

Added new CPU SWEET16

git-svn-id: svn://svn.cc65.org/cc65/trunk@3208 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2004-10-03 21:26:00 +00:00
parent 7d72f47fe6
commit 7d0eb0d3ff
14 changed files with 785 additions and 78 deletions

68
src/ca65/ea.h Normal file
View File

@ -0,0 +1,68 @@
/*****************************************************************************/
/* */
/* 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

205
src/ca65/ea65.c Normal file
View File

@ -0,0 +1,205 @@
/*****************************************************************************/
/* */
/* 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;
}

67
src/ca65/ea65.h Normal file
View File

@ -0,0 +1,67 @@
/*****************************************************************************/
/* */
/* 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

107
src/ca65/easw16.c Normal file
View File

@ -0,0 +1,107 @@
/*****************************************************************************/
/* */
/* 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;
}
}

68
src/ca65/easw16.h Normal file
View File

@ -0,0 +1,68 @@
/*****************************************************************************/
/* */
/* 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

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -48,6 +48,8 @@
/* ca65 */
#include "asserts.h"
#include "ea.h"
#include "ea65.h"
#include "easw16.h"
#include "error.h"
#include "expr.h"
#include "global.h"
@ -76,6 +78,8 @@ static void PutSEP (const InsDesc* Ins);
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);
@ -419,7 +423,7 @@ static const struct {
unsigned Count;
InsDesc Ins[INS_COUNT_65816];
} InsTab65816 = {
INS_COUNT_65816,
INS_COUNT_65816,
{
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
{ "AND", 0x0b8f6fc, 0x20, 0, PutAll },
@ -530,6 +534,43 @@ static const struct {
#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 */
@ -541,14 +582,17 @@ static const InsTable* InsTabs[CPU_COUNT] = {
(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,
@ -605,8 +649,20 @@ unsigned char EATab [9][AMI_COUNT] = {
},
};
/* 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 */
@ -634,10 +690,19 @@ unsigned char ExtBytes [AMI_COUNT] = {
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 */
/*****************************************************************************/
@ -680,11 +745,11 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
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;
}
@ -706,8 +771,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
* 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 */
@ -745,7 +810,7 @@ static void EmitCode (EffAddr* A)
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.
@ -859,11 +924,11 @@ static void PutREP (const InsDesc* Ins)
} 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;
}
}
}
@ -887,11 +952,11 @@ static void PutSEP (const InsDesc* Ins)
} 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;
}
}
}
@ -912,7 +977,7 @@ static void PutJMP (const InsDesc* Ins)
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
@ -963,7 +1028,68 @@ static void PutAll (const InsDesc* Ins)
/*****************************************************************************/
/* 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 */
/*****************************************************************************/

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -44,7 +44,7 @@
/*****************************************************************************/
/* Data */
/* Data for 6502 and successors */
/*****************************************************************************/
@ -57,43 +57,43 @@
* 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
@ -117,18 +117,30 @@ struct InsTable {
/* 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];
/*****************************************************************************/
/* Code */
/* 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 */
/*****************************************************************************/

View File

@ -14,7 +14,8 @@ OBJS = anonname.o \
asserts.o \
condasm.o \
dbginfo.o \
ea.o \
ea65.o \
easw16.o \
enum.o \
error.o \
expr.o \

View File

@ -63,7 +63,8 @@ OBJS = anonname.obj \
asserts.obj \
condasm.obj \
dbginfo.obj \
ea.obj \
ea65.obj \
easw16.obj \
enum.obj \
error.obj \
expr.obj \

View File

@ -269,7 +269,7 @@ static void DoA16 (void)
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;
}
}
@ -282,7 +282,7 @@ static void DoA8 (void)
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;
}
}
@ -524,7 +524,7 @@ static void DoConDes (void)
{
static const char* Keys[] = {
"CONSTRUCTOR",
"DESTRUCTOR",
"DESTRUCTOR",
"INTERRUPTOR",
};
char Name [sizeof (SVal)];
@ -568,7 +568,7 @@ static void DoConDes (void)
/* Parse the remainder of the line and export the symbol */
ConDes (Name, (unsigned) Type);
}
static void DoConstructor (void)
@ -943,7 +943,7 @@ static void DoI16 (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;
}
}
@ -956,7 +956,7 @@ static void DoI8 (void)
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;
}
}
@ -1501,12 +1501,16 @@ static void DoSetCPU (void)
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 ();
}
}

View File

@ -640,6 +640,32 @@ static unsigned ReadStringConst (int StringTerm)
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 */
{
@ -791,6 +817,15 @@ Again:
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) {
@ -834,7 +869,7 @@ Again:
if (C == ':') {
NextChar ();
Tok = TOK_OVERRIDE_FAR;
return;
return;
}
break;
@ -854,14 +889,21 @@ Again:
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)) {
@ -1147,7 +1189,7 @@ int TokHasSVal (enum Token Tok)
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);
}

View File

@ -62,10 +62,11 @@ enum Token {
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 :-- */
@ -108,6 +109,7 @@ enum Token {
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_AT, /* @ - in Sweet16 mode */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
@ -194,7 +196,7 @@ enum Token {
TOK_LINECONT,
TOK_LIST,
TOK_LISTBYTES,
TOK_LOBYTE,
TOK_LOBYTE,
TOK_LOCAL,
TOK_LOCALCHAR,
TOK_LOWORD,

View File

@ -57,6 +57,7 @@ const char* CPUNames[CPU_COUNT] = {
"65C02",
"65816",
"sunplus",
"sweet16",
};
/* Tables with CPU instruction sets */
@ -66,7 +67,8 @@ const unsigned CPUIsets[CPU_COUNT] = {
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,
};

View File

@ -53,6 +53,7 @@ typedef enum {
CPU_65C02,
CPU_65816,
CPU_SUNPLUS, /* Not in the freeware version - sorry */
CPU_SWEET16,
CPU_COUNT /* Number of different CPUs */
} cpu_t;
@ -63,7 +64,8 @@ enum {
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 */
@ -81,7 +83,7 @@ extern const unsigned CPUIsets[CPU_COUNT];
/* Code */
/*****************************************************************************/
cpu_t FindCPU (const char* Name);
/* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if