meow.git
tables.c
/* meow - 6502 assembler
* Copyright (C) 2024-2025 ArcNyxx
* see LICENCE file for licensing information */
#include <ctype.h>
#include <string.h>
#include <stdint.h>
#include "meow.h"
#include "tables.h"
mne_t
mnemonic(char *str)
{
if (strlen(str) != 3)
return INVMNE;
str[0] = toupper(str[0]);
str[1] = toupper(str[1]);
str[2] = toupper(str[2]);
switch (str[0]) {
case 'A':
if (str[1] == 'D' && str[2] == 'C')
return ADC;
if (str[1] == 'N' && str[2] == 'D')
return AND;
if (str[1] == 'S' && str[2] == 'L')
return ASL;
return INVMNE;
case 'B':
if (str[1] == 'C' && str[2] == 'C')
return BCC;
if (str[1] == 'C' && str[2] == 'S')
return BCS;
if (str[1] == 'E' && str[2] == 'Q')
return BEQ;
if (str[1] == 'I' && str[2] == 'T')
return BIT;
if (str[1] == 'M' && str[2] == 'I')
return BMI;
if (str[1] == 'N' && str[2] == 'E')
return BNE;
if (str[1] == 'P' && str[2] == 'L')
return BPL;
if (str[1] == 'R' && str[2] == 'K')
return BRK;
if (str[1] == 'V' && str[2] == 'C')
return BVC;
if (str[1] == 'V' && str[2] == 'S')
return BVS;
return INVMNE;
case 'C':
if (str[1] == 'L' && str[2] == 'C')
return CLC;
if (str[1] == 'L' && str[2] == 'D')
return CLD;
if (str[1] == 'L' && str[2] == 'I')
return CLI;
if (str[1] == 'L' && str[2] == 'V')
return CLV;
if (str[1] == 'M' && str[2] == 'P')
return CMP;
if (str[1] == 'P' && str[2] == 'X')
return CPX;
if (str[1] == 'P' && str[2] == 'Y')
return CPY;
return INVMNE;
case 'D':
if (str[1] == 'E' && str[2] == 'C')
return DEC;
if (str[1] == 'E' && str[2] == 'X')
return DEX;
if (str[1] == 'E' && str[2] == 'Y')
return DEY;
return INVMNE;
case 'E':
if (str[1] == 'O' && str[2] == 'R')
return EOR;
return INVMNE;
case 'I':
if (str[1] == 'N' && str[2] == 'C')
return INC;
if (str[1] == 'N' && str[2] == 'X')
return INX;
if (str[1] == 'N' && str[2] == 'Y')
return INY;
return INVMNE;
case 'J':
if (str[1] == 'M' && str[2] == 'P')
return JMP;
if (str[1] == 'S' && str[2] == 'R')
return JSR;
return INVMNE;
case 'L':
if (str[1] == 'D' && str[2] == 'A')
return LDA;
if (str[1] == 'D' && str[2] == 'X')
return LDX;
if (str[1] == 'D' && str[2] == 'Y')
return LDY;
if (str[1] == 'S' && str[2] == 'R')
return LSR;
return INVMNE;
case 'N':
if (str[1] == 'O' && str[2] == 'P')
return NOP;
return INVMNE;
case 'O':
if (str[1] == 'R' && str[2] == 'A')
return ORA;
return INVMNE;
case 'P':
if (str[1] == 'H' && str[2] == 'A')
return PHA;
if (str[1] == 'H' && str[2] == 'P')
return PHP;
if (str[1] == 'L' && str[2] == 'A')
return PLA;
if (str[1] == 'L' && str[2] == 'P')
return PLP;
return INVMNE;
case 'R':
if (str[1] == 'O' && str[2] == 'L')
return ROL;
if (str[1] == 'O' && str[2] == 'R')
return ROR;
if (str[1] == 'T' && str[2] == 'I')
return RTI;
if (str[1] == 'T' && str[2] == 'S')
return RTS;
return INVMNE;
case 'S':
if (str[1] == 'B' && str[2] == 'C')
return SBC;
if (str[1] == 'E' && str[2] == 'C')
return SEC;
if (str[1] == 'E' && str[2] == 'D')
return SED;
if (str[1] == 'E' && str[2] == 'I')
return SEI;
if (str[1] == 'T' && str[2] == 'A')
return STA;
if (str[1] == 'T' && str[2] == 'X')
return STX;
if (str[1] == 'T' && str[2] == 'Y')
return STY;
return INVMNE;
case 'T':
if (str[1] == 'A' && str[2] == 'X')
return TAX;
if (str[1] == 'A' && str[2] == 'Y')
return TAY;
if (str[1] == 'S' && str[2] == 'X')
return TSX;
if (str[1] == 'X' && str[2] == 'A')
return TXA;
if (str[1] == 'X' && str[2] == 'S')
return TXS;
if (str[1] == 'Y' && str[2] == 'A')
return TYA;
return INVMNE;
default:
return INVMNE;
}
}
uint8_t
opcode(mne_t mne, addr_t addr)
{
switch (mne) {
case ADC:
switch (addr) {
case ABS:
return 0x6d;
case ABSX:
return 0x7d;
case ABSY:
return 0x79;
case IMM:
return 0x69;
case ZP:
return 0x65;
case ZPX:
return 0x75;
case ZPXI:
return 0x61;
case ZPYI:
return 0x71;
default:
return 0xff;
}
case AND:
switch (addr) {
case ABS:
return 0x2d;
case ABSX:
return 0x3d;
case ABSY:
return 0x39;
case IMM:
return 0x29;
case ZP:
return 0x25;
case ZPX:
return 0x35;
case ZPXI:
return 0x21;
case ZPYI:
return 0x31;
default:
return 0xff;
}
case ASL:
switch (addr) {
case ABS:
return 0x0e;
case ABSX:
return 0x1e;
case IMP:
return 0x0a;
case ZP:
return 0x06;
case ZPX:
return 0x16;
default:
return 0xff;
}
case BCC:
switch (addr) {
case REL:
return 0x90;
default:
return 0xff;
}
case BCS:
switch (addr) {
case REL:
return 0xb0;
default:
return 0xff;
}
case BEQ:
switch (addr) {
case REL:
return 0xf0;
default:
return 0xff;
}
case BIT:
switch (addr) {
case ABS:
return 0x2c;
case IMM:
return 0x89;
case ZP:
return 0x24;
default:
return 0xff;
}
case BMI:
switch (addr) {
case REL:
return 0x30;
default:
return 0xff;
}
case BNE:
switch (addr) {
case REL:
return 0xd0;
default:
return 0xff;
}
case BPL:
switch (addr) {
case REL:
return 0x10;
default:
return 0xff;
}
case BRK:
switch (addr) {
case IMP:
return 0x00;
default:
return 0xff;
}
case BVC:
switch (addr) {
case REL:
return 0x50;
default:
return 0xff;
}
case BVS:
switch (addr) {
case REL:
return 0x70;
default:
return 0xff;
}
case CLC:
switch (addr) {
case IMP:
return 0x18;
default:
return 0xff;
}
case CLD:
switch (addr) {
case IMP:
return 0xd8;
default:
return 0xff;
}
case CLI:
switch (addr) {
case IMP:
return 0x58;
default:
return 0xff;
}
case CLV:
switch (addr) {
case IMP:
return 0xb8;
default:
return 0xff;
}
case CMP:
switch (addr) {
case ABS:
return 0xcd;
case ABSX:
return 0xdd;
case ABSY:
return 0xd9;
case IMM:
return 0xc9;
case ZP:
return 0xc5;
case ZPX:
return 0xd5;
case ZPXI:
return 0xc1;
case ZPYI:
return 0xd1;
default:
return 0xff;
}
case CPX:
switch (addr) {
case ABS:
return 0xec;
case IMM:
return 0xe0;
case ZP:
return 0xe4;
default:
return 0xff;
}
case CPY:
switch (addr) {
case ABS:
return 0xcc;
case IMM:
return 0xc0;
case ZP:
return 0xc4;
default:
return 0xff;
}
case DEC:
switch (addr) {
case ABS:
return 0xce;
case ABSX:
return 0xde;
case ZP:
return 0xc6;
case ZPX:
return 0xd6;
default:
return 0xff;
}
case DEX:
switch (addr) {
case IMP:
return 0xca;
default:
return 0xff;
}
case DEY:
switch (addr) {
case IMP:
return 0x88;
default:
return 0xff;
}
case EOR:
switch (addr) {
case ABS:
return 0x4d;
case ABSX:
return 0x5d;
case ABSY:
return 0x59;
case IMM:
return 0x49;
case ZP:
return 0x45;
case ZPX:
return 0x55;
case ZPXI:
return 0x41;
case ZPYI:
return 0x51;
default:
return 0xff;
}
case INC:
switch (addr) {
case ABS:
return 0xee;
case ABSX:
return 0xfe;
case ZP:
return 0xe6;
case ZPX:
return 0xf6;
default:
return 0xff;
}
case INX:
switch (addr) {
case IMP:
return 0xe8;
default:
return 0xff;
}
case INY:
switch (addr) {
case IMP:
return 0xc8;
default:
return 0xff;
}
case JMP:
switch (addr) {
case ABS:
return 0x4c;
case ABSI:
return 0x6c;
default:
return 0xff;
}
case JSR:
switch (addr) {
case ABS:
return 0x20;
default:
return 0xff;
}
case LDA:
switch (addr) {
case ABS:
return 0xad;
case ABSX:
return 0xbd;
case ABSY:
return 0xb9;
case IMM:
return 0xa9;
case ZP:
return 0xa5;
case ZPX:
return 0xb5;
case ZPXI:
return 0xa1;
case ZPYI:
return 0xb1;
default:
return 0xff;
}
case LDX:
switch (addr) {
case ABS:
return 0xae;
case ABSY:
return 0xbe;
case IMM:
return 0xa2;
case ZP:
return 0xa6;
case ZPY:
return 0xb6;
default:
return 0xff;
}
case LDY:
switch (addr) {
case ABS:
return 0xac;
case ABSX:
return 0xbc;
case IMM:
return 0xa0;
case ZP:
return 0xa4;
case ZPX:
return 0xb4;
default:
return 0xff;
}
case LSR:
switch (addr) {
case ABS:
return 0x4e;
case ABSX:
return 0x5e;
case IMP:
return 0x4a;
case ZP:
return 0x46;
case ZPX:
return 0x56;
default:
return 0xff;
}
case NOP:
switch (addr) {
case IMP:
return 0xea;
default:
return 0xff;
}
case ORA:
switch (addr) {
case ABS:
return 0x0d;
case ABSX:
return 0x1d;
case ABSY:
return 0x19;
case IMM:
return 0x09;
case ZP:
return 0x05;
case ZPX:
return 0x15;
case ZPXI:
return 0x01;
case ZPYI:
return 0x11;
default:
return 0xff;
}
case PHA:
switch (addr) {
case IMP:
return 0x48;
default:
return 0xff;
}
case PHP:
switch (addr) {
case IMP:
return 0x08;
default:
return 0xff;
}
case PLA:
switch (addr) {
case IMP:
return 0x68;
default:
return 0xff;
}
case PLP:
switch (addr) {
case IMP:
return 0x28;
default:
return 0xff;
}
case ROL:
switch (addr) {
case ABS:
return 0x2e;
case ABSX:
return 0x3e;
case IMP:
return 0x2a;
case ZP:
return 0x26;
case ZPX:
return 0x36;
default:
return 0xff;
}
case ROR:
switch (addr) {
case ABS:
return 0x6e;
case ABSX:
return 0x7e;
case IMP:
return 0x6a;
case ZP:
return 0x66;
case ZPX:
return 0x76;
default:
return 0xff;
}
case RTI:
switch (addr) {
case IMP:
return 0x40;
default:
return 0xff;
}
case RTS:
switch (addr) {
case IMP:
return 0x60;
default:
return 0xff;
}
case SBC:
switch (addr) {
case ABS:
return 0xed;
case ABSX:
return 0xfd;
case ABSY:
return 0xf9;
case IMM:
return 0xe9;
case ZP:
return 0xe5;
case ZPX:
return 0xf5;
case ZPXI:
return 0xe1;
case ZPYI:
return 0xf1;
default:
return 0xff;
}
case SEC:
switch (addr) {
case IMP:
return 0x38;
default:
return 0xff;
}
case SED:
switch (addr) {
case IMP:
return 0xf8;
default:
return 0xff;
}
case SEI:
switch (addr) {
case IMP:
return 0x78;
default:
return 0xff;
}
case STA:
switch (addr) {
case ABS:
return 0x8d;
case ABSX:
return 0x9d;
case ABSY:
return 0x99;
case ZP:
return 0x85;
case ZPX:
return 0x95;
case ZPXI:
return 0x81;
case ZPYI:
return 0x91;
default:
return 0xff;
}
case STX:
switch (addr) {
case ABS:
return 0x8e;
case ZP:
return 0x86;
case ZPY:
return 0x96;
default:
return 0xff;
}
case STY:
switch (addr) {
case ABS:
return 0x8c;
case ZP:
return 0x84;
case ZPX:
return 0x94;
default:
return 0xff;
}
case TAX:
switch (addr) {
case IMP:
return 0xaa;
default:
return 0xff;
}
case TAY:
switch (addr) {
case IMP:
return 0xa8;
default:
return 0xff;
}
case TSX:
switch (addr) {
case IMP:
return 0xba;
default:
return 0xff;
}
case TXA:
switch (addr) {
case IMP:
return 0x8a;
default:
return 0xff;
}
case TXS:
switch (addr) {
case IMP:
return 0x9a;
default:
return 0xff;
}
case TYA:
switch (addr) {
case IMP:
return 0x98;
default:
return 0xff;
}
default:
return 0xff;
}
}