| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-03-28 08:57:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | #include "x64Analyzer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned const char *startCodePtr = codePtr; | 
					
						
							|  |  |  | 	u8 rex = 0; | 
					
						
							|  |  |  | 	u8 codeByte = 0; | 
					
						
							|  |  |  | 	u8 codeByte2 = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//Check for regular prefix
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	info->operandSize = 4; | 
					
						
							|  |  |  | 	info->zeroExtend = false; | 
					
						
							|  |  |  | 	info->signExtend = false; | 
					
						
							|  |  |  | 	info->hasImmediate = false; | 
					
						
							|  |  |  | 	info->isMemoryWrite = false; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	u8 modRMbyte = 0; | 
					
						
							|  |  |  | 	u8 sibByte = 0; | 
					
						
							| 
									
										
										
										
											2013-04-15 16:28:55 -04:00
										 |  |  | 	bool hasModRM = false; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int displacementSize = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*codePtr == 0x66) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		info->operandSize = 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		codePtr++; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else if (*codePtr == 0x67) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		codePtr++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//Check for REX prefix
 | 
					
						
							|  |  |  | 	if ((*codePtr & 0xF0) == 0x40) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		rex = *codePtr; | 
					
						
							|  |  |  | 		if (rex & 8) //REX.W
 | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			info->operandSize = 8; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		codePtr++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	codeByte = *codePtr++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	// Skip two-byte opcode byte 
 | 
					
						
							|  |  |  | 	bool twoByte = false;  | 
					
						
							|  |  |  | 	if(codeByte == 0x0F)  | 
					
						
							| 
									
										
										
										
											2013-04-15 16:28:55 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		twoByte = true;  | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		codeByte2 = *codePtr++; | 
					
						
							| 
									
										
										
										
											2013-04-15 16:28:55 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!twoByte) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		if ((codeByte & 0xF0) == 0x80 ||  | 
					
						
							|  |  |  | 			((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02)) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			modRMbyte = *codePtr++; | 
					
						
							|  |  |  | 			hasModRM = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||  | 
					
						
							|  |  |  | 			(codeByte2 & 0xF0) == 0x30 ||  | 
					
						
							|  |  |  | 			codeByte2 == 0x77 ||  | 
					
						
							|  |  |  | 			(codeByte2 & 0xF0) == 0x80 ||  | 
					
						
							|  |  |  | 			((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||  | 
					
						
							|  |  |  | 			(codeByte2 & 0xF8) == 0xC8)  | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 			// No mod R/M byte 
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		else  | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			modRMbyte = *codePtr++; | 
					
						
							|  |  |  | 			hasModRM = true; | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		}  | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hasModRM) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ModRM mrm(modRMbyte, rex); | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		info->regOperandReg = mrm.reg; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		if (mrm.mod < 3) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (mrm.rm == 4) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				//SIB byte
 | 
					
						
							|  |  |  | 				sibByte = *codePtr++; | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 				info->scaledReg = (sibByte >> 3) & 7; | 
					
						
							|  |  |  | 				info->otherReg = (sibByte & 7); | 
					
						
							|  |  |  | 				if (rex & 2) info->scaledReg += 8; | 
					
						
							|  |  |  | 				if (rex & 1) info->otherReg += 8; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 				//info->scaledReg = 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (mrm.mod == 1 || mrm.mod == 2) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (mrm.mod == 1) | 
					
						
							|  |  |  | 				displacementSize = 1; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				displacementSize = 4; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (displacementSize == 1) | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		info->displacement = (s32)(s8)*codePtr; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		info->displacement = *((s32 *)codePtr); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	codePtr += displacementSize; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	switch (codeByte) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	// writes
 | 
					
						
							|  |  |  | 	case 0xC6: // mem <- imm8
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			info->isMemoryWrite = true; | 
					
						
							|  |  |  | 			info->hasImmediate = true; | 
					
						
							|  |  |  | 			info->immediate = *codePtr; | 
					
						
							|  |  |  | 			codePtr++; //move past immediate
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 0xC7: // mem <- imm16/32
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			info->isMemoryWrite = true; | 
					
						
							|  |  |  | 			if (info->operandSize == 2) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 				info->hasImmediate = true; | 
					
						
							|  |  |  | 				info->immediate = *(u16*)codePtr; | 
					
						
							|  |  |  | 				codePtr += 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			else if (info->operandSize == 4) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 				info->hasImmediate = true; | 
					
						
							|  |  |  | 				info->immediate = *(u32*)codePtr; | 
					
						
							|  |  |  | 				codePtr += 4; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			else if (info->operandSize == 8) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				info->zeroExtend = true; | 
					
						
							|  |  |  | 				info->immediate = *(u32*)codePtr; | 
					
						
							|  |  |  | 				codePtr += 4; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-24 22:47:01 -04:00
										 |  |  | 	case 0x88: // mem <- r8
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			info->isMemoryWrite = true; | 
					
						
							|  |  |  | 			if (info->operandSize == 4) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				info->operandSize = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	case 0x89: // mem <- r16/32/64
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			info->isMemoryWrite = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	case 0x0F: // two-byte escape
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			info->isMemoryWrite = false; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			switch (codeByte2) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			case 0xB6: // movzx on byte
 | 
					
						
							|  |  |  | 				info->zeroExtend = true; | 
					
						
							|  |  |  | 				info->operandSize = 1; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			case 0xB7: // movzx on short
 | 
					
						
							|  |  |  | 				info->zeroExtend = true; | 
					
						
							|  |  |  | 				info->operandSize = 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			case 0xBE: // movsx on byte
 | 
					
						
							|  |  |  | 				info->signExtend = true; | 
					
						
							|  |  |  | 				info->operandSize = 1; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			case 0xBF: // movsx on short
 | 
					
						
							|  |  |  | 				info->signExtend = true; | 
					
						
							|  |  |  | 				info->operandSize = 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 0x8A: // r8 <- mem
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			info->isMemoryWrite = false; | 
					
						
							|  |  |  | 			if (info->operandSize == 4) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 				info->operandSize = 1; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 				return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case 0x8B: // r16/32/64 <- mem
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			info->isMemoryWrite = false; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-09-02 16:37:04 -04:00
										 |  |  | 	info->instructionSize = (int)(codePtr - startCodePtr); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } |