beebasm

changeset 22:3f1b3ffd6beb v1.04

BeebASM v1.04 - first released Dec 02 2009 21:24:57
author Samwise <samwise@bagshot-row.org>
date Sun May 02 12:29:28 2010 +0100
parents 5db9dbc9a87d
children 1f49259b73aa
files about.txt beebasm.exe src/asmexception.h src/assemble.cpp src/commands.cpp src/expression.cpp src/lineparser.cpp src/lineparser.h src/main.cpp src/objectcode.cpp src/objectcode.h src/sourcefile.cpp src/sourcefile.h
diffstat 13 files changed, 377 insertions(+), 174 deletions(-) [+]
line diff
     1.1 --- a/about.txt	Sun May 02 12:27:54 2010 +0100
     1.2 +++ b/about.txt	Sun May 02 12:29:28 2010 +0100
     1.3 @@ -1,10 +1,10 @@
     1.4  *******************************************************************************
     1.5  *                                                                             *
     1.6 -*                               BeebAsm V1.02                                 *
     1.7 +*                               BeebAsm V1.04                                 *
     1.8  *                                                                             *
     1.9  *             A portable 6502 assembler with BBC Micro style syntax           *
    1.10  *                                                                             *
    1.11 -*                  Copyright (C) Rich Talbot-Watkins 2007, 2008               *
    1.12 +*              Copyright (C) Rich Talbot-Watkins 2007, 2008, 2009             *
    1.13  *                            <rich_tw@hotmail.com>                            *
    1.14  *                                                                             *
    1.15  *    This program is free software: you can redistribute it and/or modify     *
    1.16 @@ -270,6 +270,15 @@
    1.17    blocks.  This is exactly equivalent to BBC BASIC's 'P%=<addr>'.
    1.18  
    1.19  
    1.20 +CPU <n>
    1.21 +
    1.22 +  Selects the target CPU, which determines the range of instructions that
    1.23 +  will be accepted. The default is 0, which provides the original 6502
    1.24 +  instruction set. The only current alternative is 1, which provides the
    1.25 +  65C02 instruction set (including PLX, TRB etc, but not the Rockwell
    1.26 +  additions like BBR).
    1.27 +
    1.28 +
    1.29  SKIP <bytes>
    1.30  
    1.31    Moves the address pointer on by the specified number of bytes.  Use this to
    1.32 @@ -310,6 +319,11 @@
    1.33    Insert the specified 16-bit word(s) into the code.
    1.34  
    1.35  
    1.36 +EQUD a [, b, c, ...]
    1.37 +
    1.38 +  Insert the specified 32-bit word(s) into the code.
    1.39 +
    1.40 +
    1.41  EQUS "string" [, "string", byte, ...]
    1.42  
    1.43    Inserts the specified string into the code.  Note that this can take a comma-
    1.44 @@ -421,7 +435,7 @@
    1.45              STX product:STX product+1:RTS
    1.46  
    1.47  
    1.48 -IF...ELSE...ENDIF
    1.49 +IF...ELIF...ELSE...ENDIF
    1.50  
    1.51    Use to assemble conditionally.  Like anything else in BeebAsm, these
    1.52    statements can be placed on one line, separated by colons, but even if they
    1.53 @@ -442,6 +456,17 @@
    1.54  
    1.55              IF debugraster:LDA #3:STA &FE21:ENDIF
    1.56  
    1.57 +            IF rom
    1.58 +              ORG &8000
    1.59 +              GUARD &C000
    1.60 +            ELIF tube
    1.61 +              ORG &B800
    1.62 +              GUARD &F800
    1.63 +            ELSE
    1.64 +              ORG &3C00
    1.65 +              GUARD &7C00
    1.66 +            ENDIF
    1.67 +
    1.68  
    1.69  { ... }
    1.70  
    1.71 @@ -583,6 +608,10 @@
    1.72  
    1.73  9. VERSION HISTORY
    1.74  
    1.75 +02/12/2009  1.04  Additions by Kevin Bracey:
    1.76 +                  Added 65C02 instruction set and CPU directive.
    1.77 +                  Added ELIF, EQUD.
    1.78 +                  SKIP now lists the current address.
    1.79  27/07/2009  1.03  Bugfix: Corrected the unary < and > operators to
    1.80                    correspond to HI and LO as appropriate.
    1.81                    Added '$' as a valid hex literal prefix.
     2.1 Binary file beebasm.exe has changed
     3.1 --- a/src/asmexception.h	Sun May 02 12:27:54 2010 +0100
     3.2 +++ b/src/asmexception.h	Sun May 02 12:29:28 2010 +0100
     3.3 @@ -187,10 +187,9 @@
     3.4  DEFINE_SYNTAX_EXCEPTION( ImmNegative, "Constant cannot be negative." );
     3.5  DEFINE_SYNTAX_EXCEPTION( UnexpectedComma, "Unexpected comma enountered." );
     3.6  DEFINE_SYNTAX_EXCEPTION( NoImmediate, "Immediate mode not allowed for this instruction." );
     3.7 -DEFINE_SYNTAX_EXCEPTION( NoIndirect16, "16-bit indirect mode not allowed for this instruction." );
     3.8 +DEFINE_SYNTAX_EXCEPTION( NoIndirect, "Indirect mode not allowed for this instruction." );
     3.9  DEFINE_SYNTAX_EXCEPTION( 6502Bug, "JMP (addr) will not execute as intended due to the 6502 bug (addr = &xxFF)." );
    3.10  DEFINE_SYNTAX_EXCEPTION( BadIndirect, "Incorrectly formed indirect instruction." );
    3.11 -DEFINE_SYNTAX_EXCEPTION( NoIndirect, "Indirect mode not allowed for this instruction." );
    3.12  DEFINE_SYNTAX_EXCEPTION( NotZeroPage, "Address is not in zero-page." );
    3.13  DEFINE_SYNTAX_EXCEPTION( BranchOutOfRange, "Branch out of range." );
    3.14  DEFINE_SYNTAX_EXCEPTION( NoAbsolute, "Absolute addressing mode not allowed for this instruction." );
    3.15 @@ -211,6 +210,7 @@
    3.16  DEFINE_SYNTAX_EXCEPTION( MismatchedBraces, "Mismatched braces." );
    3.17  DEFINE_SYNTAX_EXCEPTION( CantInclude, "Cannot include a source file within a FOR loop or braced block." );
    3.18  DEFINE_SYNTAX_EXCEPTION( ElseWithoutIf, "ELSE without IF." );
    3.19 +DEFINE_SYNTAX_EXCEPTION( ElifWithoutIf, "ELIF without IF." );
    3.20  DEFINE_SYNTAX_EXCEPTION( EndifWithoutIf, "ENDIF without IF." );
    3.21  DEFINE_SYNTAX_EXCEPTION( IfWithoutEndif, "IF without ENDIF." );
    3.22  DEFINE_SYNTAX_EXCEPTION( TooManyIFs, "Too many nested IFs." );
     4.1 --- a/src/assemble.cpp	Sun May 02 12:27:54 2010 +0100
     4.2 +++ b/src/assemble.cpp	Sun May 02 12:29:28 2010 +0100
     4.3 @@ -35,71 +35,82 @@
     4.4  
     4.5  
     4.6  
     4.7 -#define DATA( op, imp, acc, imm, zp, zpx, zpy, abs, absx, absy, indx, indy, ind16, rel )  \
     4.8 -	{ { imp, acc, imm, zp, zpx, zpy, abs, absx, absy, indx, indy, ind16, rel }, op }
     4.9 +#define DATA( cpu, op, imp, acc, imm, zp, zpx, zpy, abs, absx, absy, ind, indx, indy, ind16, ind16x, rel )  \
    4.10 +	{ { imp, acc, imm, zp, zpx, zpy, abs, absx, absy, ind, indx, indy, ind16, ind16x, rel }, op, cpu }
    4.11  
    4.12  #define X -1
    4.13  
    4.14 -LineParser::OpcodeData	LineParser::m_gaOpcodeTable[] =
    4.15 +const LineParser::OpcodeData	LineParser::m_gaOpcodeTable[] =
    4.16  {
    4.17 -//					IMP		ACC		IMM		ZP		ZPX		ZPY		ABS		ABSX	ABSY	INDX	INDY	IND16	REL
    4.18 +//					IMP		ACC		IMM		ZP		ZPX		ZPY		ABS		ABSX	ABSY	IND		INDX	INDY	IND16	IND16X	REL
    4.19  
    4.20 -	DATA( "ADC",	 X,		 X,		0x69,	0x65,	0x75,	 X,		0x6D,	0x7D,	0x79,	0x61,	0x71,	 X,		 X		),
    4.21 -	DATA( "AND",	 X,		 X,		0x29,	0x25,	0x35,	 X,		0x2D,	0x3D,	0x39,	0x21,	0x31,	 X,		 X		),
    4.22 -	DATA( "ASL",	 X,		0x0A,	 X,		0x06,	0x16,	 X,		0x0E,	0x1E,	 X,		 X,		 X,		 X,		 X		),
    4.23 -	DATA( "BCC",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x90	),
    4.24 -	DATA( "BCS",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xB0	),
    4.25 -	DATA( "BEQ",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xF0	),
    4.26 -	DATA( "BIT",	 X,		 X,		 X,		0x24,	 X,		 X,		0x2C,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.27 -	DATA( "BMI",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x30	),
    4.28 -	DATA( "BNE",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xD0	),
    4.29 -	DATA( "BPL",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x10	),
    4.30 -	DATA( "BRK",	0x00,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.31 -	DATA( "BVC",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x50	),
    4.32 -	DATA( "BVS",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x70	),
    4.33 -	DATA( "CLC",	0x18,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.34 -	DATA( "CLD",	0xD8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.35 -	DATA( "CLI",	0x58,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.36 -	DATA( "CLV",	0xB8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.37 -	DATA( "CMP",	 X,		 X,		0xC9,	0xC5,	0xD5,	 X,		0xCD,	0xDD,	0xD9,	0xC1,	0xD1,	 X,		 X		),
    4.38 -	DATA( "CPX",	 X,		 X,		0xE0,	0xE4,	 X,		 X,		0xEC,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.39 -	DATA( "CPY",	 X,		 X,		0xC0,	0xC4,	 X,		 X,		0xCC,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.40 -	DATA( "DEC",	 X,		 X,		 X,		0xC6,	0xD6,	 X,		0xCE,	0xDE,	 X,		 X,		 X,		 X,		 X		),
    4.41 -	DATA( "DEX",	0xCA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.42 -	DATA( "DEY",	0x88,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.43 -	DATA( "EOR",	 X,		 X,		0x49,	0x45,	0x55,	 X,		0x4D,	0x5D,	0x59,	0x41,	0x51,	 X,		 X		),
    4.44 -	DATA( "INC",	 X,		 X,		 X,		0xE6,	0xF6,	 X,		0xEE,	0xFE,	 X,		 X,		 X,		 X,		 X		),
    4.45 -	DATA( "INX",	0xE8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.46 -	DATA( "INY",	0xC8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.47 -	DATA( "JMP",	 X,		 X,		 X,		 X,		 X,		 X,		0x4C,	 X,		 X,		 X,		 X,		0x6C,	 X		),
    4.48 -	DATA( "JSR",	 X,		 X,		 X,		 X,		 X,		 X,		0x20,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.49 -	DATA( "LDA",	 X,		 X,		0xA9,	0xA5,	0xB5,	 X,		0xAD,	0xBD,	0xB9,	0xA1,	0xB1,	 X,		 X		),
    4.50 -	DATA( "LDX",	 X,		 X,		0xA2,	0xA6,	 X,		0xB6,	0xAE,	 X,		0xBE,	 X,		 X,		 X,		 X		),
    4.51 -	DATA( "LDY",	 X,		 X,		0xA0,	0xA4,	0xB4,	 X,		0xAC,	0xBC,	 X,		 X,		 X,		 X,		 X		),
    4.52 -	DATA( "LSR",	 X,		0x4A,	 X,		0x46,	0x56,	 X,		0x4E,	0x5E,	 X,		 X,		 X,		 X,		 X		),
    4.53 -	DATA( "NOP",	0xEA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.54 -	DATA( "ORA",	 X,		 X,		0x09,	0x05,	0x15,	 X,		0x0D,	0x1D,	0x19,	0x01,	0x11,	 X,		 X		),
    4.55 -	DATA( "PHA",	0x48,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.56 -	DATA( "PHP",	0x08,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.57 -	DATA( "PLA",	0x68,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.58 -	DATA( "PLP",	0x28,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.59 -	DATA( "ROL",	 X,		0x2A,	 X,		0x26,	0x36,	 X,		0x2E,	0x3E,	 X,		 X,		 X,		 X,		 X		),
    4.60 -	DATA( "ROR",	 X,		0x6A,	 X,		0x66,	0x76,	 X,		0x6E,	0x7E,	 X,		 X,		 X,		 X,		 X		),
    4.61 -	DATA( "RTI",	0x40,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.62 -	DATA( "RTS",	0x60,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.63 -	DATA( "SBC",	 X,		 X,		0xE9,	0xE5,	0xF5,	 X,		0xED,	0xFD,	0xF9,	0xE1,	0xF1,	 X,		 X		),
    4.64 -	DATA( "SEC",	0x38,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.65 -	DATA( "SED",	0xF8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.66 -	DATA( "SEI",	0x78,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.67 -	DATA( "STA",	 X,		 X,		 X,		0x85,	0x95,	 X,		0x8D,	0x9D,	0x99,	0x81,	0x91,	 X,		 X		),
    4.68 -	DATA( "STX",	 X,		 X,		 X,		0x86,	 X,		0x96,	0x8E,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.69 -	DATA( "STY",	 X,		 X,		 X,		0x84,	0x94,	 X,		0x8C,	 X,		 X,		 X,		 X,		 X,		 X		),
    4.70 -	DATA( "TAX",	0xAA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.71 -	DATA( "TAY",	0xA8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.72 -	DATA( "TSX",	0xBA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.73 -	DATA( "TXA",	0x8A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.74 -	DATA( "TXS",	0x9A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.75 -	DATA( "TYA",	0x98,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		)
    4.76 +	DATA( 0, "ADC",	 X,		 X,		0x69,	0x65,	0x75,	 X,		0x6D,	0x7D,	0x79,	0x172,	0x61,	0x71,	 X,		 X,		 X		),
    4.77 +	DATA( 0, "AND",	 X,		 X,		0x29,	0x25,	0x35,	 X,		0x2D,	0x3D,	0x39,	0x132,	0x21,	0x31,	 X,		 X,		 X		),
    4.78 +	DATA( 0, "ASL",	 X,		0x0A,	 X,		0x06,	0x16,	 X,		0x0E,	0x1E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.79 +	DATA( 0, "BCC",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x90	),
    4.80 +	DATA( 0, "BCS",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xB0	),
    4.81 +	DATA( 0, "BEQ",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xF0	),
    4.82 +	DATA( 0, "BIT",	 X,		 X,		0x189,	0x24,	0x134,	 X,		0x2C,	0x13C,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.83 +	DATA( 0, "BMI",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x30	),
    4.84 +	DATA( 0, "BNE",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0xD0	),
    4.85 +	DATA( 0, "BPL",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x10	),
    4.86 +	DATA( 1, "BRA",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x180	),
    4.87 +	DATA( 0, "BRK",	0x00,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.88 +	DATA( 0, "BVC",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x50	),
    4.89 +	DATA( 0, "BVS",	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		0x70	),
    4.90 +	DATA( 0, "CLC",	0x18,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.91 +	DATA( 0, "CLD",	0xD8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.92 +	DATA( 0, "CLI",	0x58,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.93 +	DATA( 1, "CLR",	 X,		 X,		 X,		0x164,	0x174,	 X,		0x19C,	0x19E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.94 +	DATA( 0, "CLV",	0xB8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.95 +	DATA( 0, "CMP",	 X,		 X,		0xC9,	0xC5,	0xD5,	 X,		0xCD,	0xDD,	0xD9,	0x1D2,	0xC1,	0xD1,	 X,		 X,		 X		),
    4.96 +	DATA( 0, "CPX",	 X,		 X,		0xE0,	0xE4,	 X,		 X,		0xEC,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.97 +	DATA( 0, "CPY",	 X,		 X,		0xC0,	0xC4,	 X,		 X,		0xCC,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.98 +	DATA( 1, "DEA",	0x13A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
    4.99 +	DATA( 0, "DEC",	 X,		0x13A,	 X,		0xC6,	0xD6,	 X,		0xCE,	0xDE,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.100 +	DATA( 0, "DEX",	0xCA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.101 +	DATA( 0, "DEY",	0x88,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.102 +	DATA( 0, "EOR",	 X,		 X,		0x49,	0x45,	0x55,	 X,		0x4D,	0x5D,	0x59,	0x152,	0x41,	0x51,	 X,		 X,		 X		),
   4.103 +	DATA( 1, "INA",	0x11A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.104 +	DATA( 0, "INC",	 X,		0x11A,	 X,		0xE6,	0xF6,	 X,		0xEE,	0xFE,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.105 +	DATA( 0, "INX",	0xE8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.106 +	DATA( 0, "INY",	0xC8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.107 +	DATA( 0, "JMP",	 X,		 X,		 X,		 X,		 X,		 X,		0x4C,	 X,		 X,		 X,		 X,		 X,		0x6C,	0x17C,	 X		),
   4.108 +	DATA( 0, "JSR",	 X,		 X,		 X,		 X,		 X,		 X,		0x20,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.109 +	DATA( 0, "LDA",	 X,		 X,		0xA9,	0xA5,	0xB5,	 X,		0xAD,	0xBD,	0xB9,	0x1B2,	0xA1,	0xB1,	 X,		 X,		 X		),
   4.110 +	DATA( 0, "LDX",	 X,		 X,		0xA2,	0xA6,	 X,		0xB6,	0xAE,	 X,		0xBE,	 X,		 X,		 X,		 X,		 X,		 X		),
   4.111 +	DATA( 0, "LDY",	 X,		 X,		0xA0,	0xA4,	0xB4,	 X,		0xAC,	0xBC,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.112 +	DATA( 0, "LSR",	 X,		0x4A,	 X,		0x46,	0x56,	 X,		0x4E,	0x5E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.113 +	DATA( 0, "NOP",	0xEA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.114 +	DATA( 0, "ORA",	 X,		 X,		0x09,	0x05,	0x15,	 X,		0x0D,	0x1D,	0x19,	0x112,	0x01,	0x11,	 X,		 X,		 X		),
   4.115 +	DATA( 0, "PHA",	0x48,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.116 +	DATA( 0, "PHP",	0x08,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.117 +	DATA( 1, "PHX",	0x1DA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.118 +	DATA( 1, "PHY",	0x15A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.119 +	DATA( 0, "PLA",	0x68,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.120 +	DATA( 0, "PLP",	0x28,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.121 +	DATA( 1, "PLX",	0x1FA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.122 +	DATA( 1, "PLY",	0x17A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.123 +	DATA( 0, "ROL",	 X,		0x2A,	 X,		0x26,	0x36,	 X,		0x2E,	0x3E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.124 +	DATA( 0, "ROR",	 X,		0x6A,	 X,		0x66,	0x76,	 X,		0x6E,	0x7E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.125 +	DATA( 0, "RTI",	0x40,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.126 +	DATA( 0, "RTS",	0x60,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.127 +	DATA( 0, "SBC",	 X,		 X,		0xE9,	0xE5,	0xF5,	 X,		0xED,	0xFD,	0xF9,	0x1F2,	0xE1,	0xF1,	 X,		 X,		 X		),
   4.128 +	DATA( 0, "SEC",	0x38,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.129 +	DATA( 0, "SED",	0xF8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.130 +	DATA( 0, "SEI",	0x78,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.131 +	DATA( 0, "STA",	 X,		 X,		 X,		0x85,	0x95,	 X,		0x8D,	0x9D,	0x99,	0x192,	0x81,	0x91,	 X,		 X,		 X		),
   4.132 +	DATA( 0, "STX",	 X,		 X,		 X,		0x86,	 X,		0x96,	0x8E,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.133 +	DATA( 0, "STY",	 X,		 X,		 X,		0x84,	0x94,	 X,		0x8C,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.134 +	DATA( 1, "STZ",	 X,		 X,		 X,		0x164,	0x174,	 X,		0x19C,	0x19E,	 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.135 +	DATA( 0, "TAX",	0xAA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.136 +	DATA( 0, "TAY",	0xA8,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.137 +	DATA( 1, "TRB",	 X,		 X,		 X,		0x114,	 X,		 X,		0x11C,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.138 +	DATA( 1, "TSB",	 X,		 X,		 X,		0x104,	 X,		 X,		0x10C,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.139 +	DATA( 0, "TSX",	0xBA,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.140 +	DATA( 0, "TXA",	0x8A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.141 +	DATA( 0, "TXS",	0x9A,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		),
   4.142 +	DATA( 0, "TYA",	0x98,	 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X,		 X		)
   4.143  };
   4.144  
   4.145  
   4.146 @@ -122,9 +133,14 @@
   4.147  {
   4.148  	for ( int i = 0; i < static_cast<int>( sizeof m_gaOpcodeTable / sizeof( OpcodeData ) ); i++ )
   4.149  	{
   4.150 +		int			cpu		= m_gaOpcodeTable[ i ].m_cpu;
   4.151  		const char*	token	= m_gaOpcodeTable[ i ].m_pName;
   4.152  		size_t		len		= strlen( token );
   4.153  
   4.154 +		// ignore instructions not for current cpu
   4.155 +		if ( cpu > ObjectCode::Instance().GetCPU() )
   4.156 +			continue;
   4.157 +
   4.158  		// create lower-case version of token
   4.159  
   4.160  		char tokenLC[ 16 ];
   4.161 @@ -156,7 +172,8 @@
   4.162  /*************************************************************************************************/
   4.163  bool LineParser::HasAddressingMode( int instructionIndex, ADDRESSING_MODE mode )
   4.164  {
   4.165 -	return ( m_gaOpcodeTable[ instructionIndex ].m_aOpcodes[ mode ] != -1 );
   4.166 +	int i = m_gaOpcodeTable[ instructionIndex ].m_aOpcodes[ mode ];
   4.167 +	return ( i != -1 && (i & 0xFF00) <= (ObjectCode::Instance().GetCPU() << 8) );
   4.168  }
   4.169  
   4.170  
   4.171 @@ -171,7 +188,7 @@
   4.172  	int i = m_gaOpcodeTable[ instructionIndex ].m_aOpcodes[ mode ];
   4.173  
   4.174  	assert( i != -1 );
   4.175 -	return static_cast< unsigned int >( i );
   4.176 +	return static_cast< unsigned int >( i & 0xFF );
   4.177  }
   4.178  
   4.179  
   4.180 @@ -236,7 +253,7 @@
   4.181  		{
   4.182  			cout << "#";
   4.183  		}
   4.184 -		else if ( mode == INDX || mode == INDY )
   4.185 +		else if ( mode == IND || mode == INDX || mode == INDY )
   4.186  		{
   4.187  			cout << "(";
   4.188  		}
   4.189 @@ -258,6 +275,10 @@
   4.190  		{
   4.191  			cout << ",Y";
   4.192  		}
   4.193 +		else if ( mode == IND )
   4.194 +		{
   4.195 +			cout << ")";
   4.196 +		}
   4.197  		else if ( mode == INDX )
   4.198  		{
   4.199  			cout << ",X)";
   4.200 @@ -303,7 +324,7 @@
   4.201  		cout << setw(2) << ( ( value >> 8 ) & 0xFF ) << "   ";
   4.202  		cout << m_gaOpcodeTable[ instructionIndex ].m_pName << " ";
   4.203  
   4.204 -		if ( mode == IND16 )
   4.205 +		if ( mode == IND16 || mode == IND16X )
   4.206  		{
   4.207  			cout << "(";
   4.208  		}
   4.209 @@ -322,6 +343,10 @@
   4.210  		{
   4.211  			cout << ")";
   4.212  		}
   4.213 +		else if ( mode == IND16X )
   4.214 +		{
   4.215 +			cout << ",X)";
   4.216 +		}
   4.217  
   4.218  		cout << endl << nouppercase << dec << setfill( ' ' );
   4.219  	}
   4.220 @@ -471,34 +496,53 @@
   4.221  			}
   4.222  		}
   4.223  
   4.224 -		// the only valid character to find here is ',' for (ind,X) and ')' for (ind),Y and (ind16)
   4.225 -
   4.226 -		// check (ind16) and (ind),Y
   4.227 +		// the only valid character to find here is ',' for (ind,X) or (ind16,X) and ')' for (ind),Y or (ind16) or (ind)
   4.228 +		// we know that ind and ind16 forms are exclusive
   4.229 +		// check (ind), (ind16) and (ind),Y
   4.230  
   4.231  		if ( m_line[ m_column ] == ')' )
   4.232  		{
   4.233  			m_column++;
   4.234  
   4.235 -			// check (ind16)
   4.236 +			// check (ind) and (ind16)
   4.237  
   4.238  			if ( !AdvanceAndCheckEndOfStatement() )
   4.239  			{
   4.240 -				// nothing else here - must be ind16... see if this is allowed!
   4.241 +				// nothing else here - must be ind or ind16... see if this is allowed!
   4.242  
   4.243 -				if ( !HasAddressingMode( instruction, IND16 ) )
   4.244 +				if ( HasAddressingMode( instruction, IND16 ) )
   4.245  				{
   4.246 -					throw AsmException_SyntaxError_NoIndirect16( m_line, oldColumn );
   4.247 +					// It is definitely ind16 mode - check for the 6502 bug
   4.248 +
   4.249 +					if ( ( value & 0xFF ) == 0xFF )
   4.250 +					{
   4.251 +						// victim of the 6502 bug!  throw an error
   4.252 +						throw AsmException_SyntaxError_6502Bug( m_line, oldColumn + 1 );
   4.253 +					}
   4.254 +
   4.255 +					Assemble3( instruction, IND16, value );
   4.256 +					return;
   4.257  				}
   4.258  
   4.259 -				// It is definitely ind16 mode - check for the 6502 bug
   4.260 -
   4.261 -				if ( ( value & 0xFF ) == 0xFF )
   4.262 +				if ( !HasAddressingMode( instruction, IND ) )
   4.263  				{
   4.264 -					// victim of the 6502 bug!  throw an error
   4.265 -					throw AsmException_SyntaxError_6502Bug( m_line, oldColumn + 1 );
   4.266 +					throw AsmException_SyntaxError_NoIndirect( m_line, oldColumn );
   4.267  				}
   4.268  
   4.269 -				Assemble3( instruction, IND16, value );
   4.270 +				// assemble (ind) instruction
   4.271 +
   4.272 +				if ( value > 0xFF )
   4.273 +				{
   4.274 +					// it's not ZP and it must be
   4.275 +					throw AsmException_SyntaxError_NotZeroPage( m_line, oldColumn + 1 );
   4.276 +				}
   4.277 +
   4.278 +				if ( value < 0 )
   4.279 +				{
   4.280 +					throw AsmException_SyntaxError_BadAddress( m_line, oldColumn + 1 );
   4.281 +				}
   4.282 +
   4.283 +				Assemble2( instruction, IND, value );
   4.284  				return;
   4.285  			}
   4.286  
   4.287 @@ -559,7 +603,7 @@
   4.288  			throw AsmException_SyntaxError_BadIndirect( m_line, m_column );
   4.289  		}
   4.290  
   4.291 -		// check (ind,X)
   4.292 +		// check (ind,X) or (ind16,X)
   4.293  
   4.294  		if ( m_line[ m_column ] == ',' )
   4.295  		{
   4.296 @@ -599,6 +643,14 @@
   4.297  				throw AsmException_SyntaxError_BadIndirect( m_line, m_column );
   4.298  			}
   4.299  
   4.300 +			if ( HasAddressingMode( instruction, IND16X ) )
   4.301 +			{
   4.302 +				// It is definitely ind16,x mode
   4.303 +
   4.304 +				Assemble3( instruction, IND16X, value );
   4.305 +				return;
   4.306 +			}
   4.307 +
   4.308  			// It is definitely (ind,X) - check we can use it
   4.309  
   4.310  			if ( !HasAddressingMode( instruction, INDX ) )
   4.311 @@ -624,7 +676,7 @@
   4.312  			return;
   4.313  		}
   4.314  
   4.315 -		// If we got here, we identified neither (ind16), (ind,X) nor (ind),Y
   4.316 +		// If we got here, we identified none of (ind), (ind16), (ind,X), (ind16,X) or (ind),Y
   4.317  		// Therefore we throw a syntax error
   4.318  
   4.319  		throw AsmException_SyntaxError_BadIndirect( m_line, m_column );
     5.1 --- a/src/commands.cpp	Sun May 02 12:27:54 2010 +0100
     5.2 +++ b/src/commands.cpp	Sun May 02 12:29:28 2010 +0100
     5.3 @@ -37,34 +37,36 @@
     5.4  
     5.5  using namespace std;
     5.6  
     5.7 -
     5.8 -LineParser::Token	LineParser::m_gaTokenTable[] =
     5.9 +const LineParser::Token	LineParser::m_gaTokenTable[] =
    5.10  {
    5.11 -	{ ".",			&LineParser::HandleDefineLabel },
    5.12 -	{ "\\",			&LineParser::HandleDefineComment },
    5.13 -	{ ";",			&LineParser::HandleDefineComment },
    5.14 -	{ ":",			&LineParser::HandleStatementSeparator },
    5.15 -	{ "PRINT",		&LineParser::HandlePrint },
    5.16 -	{ "ORG",		&LineParser::HandleOrg },
    5.17 -	{ "INCLUDE",	&LineParser::HandleInclude },
    5.18 -	{ "EQUB",		&LineParser::HandleEqub },
    5.19 -	{ "EQUS",		&LineParser::HandleEqub },
    5.20 -	{ "EQUW",		&LineParser::HandleEquw },
    5.21 -	{ "SAVE",		&LineParser::HandleSave },
    5.22 -	{ "FOR",		&LineParser::HandleFor },
    5.23 -	{ "NEXT",		&LineParser::HandleNext },
    5.24 -	{ "IF",			&LineParser::HandleIf },
    5.25 -	{ "ELSE",		&LineParser::HandleElse },
    5.26 -	{ "ENDIF",		&LineParser::HandleEndif },
    5.27 -	{ "ALIGN",		&LineParser::HandleAlign },
    5.28 -	{ "SKIPTO",		&LineParser::HandleSkipTo },
    5.29 -	{ "SKIP",		&LineParser::HandleSkip },
    5.30 -	{ "GUARD",		&LineParser::HandleGuard },
    5.31 -	{ "CLEAR",		&LineParser::HandleClear },
    5.32 -	{ "INCBIN",		&LineParser::HandleIncBin },
    5.33 -	{ "{",			&LineParser::HandleOpenBrace },
    5.34 -	{ "}",			&LineParser::HandleCloseBrace },
    5.35 -	{ "MAPCHAR",	&LineParser::HandleMapChar }
    5.36 +	{ ".",			&LineParser::HandleDefineLabel,			0 }, // Why is gcc forcing me to
    5.37 +	{ "\\",			&LineParser::HandleDefineComment,		0 }, // put all these 0s in?
    5.38 +	{ ";",			&LineParser::HandleDefineComment,		0 },
    5.39 +	{ ":",			&LineParser::HandleStatementSeparator,	0 },
    5.40 +	{ "PRINT",		&LineParser::HandlePrint,				0 },
    5.41 +	{ "CPU",		&LineParser::HandleCpu,					0 },
    5.42 +	{ "ORG",		&LineParser::HandleOrg,					0 },
    5.43 +	{ "INCLUDE",	&LineParser::HandleInclude,				0 },
    5.44 +	{ "EQUB",		&LineParser::HandleEqub,				0 },
    5.45 +	{ "EQUD",		&LineParser::HandleEqud,				0 },
    5.46 +	{ "EQUS",		&LineParser::HandleEqub,				0 },
    5.47 +	{ "EQUW",		&LineParser::HandleEquw,				0 },
    5.48 +	{ "SAVE",		&LineParser::HandleSave,				0 },
    5.49 +	{ "FOR",		&LineParser::HandleFor,					0 },
    5.50 +	{ "NEXT",		&LineParser::HandleNext,				0 },
    5.51 +	{ "IF",			&LineParser::HandleIf,					&SourceFile::AddIfLevel },
    5.52 +	{ "ELIF",		&LineParser::HandleIf,					&SourceFile::StartElif },
    5.53 +	{ "ELSE",		&LineParser::HandleDirective,			&SourceFile::StartElse },
    5.54 +	{ "ENDIF",		&LineParser::HandleDirective,			&SourceFile::RemoveIfLevel },
    5.55 +	{ "ALIGN",		&LineParser::HandleAlign,				0 },
    5.56 +	{ "SKIPTO",		&LineParser::HandleSkipTo,				0 },
    5.57 +	{ "SKIP",		&LineParser::HandleSkip,				0 },
    5.58 +	{ "GUARD",		&LineParser::HandleGuard,				0 },
    5.59 +	{ "CLEAR",		&LineParser::HandleClear,				0 },
    5.60 +	{ "INCBIN",		&LineParser::HandleIncBin,				0 },
    5.61 +	{ "{",			&LineParser::HandleOpenBrace,			0 },
    5.62 +	{ "}",			&LineParser::HandleCloseBrace,			0 },
    5.63 +	{ "MAPCHAR",	&LineParser::HandleMapChar,				0 }
    5.64  };
    5.65  
    5.66  
    5.67 @@ -199,6 +201,23 @@
    5.68  
    5.69  /*************************************************************************************************/
    5.70  /**
    5.71 +	LineParser::HandleDirective()
    5.72 +*/
    5.73 +/*************************************************************************************************/
    5.74 +void LineParser::HandleDirective()
    5.75 +{
    5.76 +	// directive that doesn't need extra handling; just check rest of line is empty
    5.77 +	if ( AdvanceAndCheckEndOfStatement() )
    5.78 +	{
    5.79 +		// found nothing
    5.80 +		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
    5.81 +	}
    5.82 +}
    5.83 +
    5.84 +
    5.85 +
    5.86 +/*************************************************************************************************/
    5.87 +/**
    5.88  	LineParser::HandleOrg()
    5.89  */
    5.90  /*************************************************************************************************/
    5.91 @@ -224,6 +243,30 @@
    5.92  
    5.93  /*************************************************************************************************/
    5.94  /**
    5.95 +	LineParser::HandleCpu()
    5.96 +*/
    5.97 +/*************************************************************************************************/
    5.98 +void LineParser::HandleCpu()
    5.99 +{
   5.100 +	int newCpu = EvaluateExpressionAsInt();
   5.101 +	if ( newCpu < 0 || newCpu > 1 )
   5.102 +	{
   5.103 +		throw AsmException_SyntaxError_OutOfRange( m_line, m_column );
   5.104 +	}
   5.105 +
   5.106 +	ObjectCode::Instance().SetCPU( newCpu );
   5.107 +
   5.108 +	if ( m_line[ m_column ] == ',' )
   5.109 +	{
   5.110 +		// Unexpected comma (remembering that an expression can validly end with a comma)
   5.111 +		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   5.112 +	}
   5.113 +}
   5.114 +
   5.115 +
   5.116 +
   5.117 +/*************************************************************************************************/
   5.118 +/**
   5.119  	LineParser::HandleGuard()
   5.120  */
   5.121  /*************************************************************************************************/
   5.122 @@ -415,6 +458,12 @@
   5.123  		throw AsmException_SyntaxError_ImmNegative( m_line, oldColumn );
   5.124  	}
   5.125  
   5.126 +	if ( GlobalData::Instance().ShouldOutputAsm() )
   5.127 +	{
   5.128 +		cout << uppercase << hex << setfill( '0' ) << "     ";
   5.129 +		cout << setw(4) << ObjectCode::Instance().GetPC() << endl;
   5.130 +	}
   5.131 +
   5.132  	for ( int i = 0; i < val; i++ )
   5.133  	{
   5.134  		try
   5.135 @@ -796,6 +845,80 @@
   5.136  
   5.137  /*************************************************************************************************/
   5.138  /**
   5.139 +	LineParser::HandleEqud()
   5.140 +*/
   5.141 +/*************************************************************************************************/
   5.142 +void LineParser::HandleEqud()
   5.143 +{
   5.144 +	do
   5.145 +	{
   5.146 +		int value;
   5.147 +
   5.148 +		try
   5.149 +		{
   5.150 +			value = EvaluateExpressionAsInt();
   5.151 +		}
   5.152 +		catch ( AsmException_SyntaxError_SymbolNotDefined& e )
   5.153 +		{
   5.154 +			if ( GlobalData::Instance().IsFirstPass() )
   5.155 +			{
   5.156 +				value = 0;
   5.157 +			}
   5.158 +			else
   5.159 +			{
   5.160 +				throw;
   5.161 +			}
   5.162 +		}
   5.163 +
   5.164 +		if ( GlobalData::Instance().ShouldOutputAsm() )
   5.165 +		{
   5.166 +			cout << uppercase << hex << setfill( '0' ) << "     ";
   5.167 +			cout << setw(4) << ObjectCode::Instance().GetPC() << "   ";
   5.168 +			cout << setw(2) << ( value & 0xFF ) << " ";
   5.169 +			cout << setw(2) << ( ( value & 0xFF00 ) >> 8 ) << " ";
   5.170 +			cout << setw(2) << ( ( value & 0xFF0000 ) >> 16 ) << " ";
   5.171 +			cout << setw(2) << ( ( value & 0xFF000000 ) >> 24 );
   5.172 +			cout << endl << nouppercase << dec << setfill( ' ' );
   5.173 +		}
   5.174 +
   5.175 +		try
   5.176 +		{
   5.177 +			ObjectCode::Instance().PutByte( value & 0xFF );
   5.178 +			ObjectCode::Instance().PutByte( ( value & 0xFF00 ) >> 8 );
   5.179 +			ObjectCode::Instance().PutByte( ( value & 0xFF0000 ) >> 16 );
   5.180 +			ObjectCode::Instance().PutByte( ( value & 0xFF000000 ) >> 24 );
   5.181 +		}
   5.182 +		catch ( AsmException_AssembleError& e )
   5.183 +		{
   5.184 +			e.SetString( m_line );
   5.185 +			e.SetColumn( m_column );
   5.186 +			throw;
   5.187 +		}
   5.188 +
   5.189 +		if ( !AdvanceAndCheckEndOfStatement() )
   5.190 +		{
   5.191 +			break;
   5.192 +		}
   5.193 +
   5.194 +		if ( m_line[ m_column ] != ',' )
   5.195 +		{
   5.196 +			throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
   5.197 +		}
   5.198 +
   5.199 +		m_column++;
   5.200 +
   5.201 +		if ( !AdvanceAndCheckEndOfStatement() )
   5.202 +		{
   5.203 +			throw AsmException_SyntaxError_EmptyExpression( m_line, m_column );
   5.204 +		}
   5.205 +
   5.206 +	} while ( true );
   5.207 +}
   5.208 +
   5.209 +
   5.210 +
   5.211 +/*************************************************************************************************/
   5.212 +/**
   5.213  	LineParser::HandleSave()
   5.214  */
   5.215  /*************************************************************************************************/
   5.216 @@ -1129,6 +1252,7 @@
   5.217  /*************************************************************************************************/
   5.218  void LineParser::HandleIf()
   5.219  {
   5.220 +	// Handles both IF and ELIF
   5.221  	int condition = EvaluateExpressionAsInt();
   5.222  	m_sourceFile->SetCurrentIfCondition( condition );
   5.223  
   5.224 @@ -1143,38 +1267,6 @@
   5.225  
   5.226  /*************************************************************************************************/
   5.227  /**
   5.228 -	LineParser::HandleElse()
   5.229 -*/
   5.230 -/*************************************************************************************************/
   5.231 -void LineParser::HandleElse()
   5.232 -{
   5.233 -	if ( AdvanceAndCheckEndOfStatement() )
   5.234 -	{
   5.235 -		// found nothing
   5.236 -		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
   5.237 -	}
   5.238 -}
   5.239 -
   5.240 -
   5.241 -
   5.242 -/*************************************************************************************************/
   5.243 -/**
   5.244 -	LineParser::HandleEndif()
   5.245 -*/
   5.246 -/*************************************************************************************************/
   5.247 -void LineParser::HandleEndif()
   5.248 -{
   5.249 -	if ( AdvanceAndCheckEndOfStatement() )
   5.250 -	{
   5.251 -		// found nothing
   5.252 -		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
   5.253 -	}
   5.254 -}
   5.255 -
   5.256 -
   5.257 -
   5.258 -/*************************************************************************************************/
   5.259 -/**
   5.260  	LineParser::HandlePrint()
   5.261  
   5.262  	Handle PRINT token.
     6.1 --- a/src/expression.cpp	Sun May 02 12:27:54 2010 +0100
     6.2 +++ b/src/expression.cpp	Sun May 02 12:29:28 2010 +0100
     6.3 @@ -39,7 +39,7 @@
     6.4  
     6.5  
     6.6  
     6.7 -LineParser::Operator	LineParser::m_gaBinaryOperatorTable[] =
     6.8 +const LineParser::Operator	LineParser::m_gaBinaryOperatorTable[] =
     6.9  {
    6.10  	{ ")",		-1,	NULL },		// special case
    6.11  	{ "]",		-1,	NULL },		// special case
    6.12 @@ -69,7 +69,7 @@
    6.13  
    6.14  
    6.15  
    6.16 -LineParser::Operator	LineParser::m_gaUnaryOperatorTable[] =
    6.17 +const LineParser::Operator	LineParser::m_gaUnaryOperatorTable[] =
    6.18  {
    6.19  	{ "(",		-1,	NULL },		// special case
    6.20  	{ "[",		-1,	NULL },		// special case
    6.21 @@ -142,7 +142,7 @@
    6.22  		{
    6.23  			// get a number
    6.24  
    6.25 -			int hexValue;
    6.26 +			unsigned int hexValue;
    6.27  
    6.28  			istringstream str( m_line );
    6.29  			str.seekg( m_column );
    6.30 @@ -321,7 +321,7 @@
    6.31  			{
    6.32  				// If unary operator *was* found...
    6.33  
    6.34 -				Operator& thisOp = m_gaUnaryOperatorTable[ matchedToken ];
    6.35 +				const Operator& thisOp = m_gaUnaryOperatorTable[ matchedToken ];
    6.36  
    6.37  				if ( thisOp.handler != NULL )
    6.38  				{
    6.39 @@ -381,7 +381,7 @@
    6.40  
    6.41  			// we found binary operator
    6.42  
    6.43 -			Operator& thisOp = m_gaBinaryOperatorTable[ matchedToken ];
    6.44 +			const Operator& thisOp = m_gaBinaryOperatorTable[ matchedToken ];
    6.45  
    6.46  			if ( thisOp.handler != NULL )
    6.47  			{
     7.1 --- a/src/lineparser.cpp	Sun May 02 12:27:54 2010 +0100
     7.2 +++ b/src/lineparser.cpp	Sun May 02 12:29:28 2010 +0100
     7.3 @@ -291,19 +291,9 @@
     7.4  {
     7.5  	assert( i >= 0 );
     7.6  
     7.7 -	// Do special case handling for IF/ELSE/ENDIF
     7.8 -
     7.9 -	if ( m_gaTokenTable[ i ].m_handler == &LineParser::HandleIf )
    7.10 +	if ( m_gaTokenTable[ i ].m_directiveHandler )
    7.11  	{
    7.12 -		m_sourceFile->AddIfLevel( m_line, m_column );
    7.13 -	}
    7.14 -	else if ( m_gaTokenTable[ i ].m_handler == &LineParser::HandleElse )
    7.15 -	{
    7.16 -		m_sourceFile->ToggleCurrentIfCondition( m_line, m_column );
    7.17 -	}
    7.18 -	else if ( m_gaTokenTable[ i ].m_handler == &LineParser::HandleEndif )
    7.19 -	{
    7.20 -		m_sourceFile->RemoveIfLevel( m_line, m_column );
    7.21 +		( m_sourceFile->*m_gaTokenTable[ i ].m_directiveHandler )( m_line, m_column );
    7.22  	}
    7.23  
    7.24  	if ( m_sourceFile->IsIfConditionTrue() )
     8.1 --- a/src/lineparser.h	Sun May 02 12:27:54 2010 +0100
     8.2 +++ b/src/lineparser.h	Sun May 02 12:29:28 2010 +0100
     8.3 @@ -46,11 +46,13 @@
     8.4  private:
     8.5  
     8.6  	typedef void ( LineParser::*TokenHandler )();
     8.7 +	typedef void ( SourceFile::*DirectiveHandler )( std::string line, int column );
     8.8  
     8.9  	struct Token
    8.10  	{
    8.11 -		const char*		m_pName;
    8.12 -		TokenHandler	m_handler;
    8.13 +		const char*			m_pName;
    8.14 +		TokenHandler		m_handler;
    8.15 +		DirectiveHandler	m_directiveHandler;
    8.16  	};
    8.17  
    8.18  	enum ADDRESSING_MODE
    8.19 @@ -64,9 +66,11 @@
    8.20  		ABS,
    8.21  		ABSX,
    8.22  		ABSY,
    8.23 +		IND,
    8.24  		INDX,
    8.25  		INDY,
    8.26  		IND16,
    8.27 +		IND16X,
    8.28  		REL,
    8.29  
    8.30  		NUM_ADDRESSING_MODES
    8.31 @@ -76,6 +80,7 @@
    8.32  	{
    8.33  		short			m_aOpcodes[NUM_ADDRESSING_MODES];
    8.34  		const char*		m_pName;
    8.35 +		int				m_cpu;
    8.36  	};
    8.37  
    8.38  
    8.39 @@ -122,20 +127,21 @@
    8.40  	void			HandleDefineLabel();
    8.41  	void			HandleDefineComment();
    8.42  	void			HandleStatementSeparator();
    8.43 +	void			HandleDirective();
    8.44  	void			HandlePrint();
    8.45 +	void			HandleCpu();
    8.46  	void			HandleOrg();
    8.47  	void			HandleInclude();
    8.48  	void			HandleIncBin();
    8.49  	void			HandleEqub();
    8.50  	void			HandleEquw();
    8.51 +	void			HandleEqud();
    8.52  	void			HandleSave();
    8.53  	void			HandleFor();
    8.54  	void			HandleNext();
    8.55  	void			HandleOpenBrace();
    8.56  	void			HandleCloseBrace();
    8.57  	void			HandleIf();
    8.58 -	void			HandleElse();
    8.59 -	void			HandleEndif();
    8.60  	void			HandleAlign();
    8.61  	void			HandleSkip();
    8.62  	void			HandleSkipTo();
    8.63 @@ -195,10 +201,10 @@
    8.64  	std::string				m_line;
    8.65  	size_t					m_column;
    8.66  
    8.67 -	static Token			m_gaTokenTable[];
    8.68 -	static OpcodeData		m_gaOpcodeTable[];
    8.69 -	static Operator			m_gaUnaryOperatorTable[];
    8.70 -	static Operator			m_gaBinaryOperatorTable[];
    8.71 +	static const Token		m_gaTokenTable[];
    8.72 +	static const OpcodeData	m_gaOpcodeTable[];
    8.73 +	static const Operator	m_gaUnaryOperatorTable[];
    8.74 +	static const Operator	m_gaBinaryOperatorTable[];
    8.75  
    8.76  	#define MAX_VALUES		128
    8.77  	#define MAX_OPERATORS	32
     9.1 --- a/src/main.cpp	Sun May 02 12:27:54 2010 +0100
     9.2 +++ b/src/main.cpp	Sun May 02 12:29:28 2010 +0100
     9.3 @@ -39,7 +39,7 @@
     9.4  using namespace std;
     9.5  
     9.6  
     9.7 -#define VERSION "1.03"
     9.8 +#define VERSION "1.04"
     9.9  
    9.10  
    9.11  /*************************************************************************************************/
    10.1 --- a/src/objectcode.cpp	Sun May 02 12:27:54 2010 +0100
    10.2 +++ b/src/objectcode.cpp	Sun May 02 12:29:28 2010 +0100
    10.3 @@ -77,7 +77,8 @@
    10.4  */
    10.5  /*************************************************************************************************/
    10.6  ObjectCode::ObjectCode()
    10.7 -	:	m_PC( 0 )
    10.8 +	:	m_PC( 0 ),
    10.9 +	 	m_CPU( 0 )
   10.10  {
   10.11  	memset( m_aMemory, 0, sizeof m_aMemory );
   10.12  	memset( m_aFlags, 0, sizeof m_aFlags );
    11.1 --- a/src/objectcode.h	Sun May 02 12:27:54 2010 +0100
    11.2 +++ b/src/objectcode.h	Sun May 02 12:29:28 2010 +0100
    11.3 @@ -38,6 +38,9 @@
    11.4  	inline void SetPC( int i )		{ m_PC = i; }
    11.5  	inline int GetPC() const		{ return m_PC; }
    11.6  
    11.7 +	inline void SetCPU( int i )		{ m_CPU = i; }
    11.8 +	inline int GetCPU() const		{ return m_CPU; }
    11.9 +
   11.10  	inline const unsigned char* GetAddr( int i ) const { return m_aMemory + i; }
   11.11  
   11.12  	void PutByte( unsigned int byte );
   11.13 @@ -70,6 +73,7 @@
   11.14  	unsigned char				m_aMemory[ 0x10000 ];
   11.15  	unsigned char				m_aFlags[ 0x10000 ];
   11.16  	int							m_PC;
   11.17 +	int							m_CPU;
   11.18  
   11.19  	unsigned char				m_aMapChar[ 96 ];
   11.20  
    12.1 --- a/src/sourcefile.cpp	Sun May 02 12:27:54 2010 +0100
    12.2 +++ b/src/sourcefile.cpp	Sun May 02 12:29:28 2010 +0100
    12.3 @@ -387,6 +387,8 @@
    12.4  	}
    12.5  
    12.6  	m_ifStack[ m_ifStackPtr ].m_condition	= true;
    12.7 +	m_ifStack[ m_ifStackPtr ].m_passed		= false;
    12.8 +	m_ifStack[ m_ifStackPtr ].m_hadElse		= false;
    12.9  	m_ifStack[ m_ifStackPtr ].m_line		= line;
   12.10  	m_ifStack[ m_ifStackPtr ].m_column		= column;
   12.11  	m_ifStack[ m_ifStackPtr ].m_lineNumber	= m_lineNumber;
   12.12 @@ -404,23 +406,46 @@
   12.13  {
   12.14  	assert( m_ifStackPtr > 0 );
   12.15  	m_ifStack[ m_ifStackPtr - 1 ].m_condition = b;
   12.16 +	if ( b )
   12.17 +	{
   12.18 +		m_ifStack[ m_ifStackPtr - 1 ].m_passed = true;
   12.19 +	}
   12.20  }
   12.21  
   12.22  
   12.23  
   12.24  /*************************************************************************************************/
   12.25  /**
   12.26 -	SourceFile::ToggleCurrentIfCondition()
   12.27 +	SourceFile::StartElse()
   12.28  */
   12.29  /*************************************************************************************************/
   12.30 -void SourceFile::ToggleCurrentIfCondition( string line, int column )
   12.31 +void SourceFile::StartElse( string line, int column )
   12.32  {
   12.33 -	if ( m_ifStackPtr == 0 )
   12.34 +	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
   12.35  	{
   12.36  		throw AsmException_SyntaxError_ElseWithoutIf( line, column );
   12.37  	}
   12.38  
   12.39 -	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_condition;
   12.40 +	m_ifStack[ m_ifStackPtr - 1 ].m_hadElse = true;
   12.41 +
   12.42 +	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
   12.43 +}
   12.44 +
   12.45 +
   12.46 +
   12.47 +/*************************************************************************************************/
   12.48 +/**
   12.49 +	SourceFile::StartElif()
   12.50 +*/
   12.51 +/*************************************************************************************************/
   12.52 +void SourceFile::StartElif( string line, int column )
   12.53 +{
   12.54 +	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
   12.55 +	{
   12.56 +		throw AsmException_SyntaxError_ElifWithoutIf( line, column );
   12.57 +	}
   12.58 +
   12.59 +	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
   12.60  }
   12.61  
   12.62  
    13.1 --- a/src/sourcefile.h	Sun May 02 12:27:54 2010 +0100
    13.2 +++ b/src/sourcefile.h	Sun May 02 12:29:28 2010 +0100
    13.3 @@ -75,6 +75,8 @@
    13.4  	struct If
    13.5  	{
    13.6  		bool				m_condition;
    13.7 +		bool                m_hadElse;
    13.8 +		bool				m_passed;
    13.9  		std::string			m_line;
   13.10  		int					m_column;
   13.11  		int					m_lineNumber;
   13.12 @@ -105,6 +107,8 @@
   13.13  	bool					IsIfConditionTrue() const;
   13.14  	void					AddIfLevel( std::string line, int column );
   13.15  	void					SetCurrentIfCondition( bool b );
   13.16 +	void					StartElse( std::string line, int column );
   13.17 +	void					StartElif( std::string line, int column );
   13.18  	void					ToggleCurrentIfCondition( std::string line, int column );
   13.19  	void					RemoveIfLevel( std::string line, int column );
   13.20