Add some arithmetics to emulator
This commit is contained in:
parent
1ae3c7a0b9
commit
bedceb28a4
57
utils/emul.c
57
utils/emul.c
@ -10,8 +10,9 @@ union regset {
|
|||||||
uint16_t r16[8]; // AX, CX, DX, BX, SP, BP, SI, DI
|
uint16_t r16[8]; // AX, CX, DX, BX, SP, BP, SI, DI
|
||||||
} regset;
|
} regset;
|
||||||
|
|
||||||
|
int carry, zero;
|
||||||
|
|
||||||
uint16_t ip = 0x100;
|
uint16_t ip = 0x100;
|
||||||
uint16_t flags;
|
|
||||||
uint16_t scratch;
|
uint16_t scratch;
|
||||||
uint16_t reg;
|
uint16_t reg;
|
||||||
int off;
|
int off;
|
||||||
@ -23,7 +24,6 @@ void* rmptr;
|
|||||||
#define R8(x) regset.r8[fixr8ref(x)]
|
#define R8(x) regset.r8[fixr8ref(x)]
|
||||||
#define R16(x) regset.r16[x]
|
#define R16(x) regset.r16[x]
|
||||||
|
|
||||||
#define syscall_number regset.r8[4]
|
|
||||||
#define AL regset.r8[0]
|
#define AL regset.r8[0]
|
||||||
#define CL regset.r8[2]
|
#define CL regset.r8[2]
|
||||||
#define DL regset.r8[4]
|
#define DL regset.r8[4]
|
||||||
@ -34,6 +34,16 @@ void* rmptr;
|
|||||||
#define SI regset.r16[6]
|
#define SI regset.r16[6]
|
||||||
#define DI regset.r16[7]
|
#define DI regset.r16[7]
|
||||||
|
|
||||||
|
#define ADD 0
|
||||||
|
#define OR 1
|
||||||
|
#define ADC 2
|
||||||
|
#define SBB 3
|
||||||
|
#define AND 4
|
||||||
|
#define SUB 5
|
||||||
|
#define XOR 6
|
||||||
|
#define CMP 7
|
||||||
|
#define TEST 8
|
||||||
|
|
||||||
const char* const regnames[] = { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", 0 };
|
const char* const regnames[] = { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", 0 };
|
||||||
|
|
||||||
// Dump registers
|
// Dump registers
|
||||||
@ -47,6 +57,32 @@ void dump() {
|
|||||||
printf("IP=%04X : %X\n", ip, mem[ip]);
|
printf("IP=%04X : %X\n", ip, mem[ip]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arith16(int op, int16_t* dst, int src) {
|
||||||
|
// I'll just assume this sign-extends
|
||||||
|
int t = *dst;
|
||||||
|
int p = *dst;
|
||||||
|
switch (op) {
|
||||||
|
case ADD: t += src; break;
|
||||||
|
case OR: t |= src; break;
|
||||||
|
case ADC: t += (src + carry); break;
|
||||||
|
case SBB: t -= (src + carry); break;
|
||||||
|
case AND: t &= src; break;
|
||||||
|
case SUB: t -= src; break;
|
||||||
|
case XOR: t ^= src; break;
|
||||||
|
case CMP: t -= src; break;
|
||||||
|
case TEST: t &= src; break;
|
||||||
|
}
|
||||||
|
zero=!t;
|
||||||
|
// I dont think the following is correct
|
||||||
|
carry=((t ^ p) >> 16) & 1;
|
||||||
|
if (op==CMP || op==TEST) return;
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t get_flags() {
|
||||||
|
return (carry & 1) | ((zero & 1)<< 6);
|
||||||
|
}
|
||||||
|
|
||||||
int fixr8ref(int r) {
|
int fixr8ref(int r) {
|
||||||
return ((r << 1) & 0b110) | ((r >> 2) & 0b1);
|
return ((r << 1) & 0b110) | ((r >> 2) & 0b1);
|
||||||
}
|
}
|
||||||
@ -71,7 +107,7 @@ void modrm(int size) {
|
|||||||
uint8_t rm = (mem[ip]) & 0b111;
|
uint8_t rm = (mem[ip]) & 0b111;
|
||||||
ip++;
|
ip++;
|
||||||
if (mod == 3) {
|
if (mod == 3) {
|
||||||
if (size == BIT8) {
|
if (size == BIT16) {
|
||||||
rmptr = &R16(rm);
|
rmptr = &R16(rm);
|
||||||
} else {
|
} else {
|
||||||
rmptr = &R8(rm);
|
rmptr = &R8(rm);
|
||||||
@ -156,15 +192,25 @@ void step() {
|
|||||||
uint8_t opcode = mem[ip];
|
uint8_t opcode = mem[ip];
|
||||||
ip++;
|
ip++;
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
|
case 0x50 ... 0x57: // PUSH reg16
|
||||||
|
push(R16(opcode-0x50));
|
||||||
|
break;
|
||||||
|
case 0x58 ... 0x5F: // POP reg16
|
||||||
|
R16(opcode-0x58)=pop();
|
||||||
|
break;
|
||||||
case 0x70 ... 0x7F: // Jcc
|
case 0x70 ... 0x7F: // Jcc
|
||||||
reg = ip + (int8_t)imm8();
|
reg = ip + (int8_t)imm8();
|
||||||
if (cond(opcode-0x70)) {
|
if (cond(opcode-0x70)) {
|
||||||
ip = reg;
|
ip = reg;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x83: // ARITH r/m16,imm8
|
||||||
|
modrm(BIT16);
|
||||||
|
arith16(reg, &RM16, imm8());
|
||||||
|
break;
|
||||||
case 0x84: // TEST r/m8,reg8
|
case 0x84: // TEST r/m8,reg8
|
||||||
modrm(BIT8);
|
modrm(BIT8);
|
||||||
scratch = AL & RM8;
|
scratch = R8(reg) & RM8;
|
||||||
break;
|
break;
|
||||||
case 0x88: // MOV r/m8,reg8
|
case 0x88: // MOV r/m8,reg8
|
||||||
modrm(BIT8);
|
modrm(BIT8);
|
||||||
@ -174,6 +220,9 @@ void step() {
|
|||||||
modrm(BIT16);
|
modrm(BIT16);
|
||||||
R16(reg) = RM16;
|
R16(reg) = RM16;
|
||||||
break;
|
break;
|
||||||
|
case 0x9C: // PUSHF
|
||||||
|
push(get_flags());
|
||||||
|
break;
|
||||||
case 0xA1: // MOV AX,memoffs16
|
case 0xA1: // MOV AX,memoffs16
|
||||||
AX = *(uint16_t*)&mem[imm16()];
|
AX = *(uint16_t*)&mem[imm16()];
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user