#pragma once

#include "Ident.h"
#include "MachineTypes.h"

enum AsmInsType : uint8
{
	ASMIT_ADC, ASMIT_AND, ASMIT_ASL, ASMIT_BCC, ASMIT_BCS, ASMIT_BEQ, ASMIT_BIT, ASMIT_BMI, ASMIT_BNE, ASMIT_BPL, ASMIT_BRK, ASMIT_BVC, ASMIT_BVS, ASMIT_CLC,
	ASMIT_CLD, ASMIT_CLI, ASMIT_CLV, ASMIT_CMP, ASMIT_CPX, ASMIT_CPY, ASMIT_DEC, ASMIT_DEX, ASMIT_DEY, ASMIT_EOR, ASMIT_INC, ASMIT_INX, ASMIT_INY, ASMIT_JMP,
	ASMIT_JSR, ASMIT_LDA, ASMIT_LDX, ASMIT_LDY, ASMIT_LSR, ASMIT_NOP, ASMIT_ORA, ASMIT_PHA, ASMIT_PHP, ASMIT_PLA, ASMIT_PLP, ASMIT_ROL, ASMIT_ROR, ASMIT_RTI,
	ASMIT_RTS, ASMIT_SBC, ASMIT_SEC, ASMIT_SED, ASMIT_SEI, ASMIT_STA, ASMIT_STX, ASMIT_STY, ASMIT_TAX, ASMIT_TAY, ASMIT_TSX, ASMIT_TXA, ASMIT_TXS, ASMIT_TYA,
	ASMIT_INV, ASMIT_BYTE,

	NUM_ASM_INS_TYPES
};


enum AsmInsMode : uint8
{
	ASMIM_IMPLIED,
	ASMIM_IMMEDIATE,
	ASMIM_ZERO_PAGE,
	ASMIM_ZERO_PAGE_X,
	ASMIM_ZERO_PAGE_Y,
	ASMIM_ABSOLUTE,
	ASMIM_ABSOLUTE_X,
	ASMIM_ABSOLUTE_Y,
	ASMIM_INDIRECT,
	ASMIM_INDIRECT_X,
	ASMIM_INDIRECT_Y,
	ASMIM_RELATIVE,

	NUM_ASM_INS_MODES,

	ASMIM_IMMEDIATE_ADDRESS,

	NUM_ASM_INS_MODES_X,
};

struct AsmInsData
{
	AsmInsType	mType;
	AsmInsMode	mMode;
};

static const uint32 ASMIFLG_USES_ACCU		= 0x00000001;
static const uint32 ASMIFLG_USES_XREG		= 0x00000002;
static const uint32 ASMIFLG_USES_YREG		= 0x00000004;
static const uint32 ASMIFLG_USES_CFLAG		= 0x00000008;
static const uint32 ASMIFLG_USES_ZFLAG		= 0x00000010;
static const uint32 ASMIFLG_USES_MEMORY		= 0x00000020;
static const uint32 ASMIFLG_USES_STACK		= 0x00000040;
static const uint32 ASMIFLG_USES_ALL		= 0x000000ff;

static const uint32 ASMIFLG_CHANGES_ACCU	= 0x00000100;
static const uint32 ASMIFLG_CHANGES_XREG	= 0x00000200;
static const uint32 ASMIFLG_CHANGES_YREG	= 0x00000400;
static const uint32 ASMIFLG_CHANGES_CFLAG	= 0x00000800;
static const uint32 ASMIFLG_CHANGES_ZFLAG	= 0x00001000;
static const uint32 ASMIFLG_CHANGES_MEMORY	= 0x00002000;
static const uint32 ASMIFLG_CHANGES_STACK	= 0x00004000;
static const uint32 ASMIFLG_CHANGES_ALL		= 0x0000ff00;

static const uint32 ASMIFLG_CONTROL_FLOW	= 0x00010000;


extern AsmInsData	DecInsData[256];

extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];

extern int AsmInsModeSize[NUM_ASM_INS_MODES_X];

extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];

AsmInsType FindAsmInstruction(const char * ins);

bool HasAsmInstructionMode(AsmInsType type, AsmInsMode mode);

int AsmInsSize(AsmInsType type, AsmInsMode mode);

uint32 AsmInsFlags(AsmInsType type, AsmInsMode mode);

void InitAssembler(void);
