65c02, rockwell 65c02 support.

This commit is contained in:
Kelvin Sherlock 2016-04-13 12:15:11 -04:00
parent 95ba6e7a48
commit 83c09bbd55
8 changed files with 294 additions and 17 deletions

View File

@ -17,6 +17,9 @@ void actionsImmIndex(opcodeTableEntryType *opcode, int numberOfOperands, valueTy
void actionsIndex(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
void actionsNone(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
void actionsRelative(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
void actionsSTZ(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
void actionsBitZPRelative(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
void actionsBitZP(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands);
bool isByte(int value);
bool isByteOffset(int value);
bool isWordOffset(int value);

View File

@ -55,7 +55,10 @@ actionsDir1(opcodeTableEntryType *opcode, int numberOfOperands, valueType **eval
#define ZERO_PAGE_ADDRESS_BIT 0x00
#define NON_ZERO_PAGE_ADDRESS_BIT 0x08
if(class==EXPRESSION_OPND && isByteAddress(operand) &&
/* only used for BIT */
/* 65c02 bit uses actionsDirX2 */
if (class==EXPRESSION_OPND && isByteAddress(operand) &&
isDefined(operand)){
emitByte(binary | ZERO_PAGE_ADDRESS_BIT);
emitByte(address);
@ -81,10 +84,13 @@ actionsDirIndir(opcodeTableEntryType *opcode, int numberOfOperands, valueType **
{
#define DIRECT_ADDRESS_BIT 0x00
#define INDIRECT_ADDRESS_BIT 0x20
#define INDIRECT_ADDRESS_BIT_X 0x30
if (wordCheck(address)) {
if (class == INDIRECT_OPND)
emitByte(binary | INDIRECT_ADDRESS_BIT);
else if (class == PRE_INDEXED_X_OPND || class == PRE_SELECTED_X_OPND) /* 65c02 jmp (abs,x) */
emitByte(binary | INDIRECT_ADDRESS_BIT_X);
else
emitByte(binary | DIRECT_ADDRESS_BIT);
putFixupsHere(WORD_FIXUP, 0);
@ -132,7 +138,21 @@ actionsDirX2(opcodeTableEntryType *opcode, int numberOfOperands, valueType **eva
#define X_INDEXED_ZERO_PAGE_BITS_X2 0x10
#define X_INDEXED_NON_ZERO_PAGE_BITS_X2 0x18
if (class == EXPRESSION_OPND) {
/*
special case for 65c02 inc a / dec a which were shoe-horned in
*/
if (class == A_REGISTER_OPND) {
emitByte(binary == 0xC6 ? 0x3A : 0x1A);
}
else if (class == IMMEDIATE_OPND) {
/* special case for 65c02 bit #immediate */
if (byteCheck(address)) {
emitByte(0x89);
putFixupsHere(BYTE_FIXUP, 0);
emitByte(address);
}
}
else if (class == EXPRESSION_OPND) {
if (isByteAddress(operand) && isDefined(operand)) {
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_X2);
emitByte(address);
@ -174,6 +194,31 @@ actionsDirX3(opcodeTableEntryType *opcode, int numberOfOperands, valueType **eva
}
}
void
actionsSTZ(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands)
{
/* STZ was shoe-horned in for the 65c02 and the encoding doesn't match up nicely */
if (class == EXPRESSION_OPND) {
if (isByteAddress(operand) && isDefined(operand)) {
emitByte(0x64);
emitByte(address);
} else if (wordCheck(address)) {
emitByte(0x9C);
putFixupsHere(WORD_FIXUP, 0);
emitWord(address);
}
} else {
if (isByteAddress(operand) && isDefined(operand)) {
emitByte(0x74);
emitByte(address);
} else if (wordCheck(address)) {
emitByte(0x9E);
putFixupsHere(WORD_FIXUP, 0);
emitWord(address);
}
}
}
void
actionsDirY(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands)
{
@ -307,6 +352,7 @@ actionsImmIndex(opcodeTableEntryType *opcode, int numberOfOperands, valueType **
#define X_INDEXED_ZERO_PAGE_BITS_A 0x14
#define Y_INDEXED_NON_ZERO_PAGE_BITS_A 0x18
#define X_INDEXED_NON_ZERO_PAGE_BITS_A 0x1C
#define INDIRECT_OPND_BITS_A 0x11
if (class == EXPRESSION_OPND) {
if (isByteAddress(operand) && isDefined(operand)) {
@ -344,6 +390,13 @@ actionsImmIndex(opcodeTableEntryType *opcode, int numberOfOperands, valueType **
putFixupsHere(BYTE_FIXUP, 0);
emitByte(address);
}
} else if (class == INDIRECT_OPND) {
/* 65c02 */
if (byteCheck(address)) {
emitByte(binary + INDIRECT_OPND_BITS_A);
putFixupsHere(BYTE_FIXUP, 0);
emitByte(address);
}
} else {
if (byteCheck(address)) {
emitByte(binary | PRE_INDEXED_BITS_A);
@ -386,6 +439,13 @@ actionsIndex(opcodeTableEntryType *opcode, int numberOfOperands, valueType **eva
putFixupsHere(BYTE_FIXUP, 0);
emitByte(address);
}
} else if (class == INDIRECT_OPND) {
/* 65c02 */
if (byteCheck(address)) {
emitByte(binary + INDIRECT_OPND_BITS_A);
putFixupsHere(BYTE_FIXUP, 0);
emitByte(address);
}
} else {
if (byteCheck(address)) {
emitByte(binary | PRE_INDEXED_BITS_A);
@ -422,6 +482,89 @@ actionsRelative(opcodeTableEntryType *opcode, int numberOfOperands, valueType **
}
}
void
actionsBitZPRelative(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands)
{
/* rockwell 65c02 bbr bit,zp,branch and bbs bit,zp,branch. */
#define operand_0 (evaluatedOperands[0])
#define address_0 (evaluatedOperands[0])->value
#define class_0 (evaluatedOperands[0])->addressMode
#define operand_1 (evaluatedOperands[1])
#define address_1 (evaluatedOperands[1])->value
#define class_1 (evaluatedOperands[1])->addressMode
#define operand_2 (evaluatedOperands[2])
#define address_2 (evaluatedOperands[2])->value
#define class_2 (evaluatedOperands[2])->addressMode
int bit;
int zp;
int offset;
if (class_0 == EXPRESSION_OPND && isDefined(operand_0) && address_0 >= 0 && address_0 <= 7) {
bit = address_0;
} else {
error(BIT_VALUE_TOO_LARGE_ERROR, address_0);
}
if (class_1 == EXPRESSION_OPND && isDefined(operand_1) && isByteAddress(operand_1)) {
zp = address_1;
} else {
error(BYTE_VALUE_TOO_LARGE_ERROR, address_1);
zp = 0;
}
if (operand_2->kindOfValue == UNDEFINED_VALUE || (currentCodeMode ==
RELOCATABLE_BUFFER && targetOffset == 0))
offset = 0;
else
offset = address_2 - (currentLocationCounter.value - targetOffset) - 2;
if (offset < 0)
offset--;
if (isByteOffset(offset)) {
emitByte(binary + (bit << 4));
emitByte(zp);
putFixupsHere(BYTE_RELATIVE_FIXUP, 0);
emitByte(offset);
} else {
error(RELATIVE_OFFSET_TOO_LARGE_ERROR);
}
}
void
actionsBitZP(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands)
{
/* rockwell 65c02 smb bit,zp and rmb bit,zp */
int bit;
int zp;
if (class_0 == EXPRESSION_OPND && isDefined(operand_0) && address_0 >= 0 && address_0 <= 7) {
bit = address_0;
} else {
error(BIT_VALUE_TOO_LARGE_ERROR, address_0);
}
if (class_1 == EXPRESSION_OPND && isDefined(operand_1) && isByteAddress(operand_1)) {
zp = address_1;
} else {
error(BYTE_VALUE_TOO_LARGE_ERROR, address_1);
zp = 0;
}
emitByte(binary + (bit << 4));
emitByte(zp);
}
/*
Miscellaneous helper predicates.
*/

View File

@ -220,6 +220,7 @@ printErrorMessage(errorType theError, va_list ap)
"fatal: no name definition given on command line after '-D'",
"bad name definition: '%s'",
"warning: perform statement has no side effects",
"value %d is too large to fit in a bit",
};
static int errorCount = 0;

View File

@ -45,6 +45,8 @@ extern int yydebug;
static fileNameListType *bottomOfInputFileStack;
static char *outputFileName;
static int machine = 0;
void
chokePukeAndDie(void)
{
@ -257,6 +259,11 @@ initializeStuff(int argc, char **argv)
printVersion();
continue;
case 'x':
/* -x6502 -x65c02 -x65c02s */
machine++;
continue;
case 'Y':
yydebug = TRUE;
continue;
@ -436,6 +443,25 @@ createHashTables(void)
while (newOpcodeEntry->mnemonic != NULL)
hashStringEnter(newOpcodeEntry++, opcodeTable);
if (machine == 0) {
newOpcodeEntry = theOpcodes_02;
while (newOpcodeEntry->mnemonic != NULL)
hashStringEnter(newOpcodeEntry++, opcodeTable);
}
else if (machine == 1) {
newOpcodeEntry = theOpcodes_c02;
while (newOpcodeEntry->mnemonic != NULL)
hashStringEnter(newOpcodeEntry++, opcodeTable);
}
else if (machine >= 2) {
newOpcodeEntry = theOpcodes_c02;
while (newOpcodeEntry->mnemonic != NULL)
hashStringEnter(newOpcodeEntry++, opcodeTable);
newOpcodeEntry = theOpcodes_c02s;
while (newOpcodeEntry->mnemonic != NULL)
hashStringEnter(newOpcodeEntry++, opcodeTable);
}
newKeywordEntry = theKeywords;
while (newKeywordEntry->string != NULL)
hashStringEnter(newKeywordEntry++, keywordTable);

View File

@ -128,6 +128,9 @@ extern macroTableEntryType *macroTable[HASH_TABLE_SIZE];
extern opcodeTableEntryType *opcodeTable[HASH_TABLE_SIZE];
extern opcodeTableEntryType theOpcodes[];
extern opcodeTableEntryType theOpcodes_02[];
extern opcodeTableEntryType theOpcodes_c02[];
extern opcodeTableEntryType theOpcodes_c02s[];
extern keywordTableEntryType *keywordTable[HASH_TABLE_SIZE];

View File

@ -129,14 +129,11 @@ conditionTableEntryType *conditionTable[HASH_TABLE_SIZE];
/* All those NULLs are used to string together lists after this all gets
hashed. */
opcodeTableEntryType theOpcodes[] = {
"adc", NULL, 0x61, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"and", NULL, 0x21, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
opcodeTableEntryType theOpcodes[] = {
"asl", NULL, 0x02, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
"bcc", NULL, 0x90, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
"bcs", NULL, 0xB0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
"beq", NULL, 0xF0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
"bit", NULL, 0x24, DIR_1, DIR_1_CLASS_BITS, 1, 1, 0,
"bmi", NULL, 0x30, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
"bne", NULL, 0xD0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
"bpl", NULL, 0x10, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
@ -147,24 +144,17 @@ opcodeTableEntryType theOpcodes[] = {
"cld", NULL, 0xD8, NONE, NONE_CLASS_BITS, 0, 0, 0,
"cli", NULL, 0x58, NONE, NONE_CLASS_BITS, 0, 0, 0,
"clv", NULL, 0xB8, NONE, NONE_CLASS_BITS, 0, 0, 0,
"cmp", NULL, 0xC1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"cpx", NULL, 0xE0, IMM_DIR, IMM_DIR_CLASS_BITS, 1, 1, 0,
"cpy", NULL, 0xC0, IMM_DIR, IMM_DIR_CLASS_BITS, 1, 1, 0,
"dec", NULL, 0xC6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
"dex", NULL, 0xCA, NONE, NONE_CLASS_BITS, 0, 0, 0,
"dey", NULL, 0x88, NONE, NONE_CLASS_BITS, 0, 0, 0,
"eor", NULL, 0x41, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"inc", NULL, 0xE6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
"inx", NULL, 0xE8, NONE, NONE_CLASS_BITS, 0, 0, 0,
"iny", NULL, 0xC8, NONE, NONE_CLASS_BITS, 0, 0, 0,
"jmp", NULL, 0x4C, DIR_INDIR, DIR_INDIR_CLASS_BITS, 1, 1, 0,
"jsr", NULL, 0x20, DIR_2, DIR_2_CLASS_BITS, 1, 1, 0,
"lda", NULL, 0xA1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"ldx", NULL, 0xA2, IMM_DIR_Y, IMM_DIR_Y_CLASS_BITS, 1, 1, 0,
"ldy", NULL, 0xA0, IMM_DIR_X, IMM_DIR_X_CLASS_BITS, 1, 1, 0,
"lsr", NULL, 0x42, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
"nop", NULL, 0xEA, NONE, NONE_CLASS_BITS, 0, 0, 0,
"ora", NULL, 0x01, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"pha", NULL, 0x48, NONE, NONE_CLASS_BITS, 0, 0, 0,
"php", NULL, 0x08, NONE, NONE_CLASS_BITS, 0, 0, 0,
"pla", NULL, 0x68, NONE, NONE_CLASS_BITS, 0, 0, 0,
@ -173,11 +163,9 @@ opcodeTableEntryType theOpcodes[] = {
"ror", NULL, 0x62, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
"rti", NULL, 0x40, NONE, NONE_CLASS_BITS, 0, 0, 0,
"rts", NULL, 0x60, NONE, NONE_CLASS_BITS, 0, 0, 0,
"sbc", NULL, 0xE1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"sec", NULL, 0x38, NONE, NONE_CLASS_BITS, 0, 0, 0,
"sed", NULL, 0xF8, NONE, NONE_CLASS_BITS, 0, 0, 0,
"sei", NULL, 0x78, NONE, NONE_CLASS_BITS, 0, 0, 0,
"sta", NULL, 0x81, INDEX, INDEX_CLASS_BITS, 1, 1, 0,
"stx", NULL, 0x86, DIR_Y, DIR_Y_CLASS_BITS, 1, 1, 0,
"sty", NULL, 0x84, DIR_X_3, DIR_X_3_CLASS_BITS, 1, 1, 0,
"tax", NULL, 0xAA, NONE, NONE_CLASS_BITS, 0, 0, 0,
@ -189,6 +177,114 @@ opcodeTableEntryType theOpcodes[] = {
NULL, NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
};
opcodeTableEntryType theOpcodes_02[] = {
"bit", NULL, 0x24, DIR_1, DIR_1_CLASS_BITS, 1, 1, 0,
"jmp", NULL, 0x4C, DIR_INDIR, DIR_INDIR_CLASS_BITS, 1, 1, 0,
"dec", NULL, 0xC6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
"inc", NULL, 0xE6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
"sta", NULL, 0x81, INDEX, INDEX_CLASS_BITS, 1, 1, 0,
"adc", NULL, 0x61, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"and", NULL, 0x21, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"cmp", NULL, 0xC1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"eor", NULL, 0x41, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"lda", NULL, 0xA1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"ora", NULL, 0x01, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
"sbc", NULL, 0xE1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
NULL, NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
};
/*
65c02 modifications:
adc (zp)
and (zp)
bit abs,x
bit #immediate
bit zp,x
cmp (zp)
dec a
eor (zp)
inc a
jmp (abs,x)
lda (zp)
ora (zp)
sbc (zp)
sta (zp)
additions:
bra relative
phx
phy
plx
ply
stp
stz abs
stz abs,x
stz zp
stz zp,x
trb abs
trb zp
tsb abs
tsb zp
wai
*/
/*
65c02s additions:
bbr
bbs
rmb
smb
*/
opcodeTableEntryType theOpcodes_c02[] = {
/* updated address modes */
"inc", NULL, 0xE6, DIR_X_2, DIR_X_2_CLASS_BITS|A_REGISTER_OPND_BIT, 1, 1, 0,
"dec", NULL, 0xC6, DIR_X_2, DIR_X_2_CLASS_BITS|A_REGISTER_OPND_BIT, 1, 1, 0,
"bit", NULL, 0x24, DIR_X_2, DIR_X_2_CLASS_BITS|IMMEDIATE_OPND_BIT, 1, 1, 0,
"jmp", NULL, 0x4C, DIR_INDIR, DIR_INDIR_CLASS_BITS|PRE_INDEXED_X_OPND_BIT|PRE_SELECTED_X_OPND_BIT, 1, 1, 0,
"sta", NULL, 0x81, INDEX, INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"adc", NULL, 0x61, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"and", NULL, 0x21, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"cmp", NULL, 0xC1, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"eor", NULL, 0x41, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"lda", NULL, 0xA1, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"ora", NULL, 0x01, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
"sbc", NULL, 0xE1, IMM_INDEX, IMM_INDEX_CLASS_BITS|INDIRECT_OPND_BIT, 1, 1, 0,
/* new instructions */
"bra", NULL, 0x80, RELATIVE, REL_CLASS_BITS, 1, 1, 0, // 65c02
"phx", NULL, 0xDA, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
"phy", NULL, 0x5A, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
"plx", NULL, 0xFA, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
"ply", NULL, 0x7A, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
"stp", NULL, 0xDB, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
"stz", NULL, 0x64, DIR_STZ, DIR_X_2_CLASS_BITS, 1, 1, 0, // 65c02
"trb", NULL, 0x14, DIR_1, DIR_1_CLASS_BITS, 1, 1, 0, // 65c02
"tsb", NULL, 0x04, DIR_1, DIR_1_CLASS_BITS, 1, 1, 0, // 65c02
"wai", NULL, 0xCB, NONE, NONE_CLASS_BITS, 0, 0, 0, // 65c02
NULL, NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
};
opcodeTableEntryType theOpcodes_c02s[] = {
"bbr", NULL, 0x0F, BIT_ZP_REL,ANY_OPND_BITS, 3, 3, 0, // r65c02
"bbs", NULL, 0x8F, BIT_ZP_REL,ANY_OPND_BITS, 3, 3, 0, // r65c02
"rmb", NULL, 0x07, BIT_ZP, ANY_OPND_BITS, 2, 2, 0, // r65c02
"smb", NULL, 0x87, BIT_ZP, ANY_OPND_BITS, 2, 2, 0, // r65c02
NULL, NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
};
int operandClassTable[] = { /* indexed by operandKindType */
EXPRESSION_OPND_BIT,
IMMEDIATE_OPND_BIT,
@ -223,6 +319,9 @@ int (*instructionActionTable[])() = {
actionsNone,
actionsIndex,
actionsImmIndex,
actionsSTZ,
actionsBitZPRelative,
actionsBitZP,
};
/* indexed by symbolUsageKindType */

View File

@ -1075,6 +1075,7 @@ typedef enum {
NO_DASH_D_FILE_NAME_ERROR,
BAD_COMMAND_LINE_DEFINE_ERROR,
PERFORM_WITHOUT_SIDE_EFFECT_ERROR,
BIT_VALUE_TOO_LARGE_ERROR,
} errorType;
#define ERROR_LIMIT 300

View File

@ -48,7 +48,8 @@ typedef enum {
others right too. */
typedef enum {
RELATIVE, DIR_1, DIR_2, DIR_INDIR, DIR_X_1, DIR_X_2, DIR_X_3,
DIR_Y, IMM_DIR, IMM_DIR_X, IMM_DIR_Y, NONE, INDEX, IMM_INDEX
DIR_Y, IMM_DIR, IMM_DIR_X, IMM_DIR_Y, NONE, INDEX, IMM_INDEX,
DIR_STZ, BIT_ZP_REL, BIT_ZP,
} addressClassType;
#define NO_OPND_BIT 0x0000
@ -98,4 +99,4 @@ typedef enum {
POST_INDEXED_Y_OPND_BIT | \
EXPRESSION_OPND_BIT | PRE_SELECTED_X_OPND_BIT
#define MAX_NUMBER_OF_OPERANDS 1
#define MAX_NUMBER_OF_OPERANDS 3