#include "Assembler.h"
#include <assert.h>
#include <string.h>


AsmInsData	DecInsData[256] = {
	{ASMIT_BRK, ASMIM_IMPLIED},
	{ASMIT_ORA, ASMIM_INDIRECT_X},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_ORA, ASMIM_ZERO_PAGE},
	{ASMIT_ASL, ASMIM_ZERO_PAGE},
	{ASMIT_INV},
	{ASMIT_PHP, ASMIM_IMPLIED},
	{ASMIT_ORA, ASMIM_IMMEDIATE},
	{ASMIT_ASL, ASMIM_IMPLIED},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_ORA, ASMIM_ABSOLUTE},
	{ASMIT_ASL, ASMIM_ABSOLUTE},
	{ASMIT_INV},

	{ASMIT_BPL, ASMIM_RELATIVE },
	{ASMIT_ORA, ASMIM_INDIRECT_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_ORA, ASMIM_ZERO_PAGE_X},
	{ASMIT_ASL, ASMIM_ZERO_PAGE_X},
	{ASMIT_INV},
	{ASMIT_CLC, ASMIM_IMPLIED},
	{ASMIT_ORA, ASMIM_ABSOLUTE_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_ORA, ASMIM_ABSOLUTE_X},
	{ASMIT_ASL, ASMIM_ABSOLUTE_X},
	{ASMIT_INV},


	{ASMIT_JSR, ASMIM_ABSOLUTE},
	{ASMIT_AND, ASMIM_INDIRECT_X},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_BIT, ASMIM_ZERO_PAGE},
	{ASMIT_AND, ASMIM_ZERO_PAGE},
	{ASMIT_ROL, ASMIM_ZERO_PAGE},
	{ASMIT_INV},
	{ASMIT_PLP, ASMIM_IMPLIED},
	{ASMIT_AND, ASMIM_IMMEDIATE},
	{ASMIT_ROL, ASMIM_IMPLIED},
	{ASMIT_INV},
	{ASMIT_BIT, ASMIM_ABSOLUTE},
	{ASMIT_AND, ASMIM_ABSOLUTE},
	{ASMIT_ROL, ASMIM_ABSOLUTE},
	{ASMIT_INV},

	{ASMIT_BMI, ASMIM_RELATIVE },
	{ASMIT_AND, ASMIM_INDIRECT_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_AND, ASMIM_ZERO_PAGE_X},
	{ASMIT_ROL, ASMIM_ZERO_PAGE_X},
	{ASMIT_INV},
	{ASMIT_SEC, ASMIM_IMPLIED},
	{ASMIT_AND, ASMIM_ABSOLUTE_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_AND, ASMIM_ABSOLUTE_X},
	{ASMIT_ROL, ASMIM_ABSOLUTE_X},
	{ASMIT_INV},


	{ASMIT_RTI, ASMIM_IMPLIED},
	{ASMIT_EOR, ASMIM_INDIRECT_X},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_EOR, ASMIM_ZERO_PAGE},
	{ASMIT_LSR, ASMIM_ZERO_PAGE},
	{ASMIT_INV},
	{ASMIT_PHA, ASMIM_IMPLIED},
	{ASMIT_EOR, ASMIM_IMMEDIATE},
	{ASMIT_LSR, ASMIM_IMPLIED},
	{ASMIT_INV},
	{ASMIT_JMP, ASMIM_ABSOLUTE},
	{ASMIT_EOR, ASMIM_ABSOLUTE},
	{ASMIT_LSR, ASMIM_ABSOLUTE},
	{ASMIT_INV},

	{ASMIT_BVC, ASMIM_RELATIVE },
	{ASMIT_EOR, ASMIM_INDIRECT_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_EOR, ASMIM_ZERO_PAGE_X},
	{ASMIT_LSR, ASMIM_ZERO_PAGE_X},
	{ASMIT_INV},
	{ASMIT_CLI, ASMIM_IMPLIED},
	{ASMIT_EOR, ASMIM_ABSOLUTE_Y},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_INV},
	{ASMIT_EOR, ASMIM_ABSOLUTE_X},
	{ASMIT_LSR, ASMIM_ABSOLUTE_X},
	{ASMIT_INV},


	{ ASMIT_RTS, ASMIM_IMPLIED },
	{ ASMIT_ADC, ASMIM_INDIRECT_X },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_ADC, ASMIM_ZERO_PAGE },
	{ ASMIT_ROR, ASMIM_ZERO_PAGE },
	{ ASMIT_INV },
	{ ASMIT_PLA, ASMIM_IMPLIED },
	{ ASMIT_ADC, ASMIM_IMMEDIATE },
	{ ASMIT_ROR, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_JMP, ASMIM_INDIRECT },
	{ ASMIT_ADC, ASMIM_ABSOLUTE },
	{ ASMIT_ROR, ASMIM_ABSOLUTE },
	{ ASMIT_INV },

	{ ASMIT_BVS, ASMIM_RELATIVE },
	{ ASMIT_ADC, ASMIM_INDIRECT_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_ADC, ASMIM_ZERO_PAGE_X },
	{ ASMIT_ROR, ASMIM_ZERO_PAGE_X },
	{ ASMIT_INV },
	{ ASMIT_SEI, ASMIM_IMPLIED },
	{ ASMIT_ADC, ASMIM_ABSOLUTE_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_ADC, ASMIM_ABSOLUTE_X },
	{ ASMIT_ROR, ASMIM_ABSOLUTE_X },
	{ ASMIT_INV },


	{ ASMIT_INV },
	{ ASMIT_STA, ASMIM_INDIRECT_X },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_STY, ASMIM_ZERO_PAGE },
	{ ASMIT_STA, ASMIM_ZERO_PAGE },
	{ ASMIT_STX, ASMIM_ZERO_PAGE },
	{ ASMIT_INV },
	{ ASMIT_DEY, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_TXA, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_STY, ASMIM_ABSOLUTE },
	{ ASMIT_STA, ASMIM_ABSOLUTE },
	{ ASMIT_STX, ASMIM_ABSOLUTE },
	{ ASMIT_INV },

	{ ASMIT_BCC, ASMIM_RELATIVE },
	{ ASMIT_STA, ASMIM_INDIRECT_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_STY, ASMIM_ZERO_PAGE_X },
	{ ASMIT_STA, ASMIM_ZERO_PAGE_X },
	{ ASMIT_STX, ASMIM_ZERO_PAGE_Y },
	{ ASMIT_INV },
	{ ASMIT_TYA, ASMIM_IMPLIED },
	{ ASMIT_STA, ASMIM_ABSOLUTE_Y },
	{ ASMIT_TXS },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_STA, ASMIM_ABSOLUTE_X },
	{ ASMIT_INV },
	{ ASMIT_INV },


	{ ASMIT_LDY, ASMIM_IMMEDIATE },
	{ ASMIT_LDA, ASMIM_INDIRECT_X },
	{ ASMIT_LDX, ASMIM_IMMEDIATE },
	{ ASMIT_INV },
	{ ASMIT_LDY, ASMIM_ZERO_PAGE },
	{ ASMIT_LDA, ASMIM_ZERO_PAGE },
	{ ASMIT_LDX, ASMIM_ZERO_PAGE },
	{ ASMIT_INV },
	{ ASMIT_TAY, ASMIM_IMPLIED },
	{ ASMIT_LDA, ASMIM_IMMEDIATE },
	{ ASMIT_TAX, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_LDY, ASMIM_ABSOLUTE },
	{ ASMIT_LDA, ASMIM_ABSOLUTE },
	{ ASMIT_LDX, ASMIM_ABSOLUTE },
	{ ASMIT_INV },

	{ ASMIT_BCS, ASMIM_RELATIVE },
	{ ASMIT_LDA, ASMIM_INDIRECT_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_LDY, ASMIM_ZERO_PAGE_X },
	{ ASMIT_LDA, ASMIM_ZERO_PAGE_X },
	{ ASMIT_LDX, ASMIM_ZERO_PAGE_Y },
	{ ASMIT_INV },
	{ ASMIT_CLV, ASMIM_IMPLIED },
	{ ASMIT_LDA, ASMIM_ABSOLUTE_Y },
	{ ASMIT_TSX, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_LDY, ASMIM_ABSOLUTE_X },
	{ ASMIT_LDA, ASMIM_ABSOLUTE_X },
	{ ASMIT_LDX, ASMIM_ABSOLUTE_Y },
	{ ASMIT_INV },


	{ ASMIT_CPY, ASMIM_IMMEDIATE },
	{ ASMIT_CMP, ASMIM_INDIRECT_X },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_CPY, ASMIM_ZERO_PAGE },
	{ ASMIT_CMP, ASMIM_ZERO_PAGE },
	{ ASMIT_DEC, ASMIM_ZERO_PAGE },
	{ ASMIT_INV },
	{ ASMIT_INY, ASMIM_IMPLIED },
	{ ASMIT_CMP, ASMIM_IMMEDIATE },
	{ ASMIT_DEX, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_CPY, ASMIM_ABSOLUTE },
	{ ASMIT_CMP, ASMIM_ABSOLUTE },
	{ ASMIT_DEC, ASMIM_ABSOLUTE },
	{ ASMIT_INV },

	{ ASMIT_BNE, ASMIM_RELATIVE },
	{ ASMIT_CMP, ASMIM_INDIRECT_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_CMP, ASMIM_ZERO_PAGE_X },
	{ ASMIT_DEC, ASMIM_ZERO_PAGE_X },
	{ ASMIT_INV },
	{ ASMIT_CLD, ASMIM_IMPLIED },
	{ ASMIT_CMP, ASMIM_ABSOLUTE_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_CMP, ASMIM_ABSOLUTE_X },
	{ ASMIT_DEC, ASMIM_ABSOLUTE_X },
	{ ASMIT_INV },

	{ ASMIT_CPX, ASMIM_IMMEDIATE },
	{ ASMIT_SBC, ASMIM_INDIRECT_X },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_CPX, ASMIM_ZERO_PAGE },
	{ ASMIT_SBC, ASMIM_ZERO_PAGE },
	{ ASMIT_INC, ASMIM_ZERO_PAGE },
	{ ASMIT_INV },
	{ ASMIT_INX, ASMIM_IMPLIED },
	{ ASMIT_SBC, ASMIM_IMMEDIATE },
	{ ASMIT_NOP, ASMIM_IMPLIED },
	{ ASMIT_INV },
	{ ASMIT_CPX, ASMIM_ABSOLUTE },
	{ ASMIT_SBC, ASMIM_ABSOLUTE },
	{ ASMIT_INC, ASMIM_ABSOLUTE },
	{ ASMIT_INV },

	{ ASMIT_BEQ, ASMIM_RELATIVE },
	{ ASMIT_SBC, ASMIM_INDIRECT_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_SBC, ASMIM_ZERO_PAGE_X },
	{ ASMIT_INC, ASMIM_ZERO_PAGE_X },
	{ ASMIT_INV },
	{ ASMIT_SED, ASMIM_IMPLIED },
	{ ASMIT_SBC, ASMIM_ABSOLUTE_Y },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_INV },
	{ ASMIT_SBC, ASMIM_ABSOLUTE_X },
	{ ASMIT_INC, ASMIM_ABSOLUTE_X },
	{ ASMIT_INV },
};

short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];

const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
	"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL", "BRK", "BVC", "BVS", "CLC",
	"CLD", "CLI", "CLV", "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "EOR", "INC", "INX", "INY", "JMP",
	"JSR", "LDA", "LDX", "LDY", "LSR", "NOP", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL", "ROR", "RTI",
	"RTS", "SBC", "SEC", "SED", "SEI", "STA", "STX", "STY", "TAX", "TAY", "TSX", "TXA", "TXS", "TYA",
	"INV", "BYT"
};

int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
	1,
	2,
	2,
	2,
	2,
	3,
	3,
	3,
	3,
	2,
	2,
	2,
	0,
	2
};

void InitAssembler(void)
{
	for (int i = 0; i < NUM_ASM_INS_TYPES; i++)
	{
		for (int j = 0; j < NUM_ASM_INS_MODES; j++)
		{
			AsmInsOpcodes[i][j] = -1;
		}
	}

	for (int i = 0; i < 256; i++)
	{
		const AsmInsData& di(DecInsData[i]);
		if (di.mType != ASMIT_INV)
		{
			assert(AsmInsOpcodes[di.mType][di.mMode] == -1);
			AsmInsOpcodes[di.mType][di.mMode] = i;
		}
	}

	AsmInsOpcodes[ASMIT_BYTE][ASMIM_ZERO_PAGE] = 0;
}

int AsmInsSize(AsmInsType type, AsmInsMode mode)
{
	if (type < ASMIT_INV && mode >= ASMIM_IMPLIED && mode < NUM_ASM_INS_MODES)
		return AsmInsModeSize[mode];
	else
		return 1;
}

uint32 AsmInsFlags(AsmInsType type, AsmInsMode mode)
{
	uint32	flags = 0;

	// Accu
	switch (type)
	{
	case ASMIT_LDA:
		flags |= ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_LDX:
		flags |= ASMIFLG_CHANGES_XREG | ASMIFLG_CHANGES_ZFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_LDY:
		flags |= ASMIFLG_CHANGES_YREG | ASMIFLG_CHANGES_ZFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_STA:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_MEMORY;
		break;

	case ASMIT_STX:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_CHANGES_MEMORY;
		break;

	case ASMIT_STY:
		flags |= ASMIFLG_USES_YREG | ASMIFLG_CHANGES_MEMORY;
		break;

	case ASMIT_ADC:
	case ASMIT_SBC:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_USES_CFLAG | ASMIFLG_CHANGES_CFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_AND:
	case ASMIT_ORA:
	case ASMIT_EOR:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_ASL:
	case ASMIT_LSR:
		flags |= ASMIFLG_CHANGES_CFLAG | ASMIFLG_CHANGES_ZFLAG;
		if (mode == ASMIM_IMPLIED)
			flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ACCU;
		else
			flags |= ASMIFLG_USES_MEMORY | ASMIFLG_CHANGES_MEMORY;
		break;

	case ASMIT_ROL:
	case ASMIT_ROR:
		flags |= ASMIFLG_USES_CFLAG | ASMIFLG_CHANGES_CFLAG | ASMIFLG_CHANGES_ZFLAG;
		if (mode == ASMIM_IMPLIED)
			flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ACCU;
		else
			flags |= ASMIFLG_USES_MEMORY | ASMIFLG_CHANGES_MEMORY;
		break;

	case ASMIT_CMP:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_CHANGES_CFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;
	case ASMIT_CPX:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_CHANGES_CFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;
	case ASMIT_CPY:
		flags |= ASMIFLG_USES_YREG | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_CHANGES_CFLAG;
		if (mode != ASMIM_IMMEDIATE)
			flags |= ASMIFLG_USES_MEMORY;
		break;

	case ASMIT_DEX:
	case ASMIT_INX:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_CHANGES_XREG;
		break;

	case ASMIT_DEY:
	case ASMIT_INY:
		flags |= ASMIFLG_USES_YREG | ASMIFLG_CHANGES_ZFLAG | ASMIFLG_CHANGES_YREG;
		break;

	case ASMIT_DEC:
	case ASMIT_INC:
		flags |= ASMIFLG_USES_MEMORY | ASMIFLG_CHANGES_MEMORY | ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_BCC:
	case ASMIT_BCS:
		flags |= ASMIFLG_USES_CFLAG | ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_BEQ:
	case ASMIT_BMI:
	case ASMIT_BNE:
	case ASMIT_BPL:
	case ASMIT_BVC:
	case ASMIT_BVS:
		flags |= ASMIFLG_USES_ZFLAG | ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_JMP:
		flags |= ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_CLC:
	case ASMIT_SEC:
		flags |= ASMIFLG_CHANGES_CFLAG;
		break;

	case ASMIT_BIT:
		flags |= ASMIFLG_USES_MEMORY | ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_CLV:
		flags |= ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_TAX:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_XREG | ASMIFLG_CHANGES_ZFLAG;
		break;
	case ASMIT_TAY:
		flags |= ASMIFLG_USES_ACCU | ASMIFLG_CHANGES_YREG | ASMIFLG_CHANGES_ZFLAG;
		break;
	case ASMIT_TSX:
		flags |= ASMIFLG_USES_STACK | ASMIFLG_CHANGES_XREG | ASMIFLG_CHANGES_ZFLAG;
		break;
	case ASMIT_TXA:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		break;
	case ASMIT_TXS:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_CHANGES_STACK | ASMIFLG_CHANGES_ZFLAG;
		break;
	case ASMIT_TYA:
		flags |= ASMIFLG_USES_YREG | ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_PLA:
		flags |= ASMIFLG_USES_STACK | ASMIFLG_CHANGES_STACK | ASMIFLG_CHANGES_ACCU | ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_PHA:
		flags |= ASMIFLG_USES_STACK | ASMIFLG_CHANGES_STACK | ASMIFLG_USES_ACCU;
		break;

	case ASMIT_PLP:
		flags |= ASMIFLG_USES_STACK | ASMIFLG_CHANGES_STACK | ASMIFLG_CHANGES_CFLAG | ASMIFLG_CHANGES_ZFLAG;
		break;

	case ASMIT_PHP:
		flags |= ASMIFLG_USES_STACK | ASMIFLG_CHANGES_STACK | ASMIFLG_USES_CFLAG | ASMIFLG_USES_ZFLAG;
		break;

	case ASMIT_JSR:
		flags |= ASMIFLG_USES_ALL | ASMIFLG_CHANGES_ALL | ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_RTS:
	case ASMIT_RTI:
		flags |= ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_BRK:
		flags |= ASMIFLG_CONTROL_FLOW;
		break;

	case ASMIT_CLI:
	case ASMIT_SEI:
	case ASMIT_CLD:
	case ASMIT_SED:
		break;

	case ASMIT_NOP:
		break;
	}

	switch (mode)
	{
	case ASMIM_ABSOLUTE_X:
	case ASMIM_ZERO_PAGE_X:
		flags |= ASMIFLG_USES_XREG;
		break;
	case ASMIM_INDIRECT_X:
		flags |= ASMIFLG_USES_XREG | ASMIFLG_USES_MEMORY;
		break;

	case ASMIM_ABSOLUTE_Y:
	case ASMIM_ZERO_PAGE_Y:
		flags |= ASMIFLG_USES_YREG;
		break;
	case ASMIM_INDIRECT_Y:
		flags |= ASMIFLG_USES_YREG | ASMIFLG_USES_MEMORY;
		break;
	}
	return flags;
}

static inline char toupper(char ch)
{
	if (ch >= 'a' && ch <= 'z')
		return ch - 'a' + 'A';
	else
		return ch;
}
AsmInsType FindAsmInstruction(const char* ins)
{
	if (ins && strlen(ins) == 3)
	{
		for (int i = 0; i < NUM_ASM_INS_TYPES; i++)
		{
			if (AsmInstructionNames[i][0] == toupper(ins[0]) &&
				AsmInstructionNames[i][1] == toupper(ins[1]) &&
				AsmInstructionNames[i][2] == toupper(ins[2]))
				return AsmInsType(i);
		}
	}

	return ASMIT_INV;
}

bool HasAsmInstructionMode(AsmInsType type, AsmInsMode mode)
{
	return AsmInsOpcodes[type][mode] != -1;
}

