📄 decode.c
字号:
/* 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 + -