From 7d0eb0d3ffa94083189a5e97886d528aa3fe8380 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 3 Oct 2004 21:26:00 +0000 Subject: [PATCH] Added new CPU SWEET16 git-svn-id: svn://svn.cc65.org/cc65/trunk@3208 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/ea.h | 68 +++++++++++++ src/ca65/ea65.c | 205 +++++++++++++++++++++++++++++++++++++++ src/ca65/ea65.h | 67 +++++++++++++ src/ca65/easw16.c | 107 ++++++++++++++++++++ src/ca65/easw16.h | 68 +++++++++++++ src/ca65/instr.c | 164 +++++++++++++++++++++++++++---- src/ca65/instr.h | 92 ++++++++++-------- src/ca65/make/gcc.mak | 3 +- src/ca65/make/watcom.mak | 3 +- src/ca65/pseudo.c | 20 ++-- src/ca65/scanner.c | 50 +++++++++- src/ca65/scanner.h | 6 +- src/common/cpu.c | 4 +- src/common/cpu.h | 6 +- 14 files changed, 785 insertions(+), 78 deletions(-) create mode 100644 src/ca65/ea.h create mode 100644 src/ca65/ea65.c create mode 100644 src/ca65/ea65.h create mode 100644 src/ca65/easw16.c create mode 100644 src/ca65/easw16.h diff --git a/src/ca65/ea.h b/src/ca65/ea.h new file mode 100644 index 000000000..dbedcd760 --- /dev/null +++ b/src/ca65/ea.h @@ -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 + + + diff --git a/src/ca65/ea65.c b/src/ca65/ea65.c new file mode 100644 index 000000000..98c5213ae --- /dev/null +++ b/src/ca65/ea65.c @@ -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; +} + + + diff --git a/src/ca65/ea65.h b/src/ca65/ea65.h new file mode 100644 index 000000000..f5b6c32cd --- /dev/null +++ b/src/ca65/ea65.h @@ -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 + + + diff --git a/src/ca65/easw16.c b/src/ca65/easw16.c new file mode 100644 index 000000000..979eb29af --- /dev/null +++ b/src/ca65/easw16.c @@ -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; + + } +} + + + diff --git a/src/ca65/easw16.h b/src/ca65/easw16.h new file mode 100644 index 000000000..3c8af690a --- /dev/null +++ b/src/ca65/easw16.h @@ -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 + + + + diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 33f364c1a..1cfc5ba30 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -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 */ /*****************************************************************************/ diff --git a/src/ca65/instr.h b/src/ca65/instr.h index de752fd63..4fa99090d 100644 --- a/src/ca65/instr.h +++ b/src/ca65/instr.h @@ -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]; + + + +/*****************************************************************************/ +/* 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 */ /*****************************************************************************/ diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index 950d725dc..97de9ebda 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -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 \ diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index fa7d9ee65..16b4fa109 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -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 \ diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index f68239bcd..d0aaff6df 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -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 (); } } diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 9b8a6dfc2..91c091212 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -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); } diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index 5c19a37f7..cf98dff02 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -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, diff --git a/src/common/cpu.c b/src/common/cpu.c index d83ab53db..52ad2bb5b 100644 --- a/src/common/cpu.c +++ b/src/common/cpu.c @@ -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, }; diff --git a/src/common/cpu.h b/src/common/cpu.h index e0f3387da..f9720bd45 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -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 -- 2.39.5