/*
 *	disasm.h,	a horribly static yet (hopefully) correct disassembler
 *
 */
#pragma once

namespace ARM
{
	
	
	
	inline static void armdis_cc(u32 cond, char *ccbuff)	// Length is always 8 for our static'{n,m}ess
	{
		switch(cond)
		{	
		case EQ:	sprintf(ccbuff, "EQ");	return;
		case NE:	sprintf(ccbuff, "NE");	return;
		case CS:	sprintf(ccbuff, "CS");	return;
		case CC:	sprintf(ccbuff, "CC");	return;
		case MI:	sprintf(ccbuff, "MI");	return;
		case PL:	sprintf(ccbuff, "PL");	return;
		case VS:	sprintf(ccbuff, "VS");	return;
		case VC:	sprintf(ccbuff, "VC");	return;

		case HI:	sprintf(ccbuff, "HI");	return;
		case LS:	sprintf(ccbuff, "LS");	return;

		case GE:	sprintf(ccbuff, "GE");	return;
		case LT:	sprintf(ccbuff, "LT");	return;
		case GT:	sprintf(ccbuff, "GT");	return;
		case LE:	sprintf(ccbuff, "LE");	return;

		case AL:	return;		// sprintf(ccbuff, "AL");	-- ALways doesn't need to be specified

		case UC:				// 
		default:	return;		// DIE
		}
	}


	inline static void armdis_dp(u32 dpop, char *dpbuff)		// Length is always 8 ...
	{
		switch(dpop)
		{
		case DP_AND:	sprintf(dpbuff, "AND");	return;
		case DP_EOR:	sprintf(dpbuff, "EOR");	return;
		case DP_SUB:	sprintf(dpbuff, "SUB");	return;
		case DP_RSB:	sprintf(dpbuff, "RSB");	return;
		case DP_ADD:	sprintf(dpbuff, "ADD");	return;
		case DP_ADC:	sprintf(dpbuff, "ADC");	return;
		case DP_SBC:	sprintf(dpbuff, "SBC");	return;
		case DP_RSC:	sprintf(dpbuff, "RSC");	return;
		case DP_TST:	sprintf(dpbuff, "TST");	return;
		case DP_TEQ:	sprintf(dpbuff, "TEQ");	return;
		case DP_CMP:	sprintf(dpbuff, "CMP");	return;
		case DP_CMN:	sprintf(dpbuff, "CMN");	return;
		case DP_ORR:	sprintf(dpbuff, "ORR");	return;
		case DP_MOV:	sprintf(dpbuff, "MOV");	return;
		case DP_BIC:	sprintf(dpbuff, "BIC");	return;
		case DP_MVN:	sprintf(dpbuff, "MVN");	return;
		}
	}



	inline static void armdis(u32 op, char *disbuf, u32 len=512)
	{
		char ipref[8]={0}, isuff[8]={0}, icond[8]={0} ;


		//	u32 uOP = ((op>>12)&0xFF00) | ((op>>4)&255) ;

		u32 uCC = ((op>>28) & 0x0F) ;		// 

		u32 uO1 = ((op>>25) & 0x07) ;		// 
		u32 uO2 = ((op>> 4) & 0x01) ;		// 
		u32 uC1 = ((op>>21) & 0x0F) ;		// 
		u32 uC2 = ((op>> 5) & 0x07) ;		// 
		u32 uSB = ((op>>20) & 0x01) ;		// Sign Change Bit


		if (uCC == UC) {

			printf ("DBG armdis has UC instruction %X\n", op);
			sprintf (disbuf, "UNCONDITIONAL / UNHANDLED INSTRUCTION");
			return;

		}


		if (uCC != AL) {
			armdis_cc(uCC,isuff);
		}



		if (uO1 == 0) 
		{

			if (uO2 == 0) {

				if ((uC1 & 0xC) == 8) {
					printf ("DBG armdis 0:0 10xx misc instruction \n", uCC);
					sprintf (disbuf, "UNHANDLED INSTRUCTION 0:");
					return;
				}

				// DP imm.shift			



			}

			else if (uO2 == 1) {

				sprintf (disbuf, "UNHANDLED INSTRUCTION 0:");
			}

		}
		else if (uO1 == 1) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 1:");
		}
		else if (uO1 == 2) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 2:");
		}
		else if (uO1 == 3) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 3:");
		}
		else if (uO1 == 4) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 4:");
		}
		else if (uO1 == 5) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 5:");
		}
		else if (uO1 == 6) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 6:");
		}
		else if (uO1 == 7) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 7:");
		}
		else if (uO1 == 8) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 8:");
		}
		else if (uO1 == 9) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 9:");
		}
		else if (uO1 == 10) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 10:");
		}
		else if (uO1 == 11) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 11:");
		}
		else if (uO1 == 12) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 12:");
		}
		else if (uO1 == 13) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 13:");
		}
		else if (uO1 == 14) {

			sprintf (disbuf, "UNHANDLED INSTRUCTION 14:");
		}
		else if (uO1 == 15)	{

			sprintf (disbuf, "UNHANDLED INSTRUCTION 15:");
		}
		else {

			sprintf (disbuf, "INVALID INSTRUCTION");
		}


	}







};

