⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 简单的虚拟机
💻 C
📖 第 1 页 / 共 4 页
字号:
/* this is really the most horrible I've ever seen. */#include <stdio.h>#include <string.h>#include "decode.h"#include "mp/arithmetic.h"#include "mp/move.h"#include "mp/pushpop.h"#include "mp/interrupt.h"#include "mp/logicalshift.h"bool decode(){	struct Operand operand1;	struct Operand operand2;	struct Operand opTmp;	word immediate;	int op;	unsigned char *currentCode,*Code;	char prefixFlag;	Code = currentCode = (unsigned char*)(cpu.ram+LADDR);	prefixFlag = 0;	struct INSTRUCTION Instruction;	/* initialize Instrction structure */	Instruction.RepeatPrefix = -1;	Instruction.SegmentPrefix = -1;	Instruction.OperandPrefix = -1;	Instruction.AddressPrefix = -1;	Instruction.Opcode = -1;	Instruction.ModRM = -1;	Instruction.SIB = -1;	Instruction.Displacement = -1;	Instruction.Immediate = -1;	Instruction.dFlag = Instruction.wFlag = Instruction.sFlag = -1;	Instruction.LinearAddress = LADDR;	/* check PREFIXES and save the values, note that prefixes in the same group can only appear once */	/* and the values assigned to xxxxPrefix in Instruction structure are the indexes of the names */	/* in corresponding name tables */	while(*currentCode == 0xF0 || *currentCode == 0xF2 || *currentCode == 0xF3 ||			*currentCode == 0x2E || *currentCode == 0x36 || *currentCode == 0x3E ||			*currentCode == 0x26 || *currentCode == 0x64 || *currentCode == 0x65 ||			*currentCode == 0x66 || *currentCode == 0x67)	{		switch(*currentCode)		{			/* group1: lock and repeat prefixes */			case 0xF0 :				if(prefixFlag)				{					/* prefix lock */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.RepeatPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.RepeatPrefix = 0;						currentCode++;						cpu.ip++;					}				}				break;			case 0xF2 :				if(prefixFlag)				{					/* prefix repnz */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.RepeatPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.RepeatPrefix = 5;						currentCode++;						cpu.ip++;					}				}				break;			case 0xF3 :				if(prefixFlag)				{					/* prefix rep */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.RepeatPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.RepeatPrefix = 1;						currentCode++;						cpu.ip++;					}				}				break;				/* group2: segment override prefixes */			case 0x2E :				if(prefixFlag)				{					/* prefix cs */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 1;						currentCode++;						cpu.ip++;					}				}				break;			case 0x36 :				if(prefixFlag)				{					/* prefix ss */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 2;						currentCode++;						cpu.ip++;					}				}				break;			case 0x3E :				if(prefixFlag)				{					/* prefix ds */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 3;						currentCode++;						cpu.ip++;					}				}				break;			case 0x26 :				if(prefixFlag)				{					/* prefix es */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 0;						currentCode++;						cpu.ip++;					}				}				break;			case 0x64 :				if(prefixFlag)				{					/* prefix fs */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 4;						currentCode++;						cpu.ip++;					}				}				break;			case 0x65 :				if(prefixFlag)				{					/* prefix gs */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.SegmentPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.SegmentPrefix = 5;						currentCode++;						cpu.ip++;					}				}				break;				/* group3: Operand-size override prefixes */			case 0x66 :				if(prefixFlag)				{					/* prefix datasize */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.OperandPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.OperandPrefix = 0;						currentCode++;						cpu.ip++;					}				}				break;				/* group4: Address-size override prefixes */			case 0x67 :				if(prefixFlag)				{					/* prefix addrsize */					currentCode++;					cpu.ip++;					return false;				}				else				{					/* rescan */					if(Instruction.AddressPrefix >= 0)					{						currentCode = Code;						prefixFlag = 1;					}					else					{						Instruction.AddressPrefix = 0;						currentCode++;						cpu.ip++;					}				}		}	}	int i;	/* CODE map */	switch(*currentCode)	{		/* Arithmetic operations */		case 0x04: case 0x05: case 0x0C: case 0x0D: /* add or */		case 0x14: case 0x15: case 0x1C: case 0x1D: /* adc sbb */		case 0x24: case 0x25: case 0x2C: case 0x2D: /* and sub */		case 0x34: case 0x35: case 0x3C: case 0x3D: /* xor cmp */			Instruction.Opcode = *currentCode;			Instruction.wFlag = (*currentCode & 1);			Instruction.sFlag = ! Instruction.wFlag;			operand1.RM=Instruction.wFlag?REG16:REG8;			operand1.value=Instruction.wFlag?(int)greg16_addr(0):(int)greg8_addr(0);			currentCode++;			cpu.ip++;			currentCode = ParseImmediate(currentCode, &Instruction, &immediate);			switch((Instruction.Opcode >> 3) & 0x1F)			{				case 0:handle_arith_rm_imm(add,operand1,immediate,Instruction.wFlag);break;				case 1:handle_arith_rm_imm(or,operand1,immediate,Instruction.wFlag);break;				case 2:handle_arith_rm_imm(adc,operand1,immediate,Instruction.wFlag);break;				case 3:handle_arith_rm_imm(sbb,operand1,immediate,Instruction.wFlag);break;				case 4:handle_arith_rm_imm(and,operand1,immediate,Instruction.wFlag);break;				case 5:handle_arith_rm_imm(sub,operand1,immediate,Instruction.wFlag);break;				case 6:handle_arith_rm_imm(xor,operand1,immediate,Instruction.wFlag);break;				case 7:handle_arith_rm_imm(cmp,operand1,immediate,Instruction.wFlag);break;			}			break;		case 0x00: case 0x01: case 0x02: case 0x03: /* add */		case 0x08: case 0x09: case 0x0A: case 0x0B: /* or */		case 0x10: case 0x11: case 0x12: case 0x13: /* adc */		case 0x18: case 0x19: case 0x1A: case 0x1B: /* sbb */		case 0x20: case 0x21: case 0x22: case 0x23: /* and */		case 0x28: case 0x29: case 0x2A: case 0x2B: /* sub */		case 0x30: case 0x31: case 0x32: case 0x33: /* xor */		case 0x38: case 0x39: case 0x3A: case 0x3B: /* cmp */			Instruction.Opcode = *currentCode;			Instruction.dFlag = (*currentCode >> 1) & 1;			Instruction.wFlag = (*currentCode) & 1;			currentCode++;			cpu.ip++;			currentCode = ParseRegModRM(currentCode, &Instruction, &operand1, &operand2);			switch((Instruction.Opcode >> 3) & 0x1F)			{					case 0:handle_arith_rm(add,operand1,operand2,Instruction.wFlag);break;				case 1:handle_arith_rm(or,operand1,operand2,Instruction.wFlag);break;				case 2:handle_arith_rm(adc,operand1,operand2,Instruction.wFlag);break;				case 3:handle_arith_rm(sbb,operand1,operand2,Instruction.wFlag);break;				case 4:handle_arith_rm(and,operand1,operand2,Instruction.wFlag);break;				case 5:handle_arith_rm(sub,operand1,operand2,Instruction.wFlag);break;				case 6:handle_arith_rm(xor,operand1,operand2,Instruction.wFlag);break;				case 7:handle_arith_rm(cmp,operand1,operand2,Instruction.wFlag);break;			}						break;		case 0x80: case 0x81: case 0x82: case 0x83:			Instruction.Opcode = *currentCode;			Instruction.wFlag = (*currentCode & 1);			Instruction.sFlag = (*currentCode >> 1) & 1;			/* special cases */			if(*currentCode == 0x80)			{				Instruction.sFlag = 1;			}			op=(*(currentCode + 1) >> 3) & 7;			currentCode++;			cpu.ip++;			currentCode = ParseModRM(currentCode, &Instruction, &operand1);			currentCode = ParseImmediate(currentCode, &Instruction, &immediate);			/* special cases */			if(Instruction.Opcode == 0x83)			{				/* add sign-extended */				immediate|=(((immediate>>7)&1)?(0xff<<8):0);			}			switch(op)			{				case 0:handle_arith_rm_imm(add,operand1,immediate,Instruction.wFlag);break;				case 1:handle_arith_rm_imm(or,operand1,immediate,Instruction.wFlag);break;				case 2:handle_arith_rm_imm(adc,operand1,immediate,Instruction.wFlag);break;				case 3:handle_arith_rm_imm(sbb,operand1,immediate,Instruction.wFlag);break;				case 4:handle_arith_rm_imm(and,operand1,immediate,Instruction.wFlag);break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -