это ужас
This commit is contained in:
117
emulator.h
Normal file
117
emulator.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
|
||||
#define MEMORY_SIZE 1048576
|
||||
|
||||
union reg16 {
|
||||
struct {
|
||||
uint8_t low;
|
||||
uint8_t high;
|
||||
};
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
struct ModRM {
|
||||
uint8_t mod; // addressing mode
|
||||
uint8_t reg; // source
|
||||
uint8_t rm; // dest
|
||||
};
|
||||
|
||||
reg16 AX, BX, CX, DX; // general regs
|
||||
uint16_t SI, DI; // source index, dest index
|
||||
uint16_t BP, SP; // base ptr, stack ptr
|
||||
uint16_t IP; // instruction ptr
|
||||
uint16_t CS, DS, ES, SS; // code segmets reg, data segment reg, extra segment reg, stack segment reg
|
||||
|
||||
bool CF; // carry
|
||||
bool PF; // parity
|
||||
bool AF; // auxiliary carry
|
||||
bool ZF; // zero
|
||||
bool SF; // sign
|
||||
bool TF; // trap
|
||||
bool IF; // interrupt
|
||||
bool DF; // direction
|
||||
bool OF; // overflow
|
||||
|
||||
uint8_t ram[MEMORY_SIZE];
|
||||
|
||||
uint32_t physical_addr(uint16_t seg, uint16_t offset);
|
||||
bool load_binary(char* filename, size_t addr);
|
||||
ModRM parse_modrm(uint8_t byte);
|
||||
|
||||
uint8_t get_reg_byte(uint8_t code);
|
||||
uint8_t set_reg_byte(uint8_t code, uint8_t value);
|
||||
|
||||
uint32_t physical_addr(uint16_t seg, uint16_t offset) {
|
||||
return ((uint32_t) seg << 4) + offset;
|
||||
}
|
||||
|
||||
bool load_binary(char* filename, size_t addr) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file) {
|
||||
std::cerr << "failed to open file " << filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
size_t file_size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
if (file_size > MEMORY_SIZE - addr) {
|
||||
std::cerr << "file is too big";
|
||||
return false;
|
||||
}
|
||||
|
||||
file.read(reinterpret_cast<char*>(ram + addr), file_size);
|
||||
|
||||
if (!file) {
|
||||
std::cerr << "failed to read entire file";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "file " << filename << " loaded to ram\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
ModRM parse_modrm(uint8_t byte) {
|
||||
ModRM modrm;
|
||||
modrm.mod = (byte >> 6) & 0x3;
|
||||
modrm.reg = (byte >> 3) & 0x7;
|
||||
modrm.rm = byte & 0x7;
|
||||
return modrm;
|
||||
}
|
||||
|
||||
uint8_t get_reg_byte(uint8_t code, uint8_t value) {
|
||||
switch (code)
|
||||
{
|
||||
case 0: AX.low = value; break;
|
||||
case 1: CX.low = value; break;
|
||||
case 2: DX.low = value; break;
|
||||
case 3: BX.low = value; break;
|
||||
case 4: AX.high = value; break;
|
||||
case 5: AX.high = value; break;
|
||||
case 6: AX.high = value; break;
|
||||
case 7: AX.high = value; break;
|
||||
default:
|
||||
std::cerr << "invalid reg code for 8-bit reg";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t set_reg_byte(uint8_t code) {
|
||||
switch (code)
|
||||
{
|
||||
case 0: return AX.low;
|
||||
case 1: return CX.low;
|
||||
case 2: return DX.low;
|
||||
case 3: return BX.low;
|
||||
case 4: return AX.high;
|
||||
case 5: return CX.high;
|
||||
case 6: return DX.high;
|
||||
case 7: return BX.high;
|
||||
default:
|
||||
std::cerr << "invalid reg code for 8-bit reg";
|
||||
return 0;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user