library/src/decoders/x86ASM/BP-x86InstDecode.cc
// This function contains an optimized loop that decodes opcodes
// of 1-3 bytes in length to their respective instruction.  The byte string
// provided must be at least 3 bytes long or an improper decode or potential
// segfault could occur.
This function contains an optimized loop that decodes opcodes
of 1-3 bytes in length to their respective instruction.  The byte string
provided must be at least 3 bytes long or an improper decode or potential
segfault could occur.
This function contains an optimized loop that decodes opcodes of 1 - 3 bytes in length to their respective instruction . The byte string provided must be at least 3 bytes long or an improper decode or potential segfault could occur .
P_X86_32_INSTRUCTION X86_32_DecodeOpcode(P_X86_32_INSTRUCTION_TABLE instTable, P_X86_32_DECODED_INSTRUCTION partialDecode, void *buff){
	if(partialDecode == NULL)
		return NULL;
	size_t x = 0;
	size_t baseCounter;
	size_t instLen;
	size_t i = 0;
	size_t badMatch = false;
	unsigned char * inBuff = (unsigned char *) buff;
	unsigned char rm = 0;
	unsigned char plusBaseOpcode = X86_32_IsBytePlusEncodedOpcode(inBuff);
	unsigned char inBuffPlusEncodedDup[15];
	if(plusBaseOpcode != 0){
		memset(inBuffPlusEncodedDup, 0x00, 15);
		memcpy(inBuffPlusEncodedDup, inBuff, 15);
		inBuffPlusEncodedDup[0] = (unsigned char) plusBaseOpcode;
		inBuff = inBuffPlusEncodedDup;
	}
	for(baseCounter = 0; baseCounter < TOP_INSTRUCTION; ){
		nextInst:
		baseCounter++;
		instLen = instTable[baseCounter].binOpcodeLen;
		badMatch = false;
		if(instTable[baseCounter].binOpcodeLen == 0)
			continue;
		for(i = 0; i < instLen; i++ ){
			if( (unsigned char) inBuff[i] != (unsigned char) instTable[baseCounter].binOpcode[i] ){
				badMatch=true;
				break;
			}
			if(instTable[baseCounter].binOpcodeLen > 1){
				if( inBuff[i+1] != (unsigned char) instTable[baseCounter].binOpcode[i+1] ){
					badMatch = true;
					break;
				}
			}
			if(badMatch == true)
				goto nextInst;
			if(X86_32_InstructionSizeVaries(&instTable[baseCounter]) > 0){
				if(partialDecode->addrSizeOverride <= 0 ||
				   partialDecode->operSizeOverride <= 0){
						baseCounter++;
				}
			}
			rm = inBuff[instTable[baseCounter].binOpcodeLen];
			if(instTable[baseCounter].opcodeOperandCount != 0)
			for(x = 0; x < instTable[baseCounter].opcodeOperandCount; x++){
				switch(instTable[baseCounter].opcodeOperand[x]){
					case OA_RM_ONLY_0:
						if(X86_32_GetSlashDigitFromRm(rm) != 0)
							badMatch = true;
						break;
					case OA_RM_ONLY_1:
						if(X86_32_GetSlashDigitFromRm(rm) != 1)
							badMatch = true;
						break;
					case OA_RM_ONLY_2:
						if(X86_32_GetSlashDigitFromRm(rm) != 2)
							badMatch = true;
						break;
					case OA_RM_ONLY_3:
						if(X86_32_GetSlashDigitFromRm(rm) != 3)
							badMatch = true;
						break;
					case OA_RM_ONLY_4:
						if(X86_32_GetSlashDigitFromRm(rm) != 4)
							badMatch = true;
						break;
					case OA_RM_ONLY_5:
						if(X86_32_GetSlashDigitFromRm(rm) != 5)
							badMatch = true;
						break;
					case OA_RM_ONLY_6:
						if(X86_32_GetSlashDigitFromRm(rm) != 6)
							badMatch = true;
						break;
					case OA_RM_ONLY_7:
						if(X86_32_GetSlashDigitFromRm(rm) != 7)
							badMatch = true;
						break;
					default:
						break;
				}
			}
		}
		if((unsigned char ) inBuff[0] != (unsigned char) instTable[baseCounter].binOpcode[0]){
			badMatch = true;
		}
		if(badMatch == false){
			goto end;
		}
	}
	if(badMatch == true){
		return NULL;
	}
	end:
	if(badMatch == false){
		return &instTable[baseCounter];
	}
	return NULL;
}
P_X86_32_INSTRUCTION X86_32_DecodeOpcode ( P_X86_32_INSTRUCTION_TABLE instTable , P_X86_32_DECODED_INSTRUCTION partialDecode , void * buff ) { if ( partialDecode == NULL ) return NULL ; size_t x = 0 ; size_t baseCounter ; size_t instLen ; size_t i = 0 ; size_t badMatch = false ; unsigned char * inBuff = ( unsigned char * ) buff ; unsigned char rm = 0 ; unsigned char plusBaseOpcode = X86_32_IsBytePlusEncodedOpcode ( inBuff ) ; unsigned char inBuffPlusEncodedDup [ 15 ] ; if ( plusBaseOpcode != 0 ) { memset ( inBuffPlusEncodedDup , 0x00 , 15 ) ; memcpy ( inBuffPlusEncodedDup , inBuff , 15 ) ; inBuffPlusEncodedDup [ 0 ] = ( unsigned char ) plusBaseOpcode ; inBuff = inBuffPlusEncodedDup ; } for ( baseCounter = 0 ; baseCounter < TOP_INSTRUCTION ; ) { nextInst : baseCounter ++ ; instLen = instTable [ baseCounter ] . binOpcodeLen ; badMatch = false ; if ( instTable [ baseCounter ] . binOpcodeLen == 0 ) continue ; for ( i = 0 ; i < instLen ; i ++ ) { if ( ( unsigned char ) inBuff [ i ] != ( unsigned char ) instTable [ baseCounter ] . binOpcode [ i ] ) { badMatch = true ; break ; } if ( instTable [ baseCounter ] . binOpcodeLen > 1 ) { if ( inBuff [ i + 1 ] != ( unsigned char ) instTable [ baseCounter ] . binOpcode [ i + 1 ] ) { badMatch = true ; break ; } } if ( badMatch == true ) goto nextInst ; if ( X86_32_InstructionSizeVaries ( & instTable [ baseCounter ] ) > 0 ) { if ( partialDecode -> addrSizeOverride <= 0 || partialDecode -> operSizeOverride <= 0 ) { baseCounter ++ ; } } rm = inBuff [ instTable [ baseCounter ] . binOpcodeLen ] ; if ( instTable [ baseCounter ] . opcodeOperandCount != 0 ) for ( x = 0 ; x < instTable [ baseCounter ] . opcodeOperandCount ; x ++ ) { switch ( instTable [ baseCounter ] . opcodeOperand [ x ] ) { case OA_RM_ONLY_0 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 0 ) badMatch = true ; break ; case OA_RM_ONLY_1 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 1 ) badMatch = true ; break ; case OA_RM_ONLY_2 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 2 ) badMatch = true ; break ; case OA_RM_ONLY_3 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 3 ) badMatch = true ; break ; case OA_RM_ONLY_4 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 4 ) badMatch = true ; break ; case OA_RM_ONLY_5 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 5 ) badMatch = true ; break ; case OA_RM_ONLY_6 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 6 ) badMatch = true ; break ; case OA_RM_ONLY_7 : if ( X86_32_GetSlashDigitFromRm ( rm ) != 7 ) badMatch = true ; break ; default : break ; } } } if ( ( unsigned char ) inBuff [ 0 ] != ( unsigned char ) instTable [ baseCounter ] . binOpcode [ 0 ] ) { badMatch = true ; } if ( badMatch == false ) { goto end ; } } if ( badMatch == true ) { return NULL ; } end : if ( badMatch == false ) { return & instTable [ baseCounter ] ; } return NULL ; }
This function contains an optimized loop that decodes opcodes
of 1-3 bytes in length to their respective instruction.
This function contains an optimized loop that decodes opcodes of 1 - 3 bytes in length to their respective instruction .
// Must have a partial decode to continue // Local function flag used to determine if an opcode does not match // the current instruction being analyzed // generic unsigned pointer for opcode operations // advance the buffer past the total length of the prefixes // inBuff = &inBuff[partialDecode->prefixCount]; // character to hold a temporary rm value // check first to see if its +digit encoded // This effectively copies the in buffer to // be able to make modifications without modifying the // original buffer. // Set and copy over data // Swap out first byte // Swqp out pointers // NOTE: THIS WILL BE REPLACED IN THE FUTURE WITH A B+ TREE TO SPEED // IT UP A GOOD AMOUNT. // Loop through instruction table // set the local instruction length // reset the badmatch flag on loop so that we start with // a clean slate. // reloop if the opcode length is 0, as then it is a // prefix not an opcode. // Find the correct instruction // return to the top of the loop if we activated // a bad match above (aka move to next instruction comparison) // 16bit/32bit determination // set the rm byte if it determined that the opcode // contains an rm value. // Now we need to verify against operands to make sure that it syncs up // Test the operands one by one to see if they're a /digit.  if // they are, match up the rm byte to see if this is the correct // instruction, if not: break the loop. // digit /0 // digit /1 // digit /2 // digit /3 // digit /4 // digit /5 // digit /6 // digit /7 // now we have to verify operand sizes and types, this will depend // on previous prefix calculations. // Because of intels insanity, this double check must be here // to make sure we didn't logically skip to the wrong instruction based // on previous instruction assumptions. // if badmatch is false, we have a correct match // break the loop and return the instruction // double check our opcodes /*
			printf("\n Found Correct Instruction at Offs: %i ", baseCounter);
			printf("\n RM IS?: %u", X86_32_GetSlashDigitFromRm(rm));
			printf("\n First byte is?: %.02x", (unsigned char) instTable[baseCounter].binOpcode[0]);
*/ // if the flag is set to which a bad match is found, // return NULL as an error. // Exits with a legitimate opcode // printf("\n Returning: %i", instTable[baseCounter].binOpcodeLen); // shouldn't actually get here.. bad match should return null above // this is simply here to remove the warning message.