This is asm.c in view mode; [Download] [Up]
/* * asm.h - 6510 assembler-related functions. * * Written by * Vesa-Matti Puro (vmp@lut.fi) * Jarkko Sonninen (sonninen@lut.fi) * Jouko Valta (jopi@stekt.oulu.fi) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ #include "vice.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "asm.h" #include "misc.h" #include "mshell.h" extern BYTE ram[]; /* FIXME: ugly! */ /* ------------------------------------------------------------------------- */ int clength[] = { 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0 }; struct lookup_tag lookup[] = { /**** Positive ****/ /* 00 */ { "BRK", IMPLIED, M_NONE, M_PC, 7, 0 }, /* Pseudo Absolute */ /* 01 */ { "ORA", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X) */ /* 02 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 03 */ { "SLO", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* 04 */ { "NOOP", ZERO_PAGE, M_NONE, M_NONE, 3, 0 }, /* 05 */ { "ORA", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* 06 */ { "ASL", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* 07 */ { "SLO", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* 08 */ { "PHP", IMPLIED, M_SR, M_NONE, 3, 0 }, /* 09 */ { "ORA", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* 0a */ { "ASL", ACCUMULATOR, M_AC, M_AC, 2, 0 }, /* Accumulator */ /* 0b */ { "ANC", IMMEDIATE, M_ACIM, M_ACNC, 2, 0 }, /* 0c */ { "NOOP", ABSOLUTE, M_NONE, M_NONE, 4, 0 }, /* 0d */ { "ORA", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* 0e */ { "ASL", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* 0f */ { "SLO", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* 10 */ { "BPL", RELATIVE, M_REL, M_NONE, 2, 0 }, /* 11 */ { "ORA", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (Indirect),Y */ /* 12 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 13 */ { "SLO", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* 14 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* 15 */ { "ORA", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* 16 */ { "ASL", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* 17 */ { "SLO", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* 18 */ { "CLC", IMPLIED, M_NONE, M_FC, 2, 0 }, /* 19 */ { "ORA", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* 1a */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* 1b */ { "SLO", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* 1c */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* 1d */ { "ORA", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* 1e */ { "ASL", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* 1f */ { "SLO", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* 20 */ { "JSR", ABSOLUTE, M_ADDR, M_PC, 6, 0 }, /* 21 */ { "AND", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X)*/ /* 22 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 23 */ { "RLA", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* 24 */ { "BIT", ZERO_PAGE, M_ZERO, M_NONE, 3, 0 }, /* Zeropage */ /* 25 */ { "AND", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* 26 */ { "ROL", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* 27 */ { "RLA", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* 28 */ { "PLP", IMPLIED, M_NONE, M_SR, 4, 0 }, /* 29 */ { "AND", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* 2a */ { "ROL", ACCUMULATOR, M_AC, M_AC, 2, 0 }, /* Accumulator */ /* 2b */ { "ANC", IMMEDIATE, M_ACIM, M_ACNC, 2, 0 }, /* 2c */ { "BIT", ABSOLUTE, M_ABS, M_NONE, 4, 0 }, /* Absolute */ /* 2d */ { "AND", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* 2e */ { "ROL", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* 2f */ { "RLA", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* 30 */ { "BMI", RELATIVE, M_REL, M_NONE, 2, 0 }, /* 31 */ { "AND", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (Indirect),Y */ /* 32 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 33 */ { "RLA", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* 34 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* 35 */ { "AND", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* 36 */ { "ROL", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* 37 */ { "RLA", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* 38 */ { "SEC", IMPLIED, M_NONE, M_FC, 2, 0 }, /* 39 */ { "AND", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* 3a */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* 3b */ { "RLA", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* 3c */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* 3d */ { "AND", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* 3e */ { "ROL", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* 3f */ { "RLA", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* 40 */ { "RTI", IMPLIED, M_NONE, M_PC, 6, 0 }, /* 41 */ { "EOR", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X) */ /* 42 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 43 */ { "SRE", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* 44 */ { "NOOP", ZERO_PAGE, M_NONE, M_NONE, 3, 0 }, /* 45 */ { "EOR", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* 46 */ { "LSR", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* 47 */ { "SRE", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* 48 */ { "PHA", IMPLIED, M_AC, M_NONE, 3, 0 }, /* 49 */ { "EOR", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* 4a */ { "LSR", ACCUMULATOR, M_AC, M_AC, 2, 0 }, /* Accumulator */ /* 4b */ { "ASR", IMMEDIATE, M_ACIM, M_AC, 2, 0 }, /* (AC & IMM) >>1 */ /* 4c */ { "JMP", ABSOLUTE, M_ADDR, M_PC, 3, 0 }, /* Absolute */ /* 4d */ { "EOR", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* 4e */ { "LSR", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* 4f */ { "SRE", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* 50 */ { "BVC", RELATIVE, M_REL, M_NONE, 2, 0 }, /* 51 */ { "EOR", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (Indirect),Y */ /* 52 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 53 */ { "SRE", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* 54 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* 55 */ { "EOR", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* 56 */ { "LSR", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* 57 */ { "SRE", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* 58 */ { "CLI", IMPLIED, M_NONE, M_FI, 2, 0 }, /* 59 */ { "EOR", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* 5a */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* 5b */ { "SRE", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* 5c */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* 5d */ { "EOR", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* 5e */ { "LSR", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* 5f */ { "SRE", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* 60 */ { "RTS", IMPLIED, M_NONE, M_PC, 6, 0 }, /* 61 */ { "ADC", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X) */ /* 62 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* 63 */ { "RRA", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* 64 */ { "NOOP", ZERO_PAGE, M_NONE, M_NONE, 3, 0 }, /* 65 */ { "ADC", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* 66 */ { "ROR", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* 67 */ { "RRA", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* 68 */ { "PLA", IMPLIED, M_NONE, M_AC, 4, 0 }, /* 69 */ { "ADC", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* 6a */ { "ROR", ACCUMULATOR, M_AC, M_AC, 2, 0 }, /* Accumulator */ /* 6b */ { "ARR", IMMEDIATE, M_ACIM, M_AC, 2, 0 }, /* ARR isn't typo */ /* 6c */ { "JMP", ABS_INDIRECT, M_AIND, M_PC, 5, 0 }, /* Indirect */ /* 6d */ { "ADC", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* 6e */ { "ROR", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* 6f */ { "RRA", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* 70 */ { "BVS", RELATIVE, M_REL, M_NONE, 2, 0 }, /* 71 */ { "ADC", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (Indirect),Y */ /* 72 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT relative? */ /* 73 */ { "RRA", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* 74 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* 75 */ { "ADC", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* 76 */ { "ROR", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* 77 */ { "RRA", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* 78 */ { "SEI", IMPLIED, M_NONE, M_FI, 2, 0 }, /* 79 */ { "ADC", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* 7a */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* 7b */ { "RRA", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* 7c */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* 7d */ { "ADC", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* 7e */ { "ROR", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* 7f */ { "RRA", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /**** Negative ****/ /* 80 */ { "NOOP", IMMEDIATE, M_NONE, M_NONE, 2, 0 }, /* 81 */ { "STA", INDIRECT_X, M_AC, M_INDX, 6, 0 }, /* (Indirect,X) */ /* 82 */ { "NOOP", IMMEDIATE, M_NONE, M_NONE, 2, 0 }, /* 83 */ { "SAX", INDIRECT_X, M_ANXR, M_INDX, 6, 0 }, /* 84 */ { "STY", ZERO_PAGE, M_YR, M_ZERO, 3, 0 }, /* Zeropage */ /* 85 */ { "STA", ZERO_PAGE, M_AC, M_ZERO, 3, 0 }, /* Zeropage */ /* 86 */ { "STX", ZERO_PAGE, M_XR, M_ZERO, 3, 0 }, /* Zeropage */ /* 87 */ { "SAX", ZERO_PAGE, M_ANXR, M_ZERO, 3, 0 }, /* 88 */ { "DEY", IMPLIED, M_YR, M_YR, 2, 0 }, /* 89 */ { "NOOP", IMMEDIATE, M_NONE, M_NONE, 2, 0 }, /* 8a */ { "TXA", IMPLIED, M_XR, M_AC, 2, 0 }, /**** very abnormal: usually AC = AC | #$EE & XR & #$oper ****/ /* 8b */ { "ANE", IMMEDIATE, M_AXIM, M_AC, 2, 0 }, /* 8c */ { "STY", ABSOLUTE, M_YR, M_ABS, 4, 0 }, /* Absolute */ /* 8d */ { "STA", ABSOLUTE, M_AC, M_ABS, 4, 0 }, /* Absolute */ /* 8e */ { "STX", ABSOLUTE, M_XR, M_ABS, 4, 0 }, /* Absolute */ /* 8f */ { "SAX", ABSOLUTE, M_ANXR, M_ABS, 4, 0 }, /* 90 */ { "BCC", RELATIVE, M_REL, M_NONE, 2, 0 }, /* 91 */ { "STA", INDIRECT_Y, M_AC, M_INDY, 6, 0 }, /* (Indirect),Y */ /* 92 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT relative? */ /* 93 */ { "SHA", INDIRECT_Y, M_ANXR, M_STH0, 6, 0 }, /* 94 */ { "STY", ZERO_PAGE_X, M_YR, M_ZERX, 4, 0 }, /* Zeropage,X */ /* 95 */ { "STA", ZERO_PAGE_X, M_AC, M_ZERX, 4, 0 }, /* Zeropage,X */ /* 96 */ { "STX", ZERO_PAGE_Y, M_XR, M_ZERY, 4, 0 }, /* Zeropage,Y */ /* 97 */ { "SAX", ZERO_PAGE_Y, M_ANXR, M_ZERY, 4, 0 }, /* 98 */ { "TYA", IMPLIED, M_YR, M_AC, 2, 0 }, /* 99 */ { "STA", ABSOLUTE_Y, M_AC, M_ABSY, 5, 0 }, /* Absolute,Y */ /* 9a */ { "TXS", IMPLIED, M_XR, M_SP, 2, 0 }, /*** This is very mysterious command ... */ /* 9b */ { "SHS", ABSOLUTE_Y, M_ANXR, M_STH3, 5, 0 }, /* 9c */ { "SHY", ABSOLUTE_X, M_YR, M_STH2, 5, 0 }, /* 9d */ { "STA", ABSOLUTE_X, M_AC, M_ABSX, 5, 0 }, /* Absolute,X */ /* 9e */ { "SHX", ABSOLUTE_Y, M_XR, M_STH1, 5, 0 }, /* 9f */ { "SHA", ABSOLUTE_Y, M_ANXR, M_STH1, 5, 0 }, /* a0 */ { "LDY", IMMEDIATE, M_IMM, M_YR, 2, 0 }, /* Immediate */ /* a1 */ { "LDA", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X) */ /* a2 */ { "LDX", IMMEDIATE, M_IMM, M_XR, 2, 0 }, /* Immediate */ /* a3 */ { "LAX", INDIRECT_X, M_INDX, M_ACXR, 6, 0 }, /* (indirect,X) */ /* a4 */ { "LDY", ZERO_PAGE, M_ZERO, M_YR, 3, 0 }, /* Zeropage */ /* a5 */ { "LDA", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* a6 */ { "LDX", ZERO_PAGE, M_ZERO, M_XR, 3, 0 }, /* Zeropage */ /* a7 */ { "LAX", ZERO_PAGE, M_ZERO, M_ACXR, 3, 0 }, /* a8 */ { "TAY", IMPLIED, M_AC, M_YR, 2, 0 }, /* a9 */ { "LDA", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* aa */ { "TAX", IMPLIED, M_AC, M_XR, 2, 0 }, /* ab */ { "LXA", IMMEDIATE, M_ACIM, M_ACXR, 2, 0 }, /* LXA isn't a typo */ /* ac */ { "LDY", ABSOLUTE, M_ABS, M_YR, 4, 0 }, /* Absolute */ /* ad */ { "LDA", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* ae */ { "LDX", ABSOLUTE, M_ABS, M_XR, 4, 0 }, /* Absolute */ /* af */ { "LAX", ABSOLUTE, M_ABS, M_ACXR, 4, 0 }, /* b0 */ { "BCS", RELATIVE, M_REL, M_NONE, 2, 0 }, /* b1 */ { "LDA", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (indirect),Y */ /* b2 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* b3 */ { "LAX", INDIRECT_Y, M_INDY, M_ACXR, 5, 1 }, /* b4 */ { "LDY", ZERO_PAGE_X, M_ZERX, M_YR, 4, 0 }, /* Zeropage,X */ /* b5 */ { "LDA", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* b6 */ { "LDX", ZERO_PAGE_Y, M_ZERY, M_XR, 4, 0 }, /* Zeropage,Y */ /* b7 */ { "LAX", ZERO_PAGE_Y, M_ZERY, M_ACXR, 4, 0 }, /* b8 */ { "CLV", IMPLIED, M_NONE, M_FV, 2, 0 }, /* b9 */ { "LDA", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* ba */ { "TSX", IMPLIED, M_SP, M_XR, 2, 0 }, /* bb */ { "LAS", ABSOLUTE_Y, M_SABY, M_ACXS, 4, 1 }, /* bc */ { "LDY", ABSOLUTE_X, M_ABSX, M_YR, 4, 1 }, /* Absolute,X */ /* bd */ { "LDA", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* be */ { "LDX", ABSOLUTE_Y, M_ABSY, M_XR, 4, 1 }, /* Absolute,Y */ /* bf */ { "LAX", ABSOLUTE_Y, M_ABSY, M_ACXR, 4, 1 }, /* c0 */ { "CPY", IMMEDIATE, M_IMM, M_NONE, 2, 0 }, /* Immediate */ /* c1 */ { "CMP", INDIRECT_X, M_INDX, M_NONE, 6, 0 }, /* (Indirect,X) */ /* c2 */ { "NOOP", IMMEDIATE, M_NONE, M_NONE, 2, 0 }, /* occasional TILT */ /* c3 */ { "DCP", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* c4 */ { "CPY", ZERO_PAGE, M_ZERO, M_NONE, 3, 0 }, /* Zeropage */ /* c5 */ { "CMP", ZERO_PAGE, M_ZERO, M_NONE, 3, 0 }, /* Zeropage */ /* c6 */ { "DEC", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* c7 */ { "DCP", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* c8 */ { "INY", IMPLIED, M_YR, M_YR, 2, 0 }, /* c9 */ { "CMP", IMMEDIATE, M_IMM, M_NONE, 2, 0 }, /* Immediate */ /* ca */ { "DEX", IMPLIED, M_XR, M_XR, 2, 0 }, /* cb */ { "SBX", IMMEDIATE, M_IMM, M_XR, 2, 0 }, /* cc */ { "CPY", ABSOLUTE, M_ABS, M_NONE, 4, 0 }, /* Absolute */ /* cd */ { "CMP", ABSOLUTE, M_ABS, M_NONE, 4, 0 }, /* Absolute */ /* ce */ { "DEC", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* cf */ { "DCP", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* d0 */ { "BNE", RELATIVE, M_REL, M_NONE, 2, 0 }, /* d1 */ { "CMP", INDIRECT_Y, M_INDY, M_NONE, 5, 1 }, /* (Indirect),Y */ /* d2 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* d3 */ { "DCP", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* d4 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* d5 */ { "CMP", ZERO_PAGE_X, M_ZERX, M_NONE, 4, 0 }, /* Zeropage,X */ /* d6 */ { "DEC", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* d7 */ { "DCP", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* d8 */ { "CLD", IMPLIED, M_NONE, M_FD, 2, 0 }, /* d9 */ { "CMP", ABSOLUTE_Y, M_ABSY, M_NONE, 4, 1 }, /* Absolute,Y */ /* da */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* db */ { "DCP", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* dc */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* dd */ { "CMP", ABSOLUTE_X, M_ABSX, M_NONE, 4, 1 }, /* Absolute,X */ /* de */ { "DEC", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* df */ { "DCP", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* e0 */ { "CPX", IMMEDIATE, M_IMM, M_NONE, 2, 0 }, /* Immediate */ /* e1 */ { "SBC", INDIRECT_X, M_INDX, M_AC, 6, 0 }, /* (Indirect,X) */ /* e2 */ { "NOOP", IMMEDIATE, M_NONE, M_NONE, 2, 0 }, /* e3 */ { "ISB", INDIRECT_X, M_INDX, M_INDX, 8, 0 }, /* e4 */ { "CPX", ZERO_PAGE, M_ZERO, M_NONE, 3, 0 }, /* Zeropage */ /* e5 */ { "SBC", ZERO_PAGE, M_ZERO, M_AC, 3, 0 }, /* Zeropage */ /* e6 */ { "INC", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* Zeropage */ /* e7 */ { "ISB", ZERO_PAGE, M_ZERO, M_ZERO, 5, 0 }, /* e8 */ { "INX", IMPLIED, M_XR, M_XR, 2, 0 }, /* e9 */ { "SBC", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* Immediate */ /* ea */ { "NOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* eb */ { "USBC", IMMEDIATE, M_IMM, M_AC, 2, 0 }, /* same as e9 */ /* ec */ { "CPX", ABSOLUTE, M_ABS, M_NONE, 4, 0 }, /* Absolute */ /* ed */ { "SBC", ABSOLUTE, M_ABS, M_AC, 4, 0 }, /* Absolute */ /* ee */ { "INC", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* Absolute */ /* ef */ { "ISB", ABSOLUTE, M_ABS, M_ABS, 6, 0 }, /* f0 */ { "BEQ", RELATIVE, M_REL, M_NONE, 2, 0 }, /* f1 */ { "SBC", INDIRECT_Y, M_INDY, M_AC, 5, 1 }, /* (Indirect),Y */ /* f2 */ { "JAM", IMPLIED, M_NONE, M_NONE, 0, 0 }, /* TILT */ /* f3 */ { "ISB", INDIRECT_Y, M_INDY, M_INDY, 8, 0 }, /* f4 */ { "NOOP", ZERO_PAGE_X, M_NONE, M_NONE, 4, 0 }, /* f5 */ { "SBC", ZERO_PAGE_X, M_ZERX, M_AC, 4, 0 }, /* Zeropage,X */ /* f6 */ { "INC", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* Zeropage,X */ /* f7 */ { "ISB", ZERO_PAGE_X, M_ZERX, M_ZERX, 6, 0 }, /* f8 */ { "SED", IMPLIED, M_NONE, M_FD, 2, 0 }, /* f9 */ { "SBC", ABSOLUTE_Y, M_ABSY, M_AC, 4, 1 }, /* Absolute,Y */ /* fa */ { "NOOP", IMPLIED, M_NONE, M_NONE, 2, 0 }, /* fb */ { "ISB", ABSOLUTE_Y, M_ABSY, M_ABSY, 7, 0 }, /* fc */ { "NOOP", ABSOLUTE_X, M_NONE, M_NONE, 4, 1 }, /* fd */ { "SBC", ABSOLUTE_X, M_ABSX, M_AC, 4, 1 }, /* Absolute,X */ /* fe */ { "INC", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 }, /* Absolute,X */ /* ff */ { "ISB", ABSOLUTE_X, M_ABSX, M_ABSX, 7, 0 } }; char *modename[] = { "IMPLIED", "ACCUMULATOR", "IMMEDIATE", #ifdef EXTENDED_CPU "IMMEDIATE_WORD", "ZERO_PAGE", "ZERO_PAGE_X", "ZERO_PAGE_Y", "ABSOLUTE", "ABSOLUTE_X", "ABSOLUTE_Y", "INDIRECT", "INDIRECT_X", "INDIRECT_Y", "INDIRECT_Z", "ABS_INDIRECT", "ABS_INDIR_X", "RELATIVE", "RELATIVE_LONG", "ZERO_RELATIVE", "STACK_RELATIVE_Y", #else "ZERO_PAGE", "ZERO_PAGE_X", "ZERO_PAGE_Y", "ABSOLUTE", "ABSOLUTE_X", "ABSOLUTE_Y", "ABS_INDIRECT", "INDIRECT_X", "INDIRECT_Y", "RELATIVE", #endif "ASS_CODE" }; /* ADDRESSING MODES */ /* ------------------------------------------------------------------------- */ /* local */ #if 0 /* DS : NO LONGER USED */ static int interpret_line(char *, ADDRESS *, int ); int interpret_instr(char *, ADDRESS , int ); int find_instr(char *); static int parse_arguments(ADDRESS , int , char *, BYTE *, int *, int ); /* * This function implements a simple MOS6502 assembler. * The interpreter selects default number base according to the * value of hexflg. */ int ass(ADDRESS addr, int mode) { char *line, prompt[10]; int cnt; int errors = 0; for (;;) { sprintf(prompt, ".%04x ", addr); line = read_line(prompt, 0); /* mode & MODE_INF */ if (line == NULL || *line == 'x') break; else if ((cnt = interpret_line(line, &addr, mode)) >= 0) { /* addr += cnt; */ } else { printf("**** %04X ", addr); switch(cnt) { /* Line syntax */ case E_SYNTAX: printf(EM_SYNTAX); break; case E_PARSE_ERROR: printf(EM_PARSE_ERROR); break; case E_TOO_MANY_ERRORS: /* Don't print */ break; /* Assembler */ case E_BAD_IDENTIFIER: printf(EM_BAD_IDENTIFIER); break; case E_SYMBOL_UNDEFINED: printf(EM_SYMBOL_UNDEFINED); break; case E_SYMBOL_REDEF: printf(EM_SYMBOL_REDEF); break; case E_PC_DECREMENT: printf(EM_PC_DECREMENT); /*non-intract*/ break; /* Mnemonic */ case E_BAD_MNEM: printf(EM_BAD_MNEM); break; case E_LONG_BRANCH: printf(EM_LONG_BRANCH); break; case E_MISSING_OPER: printf(EM_MISSING_OPER); break; /* Operand syntax */ case E_PARAMETER_SYNTAX: printf(EM_PARAMETER_SYNTAX); break; case E_TOO_MANY_COMMAS: printf(EM_TOO_MANY_COMMAS); break; case E_RIGHT_PARENTHESIS: printf(EM_RIGHT_PARENTHESIS); break; case E_LEFT_PARENTHESIS: printf(EM_LEFT_PARENTHESIS); break; case E_PARENTHESIS: printf(EM_PARENTHESIS); break; case E_MIXED_XY: printf(EM_MIXED_XY); break; case E_MISSING_XY: printf(EM_MISSING_XY); break; case E_BAD_INDEX: printf(EM_BAD_INDEX); break; default: printf("SYNTAX ERROR (%d)", cnt); } printf(": %s ****\n", line); if ( ++errors >= ERRORS_TO_STOP) { printf("%s\nStop.\n\n", EM_TOO_MANY_ERRORS); return (E_TOO_MANY_ERRORS); } } } /* for */ return (E_OK); } /* * This routine interprets assembly lines which are not direct mode * commands for the program itself. * Second iteration is done if the line contains address declaration. */ static int interpret_line(char *line, ADDRESS *addr, int mode) { int len = 0; int attempt = 0; ADDRESS adr = *addr; do { while (*line && isspace((int)*line)) line++; if (!*line) return 0; /* line doesn't contain any text */ /* * Machine language commands * Return if any mnemonic is found or error occurred. */ #ifdef HAS_ZILOG_Z80 if (mode & MODE_ZILOG) { if ((len = parse_z80_instr(line, adr, ram, mode)) > 0) { *addr = (len + adr); /* addr is changed only on success */ return (len); } } else #endif if ((len = interpret_instr(line, adr, mode)) > 0) { *addr = (len + adr); /* addr is changed only on success */ return (len); } if (len != E_BAD_MNEM) return (len); /* * Change address */ if (!*line || !sconv(line, 0, mode | MODE_QUERY)) return(E_BAD_IDENTIFIER); adr = sconv(line, 0, mode); while(*++line > ' '); if (mode & MODE_VERBOSE) printf("\nrescan %04x ===>%s<===\n", adr, line); } while(*line && !attempt++); return (E_SYNTAX); } /* end of interpret_line */ /* * Machine language commands * This routine interprets all 6502 intructions. On success data is * stored to memory and number of bytes is returned, otherwise possible * error code is returned. */ int interpret_instr(char *line, ADDRESS adr, int mode) { int i = 0; int instr = 0; int len = 0; unsigned char arg[4]; /* * First all legal mnemonics are searched and if right instruction is * found the remaining line is parsed. The numeric code of the * instruction is returned and arguments are returned in arg array. */ if ((i = find_instr(line)) >= 0) { if (lookup[i].mnemonic[3]) ++line; /* USBC, NOOP, RBMn ... */ instr = parse_arguments (adr, i, (strlen(line) > 3 ? &line[3] : NULL), arg, &len, mode); if (instr < 0) return (instr); /* Error code from parse_arguments */ ram[adr] = instr; if (len) memcpy(ram + adr + 1, arg, len); if (!(mode & MODE_QUIET)) { printf(".%04X %02X ", adr, instr); switch (len) { case 0: printf("\t%s\n", sprint_opcode(adr, 1)); break; case 1: printf("%02X\t%s\n", arg[0], sprint_opcode(adr, 1)); break; case 2: printf("%02X %02X\t%s\n", arg[0], arg[1], sprint_opcode(adr, 1)); } } return (++len); } /* end of matching mnemonic */ return (E_BAD_MNEM); } /* end of interpret_instr */ int find_instr(char *line) { int i; while (*line && isspace((int)*line)) line++; if (!*line) return (-1); /* line doesn't contain any mnemonic */ for (i = 0; line[i] && i < 3; i++) { if (isalpha ((int)line[i])) line[i] = toupper (line[i]); } for (i = 0; i < TOTAL_CODES; i++) if (0 == strncmp(lookup[i].mnemonic, line, 3) && (lookup[i].mnemonic[3] < ' ' || lookup[i].mnemonic[3] == line[3])) return (i); /* USBC, NOOP, RBMn ... */ return (-1); } static int parse_arguments(ADDRESS adr, int code, char *line, BYTE *arg, int *len, int mode) { int tstflg = mode & MODE_VERBOSE; int comma_found = 0; /* True if argument contains comma. */ int right_parenthesis = 0; int left_parenthesis = 0; int x_found = 0; int y_found = 0; int z_found = 0; int zero_page = 0; int addr_mode = 0; int i, ival; char *linep; while (line && *line && isspace((int)*line)) line++; if (NULL == line || !*line) { /* IMPLIED addressing mode. */ for (i = code; i <= OP_IMPL_MAX; i += OP_IMPL_SPC) if (((IMPLIED == lookup[i].addr_mode) || (ACCUMULATOR == lookup[i].addr_mode)) && 0 == strcmp(lookup[code].mnemonic, lookup[i].mnemonic)) { *len = 0; return i; } return (E_MISSING_OPER); } if (tstflg) printf("CODE %d strlen %d --%s--\n", code, (int)strlen(line), line); /* * Explicit ACCUMULATOR addressing. If the length of the argument is 1 * and if this argument is A, appropriate machine code with right address * mode is right is chosen, otherwise E_PARAMETER_SYNTAX is returned. * This errorcode means that argument is A (=accumulator), but this * instruction does not support accumulator addressing. If the parameter * A is not present then it matches IMPLIED address mode above. */ if (mode & MODE_SYMBOL) { if (1 == strlen(line) && (*line == 'A' || *line == 'a')) { for (i = code; i <= OP_ACCU_MAX; i += OP_MNEM_SPC) if (ACCUMULATOR == lookup[i].addr_mode && 0 == strcmp(lookup[code].mnemonic, lookup[i].mnemonic)) { *len = 0; return i; } return E_PARAMETER_SYNTAX; } if (tstflg) printf("ACCU testattu\n"); } /* IMMEDIATE addressing mode */ if (*line == '#') { for (i = code; i < OP_IMM_MAX; ++i) if (IMMEDIATE == lookup[i].addr_mode && 0 == strcmp(lookup[code].mnemonic, lookup[i].mnemonic)) { *len = 1; *arg = (BYTE) sconv(&line[1], 0, mode); return i; } return E_PARAMETER_SYNTAX; } /* Next check if relative addressing mode was used. */ if (RELATIVE == lookup[i = code].addr_mode) { if ((mode & MODE_HEX) && *line == '$') /* Skip if not prefix */ ++line; ival = sconv(line, 0, mode); *len = 1; if (tstflg) { printf("addressing mode RELATIVE\n"); printf("rel disp %d %04x\n", ival - adr - 2, ival - adr - 2); } if ((ival -= (adr + 2)) <= 127 && ival >= -128) { *arg = (BYTE) ((ival) & 0xFF); return i; } return E_LONG_BRANCH; } /* * Now it's time to parse absolute and zeropage addressing modes with * their indexed and indirect versions. First check if there are any * commas. And count also parenthesis. * * There are some addressing modes not implemented on each processor, * but they are not #ifdef'ed out to keep the parser more consistent. * With 6510 family, the additional modes will be filtered out via * failing to find any command actually using those addressing modes. */ linep = line; while (*linep) switch (*linep++) { case ')': ++right_parenthesis; break; case '(': ++left_parenthesis; break; case ',': ++comma_found; while (*linep == ' ') linep++; if (*linep) { switch (toupper(*linep)) { case 'X': ++x_found; ++linep; break; case 'Y': ++y_found; ++linep; break; case 'Z': ++z_found; ++linep; #ifdef EXTENDED_CPU break; case 'S': /* (disp,sp),y */ if (!strncmp ("sp),y", linep, 5)) { addr_mode = STACK_RELATIVE_Y; linep += 5; /* To implement other modes, set comma_found = 0; */ } #endif } /* switch */ if (*linep && !isspace((int)*linep) && *linep != ')') return E_BAD_INDEX; } } if (comma_found > 1) /* There cannot be more than 1 comma found! */ return E_TOO_MANY_COMMAS; if (left_parenthesis > 1) /* Only one '(' can be found. */ return E_LEFT_PARENTHESIS; if (right_parenthesis > 1) /* Only one ')' can be found. */ return E_RIGHT_PARENTHESIS; if (left_parenthesis != right_parenthesis) /* Must be equal. */ return E_PARENTHESIS; if (comma_found && !(x_found || y_found || z_found)) return E_MISSING_XY; if ((x_found + y_found + z_found) > 1) return E_MIXED_XY; /* Only one index register allowed */ linep = line; if (right_parenthesis) while (*linep && (*linep++ != '(')); ival = sconv(linep, 0, mode); if (tstflg) printf("integer: %d\n", ival); if (right_parenthesis && !comma_found) addr_mode = ABS_INDIRECT; if (ival < 256) zero_page = 1; if (zero_page) { if (!right_parenthesis && !comma_found) addr_mode = ZERO_PAGE; if (x_found) addr_mode = (!right_parenthesis ? ZERO_PAGE_X : INDIRECT_X); if (y_found) addr_mode = (!right_parenthesis ? ZERO_PAGE_Y : INDIRECT_Y); #ifdef EXTENDED_CPU if (z_found && right_parenthesis) addr_mode = INDIRECT_Z; if (right_parenthesis && !comma_found) addr_mode = INDIRECT; #endif } else { if (!right_parenthesis) { if (!comma_found) addr_mode = ABSOLUTE; if (x_found) addr_mode = ABSOLUTE_X; if (y_found) addr_mode = ABSOLUTE_Y; } #ifdef EXTENDED_CPU else if (x_found && right_parenthesis) addr_mode = ABS_INDIR_X; #endif } if (tstflg) printf("addressing mode 1 : %s -- code $%02x\n", modename[addr_mode], code); if (!addr_mode) return E_SYNTAX; /* * Addressing mode was found and the appropriate opcode is being selected */ for (i = code; i < TOTAL_CODES; ++i) if (addr_mode == lookup[i].addr_mode && 0 == strcmp(lookup[code].mnemonic, lookup[i].mnemonic)) { switch (addr_mode) { case ZERO_PAGE: case ZERO_PAGE_X: case ZERO_PAGE_Y: case INDIRECT_X: case INDIRECT_Y: #ifdef EXTENDED_CPU case INDIRECT_Z: case INDIRECT: case STACK_RELATIVE_Y: #endif *len = 1; *arg = (BYTE) ival; break; case ABS_INDIRECT: if ((ival & 0xff) == 0xff) printf("%04X: Warning: Indirect JMP($%04X)\n", adr, ival); /* The famous bug in jmp($indirect) */ /* fall trough */ #ifdef EXTENDED_CPU case ABS_INDIR_X: #endif case ABSOLUTE: case ABSOLUTE_X: case ABSOLUTE_Y: *len = 2; *arg++ = (BYTE) ival & 0xFF; *arg = (BYTE) (ival >> 8) & 0xFF; } return i; } /* * If machine code has not zeropage addressing mode, absolute addressing * mode is tried instead. */ if (tstflg) printf("addressing mode 2 : ABSOLUTE\n"); if (ZERO_PAGE == addr_mode || ZERO_PAGE_Y == addr_mode) { addr_mode += (ABSOLUTE - ZERO_PAGE); for (i = code; i <= OP_ABS_MAX; i += OP_ABS_SPC) if (addr_mode == lookup[i].addr_mode && 0 == strcmp(lookup[code].mnemonic, lookup[i].mnemonic)) { *len = 2; *arg++ = (BYTE) ival & 0xFF; *arg = (BYTE) (ival >> 8) & 0xFF; return i; } } if(tstflg) fprintf(stderr, "addressing mode failed\n"); return E_SYNTAX; /* Illegal address mode */ } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.