ftp.nice.ch/pub/next/tools/emulators/vice.0.15.0.NeXT.sd.tgz#/vice-0.15.0/src/asm.c

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.