1 //	Copyright (C) 1999-2012 Core Technologies.
2 //
3 //	This file is part of tpasm.
4 //
5 //	tpasm is free software; you can redistribute it and/or modify
6 //	it under the terms of the tpasm LICENSE AGREEMENT.
7 //
8 //	tpasm is distributed in the hope that it will be useful,
9 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //	tpasm LICENSE AGREEMENT for more details.
12 //
13 //	You should have received a copy of the tpasm LICENSE AGREEMENT
14 //	along with tpasm; see the file "LICENSE.TXT".
15 
16 // Generate code for Motorola 6805, or the newer hc08's
17 
18 #include	"include.h"
19 
20 #define	SP_PREAMBLE	0x9E	// all opcodes which reference SP require this preamble
21 
22 static SYM_TABLE
23 	*pseudoOpcodeSymbols,
24 	*opcodeSymbols6805,
25 	*opcodeSymbols68hc08;
26 
27 static PROCESSOR
28 	*currentProcessor;
29 
30 // enumerated addressing modes
31 
32 enum
33 {
34 	OT_INHERENT,			// no operands
35 	OT_IMM8,				// 8-bit immediate operand
36 	OT_IMM16,				// 16-bit immediate operand
37 	OT_DIRECT,				// one byte direct
38 	OT_EXTENDED,			// two byte absolute
39 	OT_INDEXED,				// indexed with no offset
40 	OT_OFF8_INDEXED,		// indexed with 8-bit offset
41 	OT_OFF16_INDEXED,		// indexed with 16-bit offset
42 	OT_OFF8_SP,				// stack pointer with 8-bit offset
43 	OT_OFF16_SP,			// stack pointer with 16-bit offset
44 	OT_BIT_DIRECT,			// one bit index, one byte of direct
45 	OT_IMM8_DIRECT,			// 8-bit immediate operand, one byte direct address
46 	OT_DIRECT_DIRECT,		// one byte direct address, one byte direct address
47 	OT_INDEXED_PI_DIRECT,	// indexed to direct with post-increment
48 	OT_DIRECT_INDEXED_PI,	// direct to indexed with post-increment
49 	OT_INDEXED_PI,			// indexed post-increment
50 	OT_OFF8_INDEXED_PI,		// indexed with 8 bit offset and post-increment
51 	OT_NUM					// number of addressing modes
52 };
53 
54 // masks for the various addressing modes (all opcodes which use relative offsets are
55 // handled with a separate flag that tells us to expect a relative offset as the last
56 // parameter)
57 
58 #define	M_INHERENT				(1<<OT_INHERENT)
59 #define	M_IMM8					(1<<OT_IMM8)
60 #define	M_IMM16					(1<<OT_IMM16)
61 #define	M_DIRECT				(1<<OT_DIRECT)
62 #define	M_EXTENDED				(1<<OT_EXTENDED)
63 #define	M_INDEXED				(1<<OT_INDEXED)
64 #define	M_OFF8_INDEXED			(1<<OT_OFF8_INDEXED)
65 #define	M_OFF16_INDEXED			(1<<OT_OFF16_INDEXED)
66 #define	M_OFF8_SP				(1<<OT_OFF8_SP)
67 #define	M_OFF16_SP				(1<<OT_OFF16_SP)
68 #define	M_BIT_DIRECT			(1<<OT_BIT_DIRECT)
69 #define	M_IMM8_DIRECT			(1<<OT_IMM8_DIRECT)
70 #define	M_DIRECT_DIRECT			(1<<OT_DIRECT_DIRECT)
71 #define	M_INDEXED_PI_DIRECT		(1<<OT_INDEXED_PI_DIRECT)
72 #define	M_DIRECT_INDEXED_PI		(1<<OT_DIRECT_INDEXED_PI)
73 #define	M_INDEXED_PI			(1<<OT_INDEXED_PI)
74 #define	M_OFF8_INDEXED_PI		(1<<OT_OFF8_INDEXED_PI)
75 
76 
77 // types of operands which we can discover while parsing
78 enum
79 {
80 	POT_INDEX,
81 	POT_INDEX_PI,						// index with post-increment (X+)
82 	POT_SP,
83 	POT_IMMEDIATE,
84 	POT_VALUE,
85 };
86 
87 struct OPCODE
88 {
89 	const char
90 		*name;							// opcode name
91 	bool
92 		relativeMode;					// tells if this opcode requires a relative address as its last operand (in addition to any others that may be specified)
93 	unsigned int
94 		typeMask;						// mask of bits that tells which type of operands are allowed for this opcode
95 	unsigned char
96 		baseOpcode[OT_NUM];				// list of opcode values -- one for each possible operand type
97 };
98 
99 struct OPERAND
100 {
101 	unsigned int
102 		type;			// type of operand located
103 	int
104 		value;			// first immediate value, or non immediate value
105 	bool
106 		unresolved;		// if value was an expression, this tells if it was unresolved
107 };
108 
109 
110 static PSEUDO_OPCODE
111 	pseudoOpcodes[]=
112 	{
113 		{"db",		HandleDB},
114 		{"dc.b",	HandleDB},
115 		{"dw",		HandleBEDW},		// words are big endian
116 		{"dc.w",	HandleBEDW},
117 		{"ds",		HandleDS},
118 		{"ds.b",	HandleDS},
119 		{"ds.w",	HandleDSW},
120 		{"incbin",	HandleIncbin},
121 	};
122 
123 // These macros are used to make the opcode table creation simpler and less error prone
124 // Entries which are passed as whitespace are not encoded into typeMask
125 // Entries which are non-whitespace have a bit set in typeMask
126 
127 #define	OP_FLAG(a,mask) ((sizeof(#a)>1)?mask:0)
128 #define	OP_VAL(a) (a+0)
129 
130 // This macro creates the typeFlags and baseOpcode list. For each non-white entry in the baseOpcode
131 // list, a bit is set in typeFlags.
132 #define OP_ENTRY(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) OP_FLAG(a,M_INHERENT)|OP_FLAG(b,M_IMM8)|OP_FLAG(c,M_IMM16)|OP_FLAG(d,M_DIRECT)|OP_FLAG(e,M_EXTENDED)|OP_FLAG(f,M_INDEXED)|OP_FLAG(g,M_OFF8_INDEXED)|OP_FLAG(h,M_OFF16_INDEXED)|OP_FLAG(i,M_OFF8_SP)|OP_FLAG(j,M_OFF16_SP)|OP_FLAG(k,M_BIT_DIRECT)|OP_FLAG(l,M_IMM8_DIRECT)|OP_FLAG(m,M_DIRECT_DIRECT)|OP_FLAG(n,M_INDEXED_PI_DIRECT)|OP_FLAG(o,M_DIRECT_INDEXED_PI)|OP_FLAG(p,M_INDEXED_PI)|OP_FLAG(q,M_OFF8_INDEXED_PI),{OP_VAL(a),OP_VAL(b),OP_VAL(c),OP_VAL(d),OP_VAL(e),OP_VAL(f),OP_VAL(g),OP_VAL(h),OP_VAL(i),OP_VAL(j),OP_VAL(k),OP_VAL(l),OP_VAL(m),OP_VAL(n),OP_VAL(o),OP_VAL(p),OP_VAL(q)}
133 
134 static OPCODE
135 	Opcodes6805[]=
136 	{
137 //								   inh  im8  im16 dir  ext  hx   8hx  16hx 8sp  16sp bd   im8d dd   hx+d dhx+ hx+  8hx+
138 		{"adc",		false,OP_ENTRY(   0,0xA9,   0,0xB9,0xC9,0xF9,0xE9,0xD9,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
139 		{"add",		false,OP_ENTRY(   0,0xAB,   0,0xBB,0xCB,0xFB,0xEB,0xDB,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
140 		{"and",		false,OP_ENTRY(   0,0xA4,   0,0xB4,0xC4,0xF4,0xE4,0xD4,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
141 		{"asl",		false,OP_ENTRY(   0,   0,   0,0x38,   0,0x78,0x68,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
142 		{"asla",	false,OP_ENTRY(0x48,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
143 		{"aslx",	false,OP_ENTRY(0x58,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
144 		{"asr",		false,OP_ENTRY(   0,   0,   0,0x37,   0,0x77,0x67,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
145 		{"asra",	false,OP_ENTRY(0x47,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
146 		{"asrx",	false,OP_ENTRY(0x57,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
147 		{"bcc",		true ,OP_ENTRY(0x24,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
148 		{"bclr",	false,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x11,   0,   0,   0,   0,   0,   0)},
149 		{"bclr0",	false,OP_ENTRY(   0,   0,   0,0x11,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
150 		{"bclr1",	false,OP_ENTRY(   0,   0,   0,0x13,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
151 		{"bclr2",	false,OP_ENTRY(   0,   0,   0,0x15,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
152 		{"bclr3",	false,OP_ENTRY(   0,   0,   0,0x17,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
153 		{"bclr4",	false,OP_ENTRY(   0,   0,   0,0x19,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
154 		{"bclr5",	false,OP_ENTRY(   0,   0,   0,0x1B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
155 		{"bclr6",	false,OP_ENTRY(   0,   0,   0,0x1D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
156 		{"bclr7",	false,OP_ENTRY(   0,   0,   0,0x1F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
157 		{"bcs",		true ,OP_ENTRY(0x25,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
158 		{"beq",		true ,OP_ENTRY(0x27,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
159 		{"bhcc",	true ,OP_ENTRY(0x28,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
160 		{"bhcs",	true ,OP_ENTRY(0x29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
161 		{"bhi",		true ,OP_ENTRY(0x22,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
162 		{"bhs",		true ,OP_ENTRY(0x24,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
163 		{"bih",		true ,OP_ENTRY(0x2F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
164 		{"bil",		true ,OP_ENTRY(0x2E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
165 		{"bit",		false,OP_ENTRY(   0,0xA5,   0,0xB5,0xC5,0xF5,0xE5,0xD5,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
166 		{"blo",		true ,OP_ENTRY(0x25,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
167 		{"bls",		true ,OP_ENTRY(0x23,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
168 		{"bmc",		true ,OP_ENTRY(0x2C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
169 		{"bmi",		true ,OP_ENTRY(0x2B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
170 		{"bms",		true ,OP_ENTRY(0x2D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
171 		{"bne",		true ,OP_ENTRY(0x26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
172 		{"bpl",		true ,OP_ENTRY(0x2A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
173 		{"bra",		true ,OP_ENTRY(0x20,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
174 		{"brclr",	true ,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x01,   0,   0,   0,   0,   0,   0)},
175 		{"brclr0",	true ,OP_ENTRY(   0,   0,   0,0x01,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
176 		{"brclr1",	true ,OP_ENTRY(   0,   0,   0,0x03,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
177 		{"brclr2",	true ,OP_ENTRY(   0,   0,   0,0x05,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
178 		{"brclr3",	true ,OP_ENTRY(   0,   0,   0,0x07,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
179 		{"brclr4",	true ,OP_ENTRY(   0,   0,   0,0x09,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
180 		{"brclr5",	true ,OP_ENTRY(   0,   0,   0,0x0B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
181 		{"brclr6",	true ,OP_ENTRY(   0,   0,   0,0x0D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
182 		{"brclr7",	true ,OP_ENTRY(   0,   0,   0,0x0F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
183 		{"brn",		true ,OP_ENTRY(0x21,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
184 		{"brset",	true ,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x00,   0,   0,   0,   0,   0,   0)},
185 		{"brset0",	true ,OP_ENTRY(   0,   0,   0,0x00,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
186 		{"brset1",	true ,OP_ENTRY(   0,   0,   0,0x02,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
187 		{"brset2",	true ,OP_ENTRY(   0,   0,   0,0x04,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
188 		{"brset3",	true ,OP_ENTRY(   0,   0,   0,0x06,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
189 		{"brset4",	true ,OP_ENTRY(   0,   0,   0,0x08,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
190 		{"brset5",	true ,OP_ENTRY(   0,   0,   0,0x0A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
191 		{"brset6",	true ,OP_ENTRY(   0,   0,   0,0x0C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
192 		{"brset7",	true ,OP_ENTRY(   0,   0,   0,0x0E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
193 		{"bset",	false,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x10,   0,   0,   0,   0,   0,   0)},
194 		{"bset0",	false,OP_ENTRY(   0,   0,   0,0x10,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
195 		{"bset1",	false,OP_ENTRY(   0,   0,   0,0x12,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
196 		{"bset2",	false,OP_ENTRY(   0,   0,   0,0x14,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
197 		{"bset3",	false,OP_ENTRY(   0,   0,   0,0x16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
198 		{"bset4",	false,OP_ENTRY(   0,   0,   0,0x18,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
199 		{"bset5",	false,OP_ENTRY(   0,   0,   0,0x1A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
200 		{"bset6",	false,OP_ENTRY(   0,   0,   0,0x1C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
201 		{"bset7",	false,OP_ENTRY(   0,   0,   0,0x1E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
202 		{"bsr",		true ,OP_ENTRY(0xAD,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
203 		{"clc",		false,OP_ENTRY(0x98,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
204 		{"cli",		false,OP_ENTRY(0x9A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
205 		{"clr",		false,OP_ENTRY(   0,   0,   0,0x3F,   0,0x7F,0x6F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
206 		{"clra",	false,OP_ENTRY(0x4F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
207 		{"clrx",	false,OP_ENTRY(0x5F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
208 		{"cmp",		false,OP_ENTRY(   0,0xA1,   0,0xB1,0xC1,0xF1,0xE1,0xD1,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
209 		{"com",		false,OP_ENTRY(   0,   0,   0,0x33,   0,0x73,0x63,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
210 		{"coma",	false,OP_ENTRY(0x43,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
211 		{"comx",	false,OP_ENTRY(0x53,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
212 		{"cpx",		false,OP_ENTRY(   0,0xA3,   0,0xB3,0xC3,0xF3,0xE3,0xD3,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
213 		{"dec",		false,OP_ENTRY(   0,   0,   0,0x3A,   0,0x7A,0x6A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
214 		{"deca",	false,OP_ENTRY(0x4A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
215 		{"decx",	false,OP_ENTRY(0x5A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
216 		{"dex",		false,OP_ENTRY(0x5A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
217 		{"eor",		false,OP_ENTRY(   0,0xA8,   0,0xB8,0xC8,0xF8,0xE8,0xD8,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
218 		{"inc",		false,OP_ENTRY(   0,   0,   0,0x3C,   0,0x7C,0x6C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
219 		{"inca",	false,OP_ENTRY(0x4C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
220 		{"incx",	false,OP_ENTRY(0x5C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
221 		{"inx",		false,OP_ENTRY(0x5C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
222 		{"jmp",		false,OP_ENTRY(   0,   0,   0,0xBC,0xCC,0xFC,0xEC,0xDC,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
223 		{"jsr",		false,OP_ENTRY(   0,   0,   0,0xBD,0xCD,0xFD,0xED,0xDD,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
224 		{"lda",		false,OP_ENTRY(   0,0xA6,   0,0xB6,0xC6,0xF6,0xE6,0xD6,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
225 		{"ldx",		false,OP_ENTRY(   0,0xAE,   0,0xBE,0xCE,0xFE,0xEE,0xDE,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
226 		{"lsl",		false,OP_ENTRY(   0,   0,   0,0x38,   0,0x78,0x68,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
227 		{"lsla",	false,OP_ENTRY(0x48,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
228 		{"lslx",	false,OP_ENTRY(0x58,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
229 		{"lsr",		false,OP_ENTRY(   0,   0,   0,0x34,   0,0x74,0x64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
230 		{"lsra",	false,OP_ENTRY(0x44,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
231 		{"lsrx",	false,OP_ENTRY(0x54,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
232 		{"mul",		false,OP_ENTRY(0x42,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
233 		{"neg",		false,OP_ENTRY(   0,   0,   0,0x30,   0,0x70,0x60,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
234 		{"nega",	false,OP_ENTRY(0x40,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
235 		{"negx",	false,OP_ENTRY(0x50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
236 		{"nop",		false,OP_ENTRY(0x9D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
237 		{"ora",		false,OP_ENTRY(   0,0xAA,   0,0xBA,0xCA,0xFA,0xEA,0xDA,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
238 		{"rol",		false,OP_ENTRY(   0,   0,   0,0x39,   0,0x79,0x69,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
239 		{"rola",	false,OP_ENTRY(0x49,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
240 		{"rolx",	false,OP_ENTRY(0x59,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
241 		{"ror",		false,OP_ENTRY(   0,   0,   0,0x36,   0,0x76,0x66,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
242 		{"rora",	false,OP_ENTRY(0x46,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
243 		{"rorx",	false,OP_ENTRY(0x56,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
244 		{"rsp",		false,OP_ENTRY(0x9C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
245 		{"rti",		false,OP_ENTRY(0x80,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
246 		{"rts",		false,OP_ENTRY(0x81,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
247 		{"sbc",		false,OP_ENTRY(   0,0xA2,   0,0xB2,0xC2,0xF2,0xE2,0xD2,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
248 		{"sec",		false,OP_ENTRY(0x99,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
249 		{"sei",		false,OP_ENTRY(0x9B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
250 		{"sta",		false,OP_ENTRY(   0,   0,   0,0xB7,0xC7,0xF7,0xE7,0xD7,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
251 		{"stop",	false,OP_ENTRY(0x8E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
252 		{"stx",		false,OP_ENTRY(   0,   0,   0,0xBF,0xCF,0xFF,0xEF,0xDF,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
253 		{"sub",		false,OP_ENTRY(   0,0xA0,   0,0xB0,0xC0,0xF0,0xE0,0xD0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
254 		{"swi",		false,OP_ENTRY(0x83,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
255 		{"tax",		false,OP_ENTRY(0x97,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
256 		{"tst",		false,OP_ENTRY(   0,   0,   0,0x3D,   0,0x7D,0x6D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
257 		{"tsta",	false,OP_ENTRY(0x4D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
258 		{"tstx",	false,OP_ENTRY(0x5D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
259 		{"txa",		false,OP_ENTRY(0x9F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
260 		{"wait",	false,OP_ENTRY(0x8F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
261 	};
262 
263 static OPCODE
264 	Opcodes68hc08[]=
265 	{
266 //								   inh  im8  im16 dir  ext  hx   8hx  16hx 8sp  16sp bd   im8d dd   hx+d dhx+ hx+  8hx+
267 		{"adc",		false,OP_ENTRY(   0,0xA9,   0,0xB9,0xC9,0xF9,0xE9,0xD9,0xE9,0xD9,   0,   0,   0,   0,   0,   0,   0)},
268 		{"add",		false,OP_ENTRY(   0,0xAB,   0,0xBB,0xCB,0xFB,0xEB,0xDB,0xEB,0xDB,   0,   0,   0,   0,   0,   0,   0)},
269 		{"ais",		false,OP_ENTRY(   0,0xA7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
270 		{"aix",		false,OP_ENTRY(   0,0xAF,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
271 		{"and",		false,OP_ENTRY(   0,0xA4,   0,0xB4,0xC4,0xF4,0xE4,0xD4,0xE4,0xD4,   0,   0,   0,   0,   0,   0,   0)},
272 		{"asl",		false,OP_ENTRY(   0,   0,   0,0x38,   0,0x78,0x68,   0,0x68,   0,   0,   0,   0,   0,   0,   0,   0)},
273 		{"asla",	false,OP_ENTRY(0x48,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
274 		{"aslx",	false,OP_ENTRY(0x58,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
275 		{"asr",		false,OP_ENTRY(   0,   0,   0,0x37,   0,0x77,0x67,   0,0x67,   0,   0,   0,   0,   0,   0,   0,   0)},
276 		{"asra",	false,OP_ENTRY(0x47,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
277 		{"asrx",	false,OP_ENTRY(0x57,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
278 		{"bcc",		true ,OP_ENTRY(0x24,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
279 		{"bclr",	false,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x11,   0,   0,   0,   0,   0,   0)},
280 		{"bclr0",	false,OP_ENTRY(   0,   0,   0,0x11,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
281 		{"bclr1",	false,OP_ENTRY(   0,   0,   0,0x13,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
282 		{"bclr2",	false,OP_ENTRY(   0,   0,   0,0x15,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
283 		{"bclr3",	false,OP_ENTRY(   0,   0,   0,0x17,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
284 		{"bclr4",	false,OP_ENTRY(   0,   0,   0,0x19,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
285 		{"bclr5",	false,OP_ENTRY(   0,   0,   0,0x1B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
286 		{"bclr6",	false,OP_ENTRY(   0,   0,   0,0x1D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
287 		{"bclr7",	false,OP_ENTRY(   0,   0,   0,0x1F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
288 		{"bcs",		true ,OP_ENTRY(0x25,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
289 		{"beq",		true ,OP_ENTRY(0x27,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
290 		{"bge",		true ,OP_ENTRY(0x90,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
291 		{"bgt",		true ,OP_ENTRY(0x92,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
292 		{"bhcc",	true ,OP_ENTRY(0x28,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
293 		{"bhcs",	true ,OP_ENTRY(0x29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
294 		{"bhi",		true ,OP_ENTRY(0x22,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
295 		{"bhs",		true ,OP_ENTRY(0x24,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
296 		{"bih",		true ,OP_ENTRY(0x2F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
297 		{"bil",		true ,OP_ENTRY(0x2E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
298 		{"bit",		false,OP_ENTRY(   0,0xA5,   0,0xB5,0xC5,0xF5,0xE5,0xD5,0xE5,0xD5,   0,   0,   0,   0,   0,   0,   0)},
299 		{"ble",		true ,OP_ENTRY(0x93,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
300 		{"blo",		true ,OP_ENTRY(0x25,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
301 		{"bls",		true ,OP_ENTRY(0x23,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
302 		{"blt",		true ,OP_ENTRY(0x91,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
303 		{"bmc",		true ,OP_ENTRY(0x2C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
304 		{"bmi",		true ,OP_ENTRY(0x2B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
305 		{"bms",		true ,OP_ENTRY(0x2D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
306 		{"bne",		true ,OP_ENTRY(0x26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
307 		{"bpl",		true ,OP_ENTRY(0x2A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
308 		{"bra",		true ,OP_ENTRY(0x20,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
309 		{"brclr",	true ,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x01,   0,   0,   0,   0,   0,   0)},
310 		{"brclr0",	true ,OP_ENTRY(   0,   0,   0,0x01,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
311 		{"brclr1",	true ,OP_ENTRY(   0,   0,   0,0x03,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
312 		{"brclr2",	true ,OP_ENTRY(   0,   0,   0,0x05,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
313 		{"brclr3",	true ,OP_ENTRY(   0,   0,   0,0x07,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
314 		{"brclr4",	true ,OP_ENTRY(   0,   0,   0,0x09,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
315 		{"brclr5",	true ,OP_ENTRY(   0,   0,   0,0x0B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
316 		{"brclr6",	true ,OP_ENTRY(   0,   0,   0,0x0D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
317 		{"brclr7",	true ,OP_ENTRY(   0,   0,   0,0x0F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
318 		{"brn",		true ,OP_ENTRY(0x21,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
319 		{"brset",	true ,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x00,   0,   0,   0,   0,   0,   0)},
320 		{"brset0",	true ,OP_ENTRY(   0,   0,   0,0x00,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
321 		{"brset1",	true ,OP_ENTRY(   0,   0,   0,0x02,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
322 		{"brset2",	true ,OP_ENTRY(   0,   0,   0,0x04,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
323 		{"brset3",	true ,OP_ENTRY(   0,   0,   0,0x06,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
324 		{"brset4",	true ,OP_ENTRY(   0,   0,   0,0x08,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
325 		{"brset5",	true ,OP_ENTRY(   0,   0,   0,0x0A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
326 		{"brset6",	true ,OP_ENTRY(   0,   0,   0,0x0C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
327 		{"brset7",	true ,OP_ENTRY(   0,   0,   0,0x0E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
328 		{"bset",	false,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x10,   0,   0,   0,   0,   0,   0)},
329 		{"bset0",	false,OP_ENTRY(   0,   0,   0,0x10,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
330 		{"bset1",	false,OP_ENTRY(   0,   0,   0,0x12,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
331 		{"bset2",	false,OP_ENTRY(   0,   0,   0,0x14,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
332 		{"bset3",	false,OP_ENTRY(   0,   0,   0,0x16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
333 		{"bset4",	false,OP_ENTRY(   0,   0,   0,0x18,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
334 		{"bset5",	false,OP_ENTRY(   0,   0,   0,0x1A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
335 		{"bset6",	false,OP_ENTRY(   0,   0,   0,0x1C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
336 		{"bset7",	false,OP_ENTRY(   0,   0,   0,0x1E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
337 		{"bsr",		true ,OP_ENTRY(0xAD,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
338 		{"cbeq",	true ,OP_ENTRY(   0,   0,   0,0x31,   0,   0,   0,   0,0x61,   0,   0,   0,   0,   0,   0,0x71,0x61)},
339 		{"cbeqa",	true ,OP_ENTRY(   0,0x41,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
340 		{"cbeqx",	true ,OP_ENTRY(   0,0x51,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
341 		{"clc",		false,OP_ENTRY(0x98,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
342 		{"cli",		false,OP_ENTRY(0x9A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
343 		{"clr",		false,OP_ENTRY(   0,   0,   0,0x3F,   0,0x7F,0x6F,   0,0x6F,   0,   0,   0,   0,   0,   0,   0,   0)},
344 		{"clra",	false,OP_ENTRY(0x4F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
345 		{"clrx",	false,OP_ENTRY(0x5F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
346 		{"clrh",	false,OP_ENTRY(0x8C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
347 		{"cmp",		false,OP_ENTRY(   0,0xA1,   0,0xB1,0xC1,0xF1,0xE1,0xD1,0xE1,0xD1,   0,   0,   0,   0,   0,   0,   0)},
348 		{"com",		false,OP_ENTRY(   0,   0,   0,0x33,   0,0x73,0x63,   0,0x63,   0,   0,   0,   0,   0,   0,   0,   0)},
349 		{"coma",	false,OP_ENTRY(0x43,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
350 		{"comx",	false,OP_ENTRY(0x53,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
351 		{"cphx",	false,OP_ENTRY(   0,   0,0x65,0x75,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
352 		{"cpx",		false,OP_ENTRY(   0,0xA3,   0,0xB3,0xC3,0xF3,0xE3,0xD3,0xE3,0xD3,   0,   0,   0,   0,   0,   0,   0)},
353 		{"daa",		false,OP_ENTRY(0x72,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
354 		{"dbnz",	true ,OP_ENTRY(   0,   0,   0,0x3B,   0,0x7B,0x6B,   0,0x6B,   0,   0,   0,   0,   0,   0,   0,   0)},
355 		{"dbnza",	true ,OP_ENTRY(0x4B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
356 		{"dbnzx",	true ,OP_ENTRY(0x5B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
357 		{"dec",		false,OP_ENTRY(   0,   0,   0,0x3A,   0,0x7A,0x6A,   0,0x6A,   0,   0,   0,   0,   0,   0,   0,   0)},
358 		{"deca",	false,OP_ENTRY(0x4A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
359 		{"decx",	false,OP_ENTRY(0x5A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
360 		{"dex",		false,OP_ENTRY(0x5A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
361 		{"div",		false,OP_ENTRY(0x52,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
362 		{"eor",		false,OP_ENTRY(   0,0xA8,   0,0xB8,0xC8,0xF8,0xE8,0xD8,0xE8,0xD8,   0,   0,   0,   0,   0,   0,   0)},
363 		{"inc",		false,OP_ENTRY(   0,   0,   0,0x3C,   0,0x7C,0x6C,   0,0x6C,   0,   0,   0,   0,   0,   0,   0,   0)},
364 		{"inca",	false,OP_ENTRY(0x4C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
365 		{"incx",	false,OP_ENTRY(0x5C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
366 		{"inx",		false,OP_ENTRY(0x5C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
367 		{"jmp",		false,OP_ENTRY(   0,   0,   0,0xBC,0xCC,0xFC,0xEC,0xDC,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
368 		{"jsr",		false,OP_ENTRY(   0,   0,   0,0xBD,0xCD,0xFD,0xED,0xDD,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
369 		{"lda",		false,OP_ENTRY(   0,0xA6,   0,0xB6,0xC6,0xF6,0xE6,0xD6,0xE6,0xD6,   0,   0,   0,   0,   0,   0,   0)},
370 		{"ldhx",	false,OP_ENTRY(   0,   0,0x45,0x55,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
371 		{"ldx",		false,OP_ENTRY(   0,0xAE,   0,0xBE,0xCE,0xFE,0xEE,0xDE,0xEE,0xDE,   0,   0,   0,   0,   0,   0,   0)},
372 		{"lsl",		false,OP_ENTRY(   0,   0,   0,0x38,   0,0x78,0x68,   0,0x68,   0,   0,   0,   0,   0,   0,   0,   0)},
373 		{"lsla",	false,OP_ENTRY(0x48,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
374 		{"lslx",	false,OP_ENTRY(0x58,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
375 		{"lsr",		false,OP_ENTRY(   0,   0,   0,0x34,   0,0x74,0x64,   0,0x64,   0,   0,   0,   0,   0,   0,   0,   0)},
376 		{"lsra",	false,OP_ENTRY(0x44,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
377 		{"lsrx",	false,OP_ENTRY(0x54,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
378 		{"mov",		false,OP_ENTRY(   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0x6E,0x4E,0x7E,0x5E,   0,   0)},
379 		{"mul",		false,OP_ENTRY(0x42,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
380 		{"neg",		false,OP_ENTRY(   0,   0,   0,0x30,   0,0x70,0x60,   0,0x60,   0,   0,   0,   0,   0,   0,   0,   0)},
381 		{"nega",	false,OP_ENTRY(0x40,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
382 		{"negx",	false,OP_ENTRY(0x50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
383 		{"nop",		false,OP_ENTRY(0x9D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
384 		{"nsa",		false,OP_ENTRY(0x62,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
385 		{"ora",		false,OP_ENTRY(   0,0xAA,   0,0xBA,0xCA,0xFA,0xEA,0xDA,0xEA,0xDA,   0,   0,   0,   0,   0,   0,   0)},
386 		{"psha",	false,OP_ENTRY(0x87,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
387 		{"pshh",	false,OP_ENTRY(0x8B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
388 		{"pshx",	false,OP_ENTRY(0x89,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
389 		{"pula",	false,OP_ENTRY(0x86,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
390 		{"pulh",	false,OP_ENTRY(0x8A,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
391 		{"pulx",	false,OP_ENTRY(0x88,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
392 		{"rol",		false,OP_ENTRY(   0,   0,   0,0x39,   0,0x79,0x69,   0,0x69,   0,   0,   0,   0,   0,   0,   0,   0)},
393 		{"rola",	false,OP_ENTRY(0x49,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
394 		{"rolx",	false,OP_ENTRY(0x59,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
395 		{"ror",		false,OP_ENTRY(   0,   0,   0,0x36,   0,0x76,0x66,   0,0x66,   0,   0,   0,   0,   0,   0,   0,   0)},
396 		{"rora",	false,OP_ENTRY(0x46,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
397 		{"rorx",	false,OP_ENTRY(0x56,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
398 		{"rsp",		false,OP_ENTRY(0x9C,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
399 		{"rti",		false,OP_ENTRY(0x80,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
400 		{"rts",		false,OP_ENTRY(0x81,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
401 		{"sbc",		false,OP_ENTRY(   0,0xA2,   0,0xB2,0xC2,0xF2,0xE2,0xD2,0xE2,0xD2,   0,   0,   0,   0,   0,   0,   0)},
402 		{"sec",		false,OP_ENTRY(0x99,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
403 		{"sei",		false,OP_ENTRY(0x9B,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
404 		{"sta",		false,OP_ENTRY(   0,   0,   0,0xB7,0xC7,0xF7,0xE7,0xD7,0xE7,0xD7,   0,   0,   0,   0,   0,   0,   0)},
405 		{"sthx",	false,OP_ENTRY(   0,   0,   0,0x35,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
406 		{"stop",	false,OP_ENTRY(0x8E,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
407 		{"stx",		false,OP_ENTRY(   0,   0,   0,0xBF,0xCF,0xFF,0xEF,0xDF,0xEF,0xDF,   0,   0,   0,   0,   0,   0,   0)},
408 		{"sub",		false,OP_ENTRY(   0,0xA0,   0,0xB0,0xC0,0xF0,0xE0,0xD0,0xE0,0xD0,   0,   0,   0,   0,   0,   0,   0)},
409 		{"swi",		false,OP_ENTRY(0x83,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
410 		{"tap",		false,OP_ENTRY(0x84,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
411 		{"tax",		false,OP_ENTRY(0x97,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
412 		{"tpa",		false,OP_ENTRY(0x85,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
413 		{"tst",		false,OP_ENTRY(   0,   0,   0,0x3D,   0,0x7D,0x6D,   0,0x6D,   0,   0,   0,   0,   0,   0,   0,   0)},
414 		{"tsta",	false,OP_ENTRY(0x4D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
415 		{"tstx",	false,OP_ENTRY(0x5D,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
416 		{"tsx",		false,OP_ENTRY(0x95,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
417 		{"txa",		false,OP_ENTRY(0x9F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
418 		{"txs",		false,OP_ENTRY(0x94,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
419 		{"wait",	false,OP_ENTRY(0x8F,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0)},
420 	};
421 
ParseImmediatePreamble(const char * line,unsigned int * lineIndex)422 static bool ParseImmediatePreamble(const char *line,unsigned int *lineIndex)
423 // Expect a pound sign, step over one if found
424 {
425 	if(line[*lineIndex]=='#')			// does this look like a '#'?
426 	{
427 		(*lineIndex)++;						// step over it
428 		return(true);
429 	}
430 	return(false);
431 }
432 
ParseIndex(const char * line,unsigned int * lineIndex)433 static bool ParseIndex(const char *line,unsigned int *lineIndex)
434 // see if next thing on the line is the index register
435 // return true if so, false otherwise
436 {
437 	if(line[*lineIndex]=='X'||line[*lineIndex]=='x')
438 	{
439 		if(!IsLabelChar(line[(*lineIndex)+1]))
440 		{
441 			(*lineIndex)++;						// step over the register
442 			return(true);
443 		}
444 	}
445 	return(false);
446 }
447 
ParseSp(const char * line,unsigned int * lineIndex)448 static bool ParseSp(const char *line,unsigned int *lineIndex)
449 // see if next thing on the line is the stack register
450 // return true if so, false otherwise
451 {
452 	if(line[*lineIndex]=='S'||line[*lineIndex]=='s')
453 	{
454 		if(line[(*lineIndex)+1]=='P'||line[(*lineIndex)+1]=='p')
455 		{
456 			if(!IsLabelChar(line[(*lineIndex)+2]))
457 			{
458 				(*lineIndex)+=2;				// step over the register
459 				return(true);
460 			}
461 		}
462 	}
463 	return(false);
464 }
465 
ParseOperand(const char * line,unsigned int * lineIndex,OPERAND * operand)466 static bool ParseOperand(const char *line,unsigned int *lineIndex,OPERAND *operand)
467 // Try to parse an operand and determine its type
468 // return true if the parsing succeeds
469 {
470 	if(ParseImmediatePreamble(line,lineIndex))		// an immediate operand?
471 	{
472 		if(ParseExpression(line,lineIndex,&operand->value,&operand->unresolved))
473 		{
474 			operand->type=POT_IMMEDIATE;
475 			return(true);
476 		}
477 	}
478 	else if(ParseIndex(line,lineIndex))
479 	{
480 		if(line[*lineIndex]=='+')	// post increment being specified?
481 		{
482 			(*lineIndex)++;
483 			operand->type=POT_INDEX_PI;
484 		}
485 		else
486 		{
487 			operand->type=POT_INDEX;
488 		}
489 		return(true);
490 	}
491 	else if(ParseSp(line,lineIndex))
492 	{
493 		operand->type=POT_SP;
494 		return(true);
495 	}
496 	else if(ParseExpression(line,lineIndex,&operand->value,&operand->unresolved))
497 	{
498 		operand->type=POT_VALUE;
499 		return(true);
500 	}
501 	return(false);
502 }
503 
GenerateImmediate8(int value,bool unresolved,LISTING_RECORD * listingRecord)504 static bool GenerateImmediate8(int value,bool unresolved,LISTING_RECORD *listingRecord)
505 // Generate an 8 bit immediate on the output byte stream
506 // if there is a hard failure, return false
507 {
508 	CheckByteRange(value,true,true);
509 	return(GenerateByte(value,listingRecord));
510 }
511 
GenerateImmediate16(int value,bool unresolved,LISTING_RECORD * listingRecord)512 static bool GenerateImmediate16(int value,bool unresolved,LISTING_RECORD *listingRecord)
513 // Generate a 16 bit immediate on the output byte stream
514 // if there is a hard failure, return false
515 {
516 	CheckWordRange(value,true,true);
517 	if(GenerateByte(value>>8,listingRecord))
518 	{
519 		return(GenerateByte(value&0xFF,listingRecord));
520 	}
521 	return(false);
522 }
523 
GenerateDirectAddress(int value,bool unresolved,LISTING_RECORD * listingRecord)524 static bool GenerateDirectAddress(int value,bool unresolved,LISTING_RECORD *listingRecord)
525 // Generate a direct address on the output byte stream
526 // if there is a hard failure, return false
527 {
528 	CheckUnsignedByteRange(value,true,true);
529 	return(GenerateByte(value,listingRecord));
530 }
531 
GenerateExtendedAddress(int value,bool unresolved,LISTING_RECORD * listingRecord)532 static bool GenerateExtendedAddress(int value,bool unresolved,LISTING_RECORD *listingRecord)
533 // Generate an extended address on the output byte stream
534 // if there is a hard failure, return false
535 {
536 	CheckUnsignedWordRange(value,true,true);
537 	if(GenerateByte(value>>8,listingRecord))
538 	{
539 		return(GenerateByte(value&0xFF,listingRecord));
540 	}
541 	return(false);
542 }
543 
GenerateRelativeOffset(int value,bool unresolved,LISTING_RECORD * listingRecord)544 static bool GenerateRelativeOffset(int value,bool unresolved,LISTING_RECORD *listingRecord)
545 // Generate an relative offset on the output byte stream
546 // if there is a hard failure, return false
547 {
548 	unsigned int
549 		offset;
550 
551 	offset=0;
552 	if(!unresolved&&currentSegment)
553 	{
554 		offset=value-(currentSegment->currentPC+currentSegment->codeGenOffset)-1;
555 		Check8RelativeRange(offset,true,true);
556 	}
557 	return(GenerateByte(offset,listingRecord));
558 }
559 
GenerateOffset8(int value,bool unresolved,LISTING_RECORD * listingRecord)560 static bool GenerateOffset8(int value,bool unresolved,LISTING_RECORD *listingRecord)
561 // Generate a 8-bit offset on the output byte stream
562 // if there is a hard failure, return false
563 {
564 	CheckUnsignedByteRange(value,true,true);
565 	return(GenerateByte(value,listingRecord));
566 }
567 
GenerateOffset16(int value,bool unresolved,LISTING_RECORD * listingRecord)568 static bool GenerateOffset16(int value,bool unresolved,LISTING_RECORD *listingRecord)
569 // Generate a 16-bit offset on the output byte stream
570 // if there is a hard failure, return false
571 {
572 	CheckWordRange(value,true,true);		// can be signed too, since address space is 16 bits
573 	if(GenerateByte(value>>8,listingRecord))
574 	{
575 		return(GenerateByte(value&0xFF,listingRecord));
576 	}
577 	return(false);
578 }
579 
580 // ----------------------------------------------------------------------------------------
581 
HandleInherent(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)582 static bool HandleInherent(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
583 // Handle an inherent opcode. Return false on hard error
584 {
585 	bool
586 		fail;
587 
588 	fail=!GenerateByte(opcode->baseOpcode[OT_INHERENT],listingRecord);
589 	if(!fail&&opcode->relativeMode)
590 	{
591 		fail=!GenerateRelativeOffset(operands[0].value,operands[0].unresolved,listingRecord);
592 	}
593 	return(!fail);
594 }
595 
HandleIndexed(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)596 static bool HandleIndexed(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
597 // Handle X. Return false on hard error
598 {
599 	bool
600 		fail;
601 
602 	fail=!GenerateByte(opcode->baseOpcode[OT_INDEXED],listingRecord);
603 	if(!fail&&opcode->relativeMode)
604 	{
605 		fail=!GenerateRelativeOffset(operands[1].value,operands[1].unresolved,listingRecord);
606 	}
607 	return(!fail);
608 }
609 
HandleIndexedPi(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)610 static bool HandleIndexedPi(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
611 // Handle X+. Return false on hard error
612 {
613 	bool
614 		fail;
615 
616 	fail=!GenerateByte(opcode->baseOpcode[OT_INDEXED_PI],listingRecord);
617 	if(!fail&&opcode->relativeMode)
618 	{
619 		fail=!GenerateRelativeOffset(operands[1].value,operands[1].unresolved,listingRecord);
620 	}
621 	return(!fail);
622 }
623 
HandleImmediate(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)624 static bool HandleImmediate(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
625 // Handle immediate (8 or 16 bit) values. Return false on hard error
626 {
627 	bool
628 		fail;
629 
630 	fail=false;
631 	if(opcode->typeMask&M_IMM8)
632 	{
633 		if(GenerateByte(opcode->baseOpcode[OT_IMM8],listingRecord))
634 		{
635 			fail=!GenerateImmediate8(operands[0].value,operands[0].unresolved,listingRecord);
636 		}
637 		else
638 		{
639 			fail=true;
640 		}
641 	}
642 	else	// must be 16 or we would not be here
643 	{
644 		if(GenerateByte(opcode->baseOpcode[OT_IMM16],listingRecord))
645 		{
646 			fail=!GenerateImmediate16(operands[0].value,operands[0].unresolved,listingRecord);
647 		}
648 		else
649 		{
650 			fail=true;
651 		}
652 	}
653 	if(!fail&&opcode->relativeMode)
654 	{
655 		fail=!GenerateRelativeOffset(operands[1].value,operands[1].unresolved,listingRecord);
656 	}
657 	return(!fail);
658 }
659 
HandleDirectExtended(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)660 static bool HandleDirectExtended(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
661 // Handle direct/extended address. Return false on hard error
662 {
663 	bool
664 		fail;
665 
666 	fail=false;
667 	if((opcode->typeMask&M_DIRECT)&&(((operands[0].value>=0)&&(operands[0].value<256))||!(opcode->typeMask&M_EXTENDED)))
668 	{
669 		if(GenerateByte(opcode->baseOpcode[OT_DIRECT],listingRecord))
670 		{
671 			fail=!GenerateDirectAddress(operands[0].value,operands[0].unresolved,listingRecord);
672 		}
673 		else
674 		{
675 			fail=true;
676 		}
677 	}
678 	else
679 	{
680 		if(GenerateByte(opcode->baseOpcode[OT_EXTENDED],listingRecord))
681 		{
682 			fail=!GenerateExtendedAddress(operands[0].value,operands[0].unresolved,listingRecord);
683 		}
684 		else
685 		{
686 			fail=true;
687 		}
688 	}
689 	if(!fail&&opcode->relativeMode)
690 	{
691 		fail=!GenerateRelativeOffset(operands[1].value,operands[1].unresolved,listingRecord);
692 	}
693 	return(!fail);
694 }
695 
HandleIndexedPiDirect(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)696 static bool HandleIndexedPiDirect(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
697 // Handle X+,direct. Return false on hard error
698 {
699 	bool
700 		fail;
701 
702 	fail=false;
703 	if(GenerateByte(opcode->baseOpcode[OT_INDEXED_PI_DIRECT],listingRecord))
704 	{
705 		fail=!GenerateDirectAddress(operands[1].value,operands[1].unresolved,listingRecord);
706 	}
707 	else
708 	{
709 		fail=true;
710 	}
711 	if(!fail&&opcode->relativeMode)
712 	{
713 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
714 	}
715 	return(!fail);
716 }
717 
HandleImmediate8Direct(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)718 static bool HandleImmediate8Direct(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
719 // Handle #immediate,direct. Return false on hard error
720 {
721 	bool
722 		fail;
723 
724 	fail=false;
725 	if(GenerateByte(opcode->baseOpcode[OT_IMM8_DIRECT],listingRecord))
726 	{
727 		if(GenerateImmediate8(operands[0].value,operands[0].unresolved,listingRecord))
728 		{
729 			fail=!GenerateDirectAddress(operands[1].value,operands[1].unresolved,listingRecord);
730 		}
731 		else
732 		{
733 			fail=true;
734 		}
735 	}
736 	else
737 	{
738 		fail=true;
739 	}
740 	if(!fail&&opcode->relativeMode)
741 	{
742 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
743 	}
744 	return(!fail);
745 }
746 
HandleOffsetIndexed(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)747 static bool HandleOffsetIndexed(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
748 // Handle offset,X. Return false on hard error
749 {
750 	bool
751 		fail;
752 
753 	fail=false;
754 	if((opcode->typeMask&M_OFF8_INDEXED)&&(((operands[0].value>=0)&&(operands[0].value<256))||!(opcode->typeMask&M_OFF16_INDEXED)))
755 	{
756 		if(GenerateByte(opcode->baseOpcode[OT_OFF8_INDEXED],listingRecord))
757 		{
758 			fail=!GenerateOffset8(operands[0].value,operands[0].unresolved,listingRecord);
759 		}
760 		else
761 		{
762 			fail=true;
763 		}
764 	}
765 	else
766 	{
767 		if(GenerateByte(opcode->baseOpcode[OT_OFF16_INDEXED],listingRecord))
768 		{
769 			fail=!GenerateOffset16(operands[0].value,operands[0].unresolved,listingRecord);
770 		}
771 		else
772 		{
773 			fail=true;
774 		}
775 	}
776 	if(!fail&&opcode->relativeMode)
777 	{
778 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
779 	}
780 	return(!fail);
781 }
782 
HandleDirectIndexedPi(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)783 static bool HandleDirectIndexedPi(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
784 // Handle direct,X+. Return false on hard error
785 {
786 	bool
787 		fail;
788 
789 	fail=false;
790 	if(GenerateByte(opcode->baseOpcode[OT_DIRECT_INDEXED_PI],listingRecord))
791 	{
792 		fail=!GenerateDirectAddress(operands[0].value,operands[0].unresolved,listingRecord);
793 	}
794 	else
795 	{
796 		fail=true;
797 	}
798 	if(!fail&&opcode->relativeMode)
799 	{
800 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
801 	}
802 	return(!fail);
803 }
804 
HandleOffsetIndexedPi(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)805 static bool HandleOffsetIndexedPi(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
806 // Handle offset,X+. Return false on hard error
807 {
808 	bool
809 		fail;
810 
811 	fail=false;
812 	if(GenerateByte(opcode->baseOpcode[OT_OFF8_INDEXED_PI],listingRecord))
813 	{
814 		fail=!GenerateOffset8(operands[0].value,operands[0].unresolved,listingRecord);
815 	}
816 	else
817 	{
818 		fail=true;
819 	}
820 	if(!fail&&opcode->relativeMode)
821 	{
822 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
823 	}
824 	return(!fail);
825 }
826 
HandleOffsetSp(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)827 static bool HandleOffsetSp(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
828 // Handle offset,SP. Return false on hard error
829 {
830 	bool
831 		fail;
832 
833 	fail=false;
834 	if(GenerateByte(SP_PREAMBLE,listingRecord))	// output preamble that tells the '08 this is a SP referencing instruction
835 	{
836 		if((opcode->typeMask&M_OFF8_SP)&&(((operands[0].value>=0)&&(operands[0].value<256))||!(opcode->typeMask&M_OFF16_SP)))
837 		{
838 			if(GenerateByte(opcode->baseOpcode[OT_OFF8_SP],listingRecord))
839 			{
840 				fail=!GenerateOffset8(operands[0].value,operands[0].unresolved,listingRecord);
841 			}
842 			else
843 			{
844 				fail=true;
845 			}
846 		}
847 		else
848 		{
849 			if(GenerateByte(opcode->baseOpcode[OT_OFF16_SP],listingRecord))
850 			{
851 				fail=!GenerateOffset16(operands[0].value,operands[0].unresolved,listingRecord);
852 			}
853 			else
854 			{
855 				fail=true;
856 			}
857 		}
858 	}
859 	if(!fail&&opcode->relativeMode)
860 	{
861 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
862 	}
863 	return(!fail);
864 }
865 
HandleBitDirect(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)866 static bool HandleBitDirect(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
867 // Handle bit,direct. Return false on hard error
868 {
869 	bool
870 		fail;
871 
872 	fail=false;
873 	Check8BitIndexRange(operands[0].value,true,true);
874 	operands[0].value&=0x07;
875 	if(GenerateByte(opcode->baseOpcode[OT_BIT_DIRECT]|(operands[0].value<<1),listingRecord))
876 	{
877 		fail=!GenerateDirectAddress(operands[1].value,operands[1].unresolved,listingRecord);
878 	}
879 	else
880 	{
881 		fail=true;
882 	}
883 	if(!fail&&opcode->relativeMode)
884 	{
885 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
886 	}
887 	return(!fail);
888 }
889 
HandleDirectDirect(OPCODE * opcode,OPERAND * operands,LISTING_RECORD * listingRecord)890 static bool HandleDirectDirect(OPCODE *opcode,OPERAND *operands,LISTING_RECORD *listingRecord)
891 // Handle direct,direct. Return false on hard error
892 {
893 	bool
894 		fail;
895 
896 	fail=false;
897 	if(GenerateByte(opcode->baseOpcode[OT_DIRECT_DIRECT],listingRecord))
898 	{
899 		if(GenerateDirectAddress(operands[0].value,operands[0].unresolved,listingRecord))
900 		{
901 			fail=!GenerateDirectAddress(operands[1].value,operands[1].unresolved,listingRecord);
902 		}
903 		else
904 		{
905 			fail=true;
906 		}
907 	}
908 	else
909 	{
910 		fail=true;
911 	}
912 	if(!fail&&opcode->relativeMode)
913 	{
914 		fail=!GenerateRelativeOffset(operands[2].value,operands[2].unresolved,listingRecord);
915 	}
916 	return(!fail);
917 }
918 
ParseOperands(const char * line,unsigned int * lineIndex,unsigned int * numOperands,OPERAND * operands)919 static bool ParseOperands(const char *line,unsigned int *lineIndex,unsigned int *numOperands,OPERAND *operands)
920 // parse from 0 to 3 operands from the line
921 // return the operands parsed
922 // If something does not look right, return false
923 {
924 	bool
925 		fail;
926 	bool
927 		initialComma;						// only allowed if first parameter is index reg
928 
929 	fail=false;
930 	*numOperands=0;
931 	if(!ParseComment(line,lineIndex))	// make sure not at end of line
932 	{
933 		initialComma=ParseCommaSeparator(line,lineIndex);
934 		if(!ParseComment(line,lineIndex))	// make sure not at end of line
935 		{
936 			if(ParseOperand(line,lineIndex,&operands[0]))
937 			{
938 				if(!initialComma||(operands[0].type==POT_INDEX)||(operands[0].type==POT_INDEX_PI))
939 				{
940 					*numOperands=1;
941 					if(!ParseComment(line,lineIndex))	// make sure not at end of line
942 					{
943 						if(ParseCommaSeparator(line,lineIndex))
944 						{
945 							if(!ParseComment(line,lineIndex))	// make sure not at end of line
946 							{
947 								if(ParseOperand(line,lineIndex,&operands[1]))
948 								{
949 									*numOperands=2;
950 									if(!ParseComment(line,lineIndex))	// make sure not at end of line
951 									{
952 										if(ParseCommaSeparator(line,lineIndex))
953 										{
954 											if(!ParseComment(line,lineIndex))	// make sure not at end of line
955 											{
956 												if(ParseOperand(line,lineIndex,&operands[2]))
957 												{
958 													*numOperands=3;
959 													if(!ParseComment(line,lineIndex))	// make sure were at end of line
960 													{
961 														fail=true;
962 													}
963 												}
964 												else
965 												{
966 													fail=true;
967 												}
968 											}
969 											else
970 											{
971 												fail=true;
972 											}
973 										}
974 										else
975 										{
976 											fail=true;
977 										}
978 									}
979 								}
980 								else
981 								{
982 									fail=true;
983 								}
984 							}
985 							else
986 							{
987 								fail=true;
988 							}
989 						}
990 						else
991 						{
992 							fail=true;
993 						}
994 					}
995 				}
996 				else
997 				{
998 					fail=true;
999 				}
1000 			}
1001 		}
1002 		else
1003 		{
1004 			fail=true;
1005 		}
1006 	}
1007 	return(!fail);
1008 }
1009 
MatchOpcode(const char * string)1010 static OPCODE *MatchOpcode(const char *string)
1011 // match opcodes for this processor, return NULL if none matched
1012 {
1013 	return((OPCODE *)STFindDataForNameNoCase(*((SYM_TABLE **)(currentProcessor->processorData)),string));
1014 }
1015 
AttemptOpcode(const char * line,unsigned int * lineIndex,LISTING_RECORD * listingRecord,bool * success)1016 static bool AttemptOpcode(const char *line,unsigned int *lineIndex,LISTING_RECORD *listingRecord,bool *success)
1017 // look at the type of opcode available, parse operands as allowed
1018 // If this matches anything, it will set success true.
1019 // If there's some sort of hard failure, this will return false
1020 {
1021 	bool
1022 		result;
1023 	unsigned int
1024 		tempIndex;
1025 	char
1026 		string[MAX_STRING];
1027 	OPCODE
1028 		*opcode;
1029 	unsigned int
1030 		numOperands;
1031 	OPERAND
1032 		operands[3];
1033 
1034 	result=true;					// no hard failure yet
1035 	*success=false;					// no match yet
1036 	tempIndex=*lineIndex;
1037 	if(ParseName(line,&tempIndex,string))						// something that looks like an opcode?
1038 	{
1039 		if((opcode=MatchOpcode(string)))						// found opcode?
1040 		{
1041 			*lineIndex=tempIndex;								// actually push forward on the line
1042 			*success=true;
1043 			if(ParseOperands(line,lineIndex,&numOperands,&operands[0]))	// fetch operands for opcode
1044 			{
1045 				if(!opcode->relativeMode||(numOperands&&(operands[numOperands-1].type==POT_VALUE)))	// if relative, make sure last operand is a value
1046 				{
1047 					switch(opcode->relativeMode?(numOperands-1):numOperands)
1048 					{
1049 						case 0:
1050 							if(opcode->typeMask&M_INHERENT)
1051 							{
1052 								result=HandleInherent(opcode,operands,listingRecord);
1053 							}
1054 							else
1055 							{
1056 								ReportBadOperands();
1057 							}
1058 							break;
1059 						case 1:
1060 							switch(operands[0].type)
1061 							{
1062 								case POT_INDEX:
1063 									if(opcode->typeMask&M_INDEXED)
1064 									{
1065 										result=HandleIndexed(opcode,operands,listingRecord);
1066 									}
1067 									else
1068 									{
1069 										ReportBadOperands();
1070 									}
1071 									break;
1072 								case POT_INDEX_PI:
1073 									if(opcode->typeMask&M_INDEXED_PI)
1074 									{
1075 										result=HandleIndexedPi(opcode,operands,listingRecord);
1076 									}
1077 									else
1078 									{
1079 										ReportBadOperands();
1080 									}
1081 									break;
1082 								case POT_IMMEDIATE:
1083 									if(opcode->typeMask&(M_IMM8|M_IMM16))
1084 									{
1085 										result=HandleImmediate(opcode,operands,listingRecord);
1086 									}
1087 									else
1088 									{
1089 										ReportBadOperands();
1090 									}
1091 									break;
1092 								case POT_VALUE:
1093 									if(opcode->typeMask&(M_DIRECT|M_EXTENDED))
1094 									{
1095 										result=HandleDirectExtended(opcode,operands,listingRecord);
1096 									}
1097 									else
1098 									{
1099 										ReportBadOperands();
1100 									}
1101 									break;
1102 								default:
1103 									ReportBadOperands();
1104 									break;
1105 							}
1106 							break;
1107 						case 2:
1108 							switch(operands[0].type)
1109 							{
1110 								case POT_INDEX_PI:
1111 									if((opcode->typeMask&M_INDEXED_PI_DIRECT)&&(operands[1].type==POT_VALUE))
1112 									{
1113 										result=HandleIndexedPiDirect(opcode,operands,listingRecord);
1114 									}
1115 									else
1116 									{
1117 										ReportBadOperands();
1118 									}
1119 									break;
1120 								case POT_IMMEDIATE:
1121 									if((opcode->typeMask&M_IMM8_DIRECT)&&(operands[1].type==POT_VALUE))
1122 									{
1123 										result=HandleImmediate8Direct(opcode,operands,listingRecord);
1124 									}
1125 									else
1126 									{
1127 										ReportBadOperands();
1128 									}
1129 									break;
1130 								case POT_VALUE:
1131 									switch(operands[1].type)
1132 									{
1133 										case POT_INDEX:
1134 											if(opcode->typeMask&(M_OFF8_INDEXED|M_OFF16_INDEXED))
1135 											{
1136 												result=HandleOffsetIndexed(opcode,operands,listingRecord);
1137 											}
1138 											else
1139 											{
1140 												ReportBadOperands();
1141 											}
1142 											break;
1143 										case POT_INDEX_PI:
1144 											if(opcode->typeMask&M_DIRECT_INDEXED_PI)
1145 											{
1146 												result=HandleDirectIndexedPi(opcode,operands,listingRecord);
1147 											}
1148 											else if(opcode->typeMask&M_OFF8_INDEXED_PI)
1149 											{
1150 												result=HandleOffsetIndexedPi(opcode,operands,listingRecord);
1151 											}
1152 											else
1153 											{
1154 												ReportBadOperands();
1155 											}
1156 											break;
1157 										case POT_SP:
1158 											if(opcode->typeMask&(M_OFF8_SP|M_OFF16_SP))
1159 											{
1160 												result=HandleOffsetSp(opcode,operands,listingRecord);
1161 											}
1162 											else
1163 											{
1164 												ReportBadOperands();
1165 											}
1166 											break;
1167 										case POT_VALUE:
1168 											if(opcode->typeMask&M_BIT_DIRECT)
1169 											{
1170 												result=HandleBitDirect(opcode,operands,listingRecord);
1171 											}
1172 											else if(opcode->typeMask&M_DIRECT_DIRECT)
1173 											{
1174 												result=HandleDirectDirect(opcode,operands,listingRecord);
1175 											}
1176 											else
1177 											{
1178 												ReportBadOperands();
1179 											}
1180 											break;
1181 										default:
1182 											ReportBadOperands();
1183 											break;
1184 									}
1185 									break;
1186 								default:
1187 									ReportBadOperands();
1188 									break;
1189 							}
1190 							break;
1191 						default:
1192 							ReportBadOperands();
1193 							break;
1194 					}
1195 				}
1196 				else
1197 				{
1198 					ReportBadOperands();
1199 				}
1200 			}
1201 			else
1202 			{
1203 				ReportBadOperands();
1204 			}
1205 		}
1206 	}
1207 	return(result);
1208 }
1209 
AttemptPseudoOpcode(const char * line,unsigned int * lineIndex,const PARSED_LABEL * lineLabel,LISTING_RECORD * listingRecord,bool * success)1210 static bool AttemptPseudoOpcode(const char *line,unsigned int *lineIndex,const PARSED_LABEL *lineLabel,LISTING_RECORD *listingRecord,bool *success)
1211 // See if the next thing on the line looks like a pseudo-op.
1212 // If this matches anything, it will set success true.
1213 // If there's some sort of hard failure, this will return false
1214 {
1215 	bool
1216 		result;
1217 	unsigned int
1218 		tempIndex;
1219 	char
1220 		string[MAX_STRING];
1221 	PSEUDO_OPCODE
1222 		*opcode;
1223 
1224 	result=true;					// no hard failure yet
1225 	*success=false;					// no match yet
1226 	tempIndex=*lineIndex;
1227 	if(ParseName(line,&tempIndex,string))						// something that looks like an opcode?
1228 	{
1229 		if((opcode=(PSEUDO_OPCODE *)STFindDataForNameNoCase(pseudoOpcodeSymbols,string)))		// matches global pseudo-op?
1230 		{
1231 			*lineIndex=tempIndex;								// actually push forward on the line
1232 			*success=true;
1233 			result=opcode->function(string,line,lineIndex,lineLabel,listingRecord);
1234 		}
1235 	}
1236 	return(result);
1237 }
1238 
SelectProcessor(PROCESSOR * processor)1239 static bool SelectProcessor(PROCESSOR *processor)
1240 // A processor in this family is being selected to assemble with
1241 {
1242 	currentProcessor=processor;
1243 	return(true);
1244 }
1245 
DeselectProcessor(PROCESSOR * processor)1246 static void DeselectProcessor(PROCESSOR *processor)
1247 // A processor in this family is being deselected
1248 {
1249 }
1250 
UnInitFamily()1251 static void UnInitFamily()
1252 // undo what InitFamily did
1253 {
1254 	STDisposeSymbolTable(opcodeSymbols68hc08);
1255 	STDisposeSymbolTable(opcodeSymbols6805);
1256 	STDisposeSymbolTable(pseudoOpcodeSymbols);
1257 }
1258 
InitFamily()1259 static bool InitFamily()
1260 // initialize symbol table
1261 {
1262 	unsigned int
1263 		i;
1264 	bool
1265 		fail;
1266 
1267 	fail=false;
1268 	if((pseudoOpcodeSymbols=STNewSymbolTable(elementsof(pseudoOpcodes))))
1269 	{
1270 		for(i=0;!fail&&(i<elementsof(pseudoOpcodes));i++)
1271 		{
1272 			if(!STAddEntryAtEnd(pseudoOpcodeSymbols,pseudoOpcodes[i].name,&pseudoOpcodes[i]))
1273 			{
1274 				fail=true;
1275 			}
1276 		}
1277 		if(!fail)
1278 		{
1279 			if((opcodeSymbols6805=STNewSymbolTable(elementsof(Opcodes6805))))
1280 			{
1281 				for(i=0;!fail&&(i<elementsof(Opcodes6805));i++)
1282 				{
1283 					if(!STAddEntryAtEnd(opcodeSymbols6805,Opcodes6805[i].name,&Opcodes6805[i]))
1284 					{
1285 						fail=true;
1286 					}
1287 				}
1288 				if(!fail)
1289 				{
1290 					if((opcodeSymbols68hc08=STNewSymbolTable(elementsof(Opcodes68hc08))))
1291 					{
1292 						for(i=0;!fail&&(i<elementsof(Opcodes68hc08));i++)
1293 						{
1294 							if(!STAddEntryAtEnd(opcodeSymbols68hc08,Opcodes68hc08[i].name,&Opcodes68hc08[i]))
1295 							{
1296 								fail=true;
1297 							}
1298 						}
1299 						if(!fail)
1300 						{
1301 							return(true);
1302 						}
1303 						STDisposeSymbolTable(opcodeSymbols68hc08);
1304 					}
1305 				}
1306 				STDisposeSymbolTable(opcodeSymbols6805);
1307 			}
1308 		}
1309 		STDisposeSymbolTable(pseudoOpcodeSymbols);
1310 	}
1311 	return(false);
1312 }
1313 
1314 // processors handled here (the constuctors for these variables link them to the global
1315 // list of processors that the assembler knows how to handle)
1316 
1317 static PROCESSOR_FAMILY
1318 	processorFamily("Motorola 6805",InitFamily,UnInitFamily,SelectProcessor,DeselectProcessor,AttemptPseudoOpcode,AttemptOpcode);
1319 
1320 static PROCESSOR
1321 	processors[]=
1322 	{
1323 		PROCESSOR(&processorFamily,"6805",&opcodeSymbols6805),
1324 		PROCESSOR(&processorFamily,"68hc05",&opcodeSymbols6805),
1325 		PROCESSOR(&processorFamily,"68705",&opcodeSymbols6805),
1326 		PROCESSOR(&processorFamily,"68hc08",&opcodeSymbols68hc08),
1327 	};
1328