85 lines
2.1 KiB
C++
85 lines
2.1 KiB
C++
#include "emulator.h"
|
|
|
|
void add_eb_gb() {
|
|
uint32_t addr = physical_addr(CS, IP);
|
|
uint8_t modrm_byte = ram[addr];
|
|
IP++;
|
|
|
|
ModRM modrm = parse_modrm(modrm_byte);
|
|
uint8_t gb_value = get_reg_byte(modrm.reg);
|
|
uint8_t eb_value;
|
|
uint32_t eb_addr;
|
|
bool eb_is_mem = false;
|
|
|
|
if (modrm.mod == 3) {
|
|
// eb is a reg
|
|
eb_value = get_reg_byte(modrm.rm);
|
|
} else {
|
|
// eb is an addr
|
|
uint32_t eff_addr = calc_effective_addr(modrm);
|
|
uint16_t segment = (modrm.rm == 2 || modrm.rm == 3 || modrm.rm == 6) ? SS : DS;
|
|
uint32_t phys_addr = physical_addr(segment, eff_addr);
|
|
eb_value = ram[phys_addr];
|
|
eb_is_mem = true;
|
|
}
|
|
|
|
uint8_t result = eb_value + gb_value;
|
|
|
|
if (eb_is_mem) {
|
|
ram[eb_addr] = result;
|
|
} else {
|
|
set_reg_byte(modrm.rm, result);
|
|
}
|
|
|
|
update_flags_add(eb_value, gb_value, result);
|
|
}
|
|
|
|
void add_ev_gv() {
|
|
uint32_t addr = physical_addr(CS, IP);
|
|
uint8_t modrm_byte = ram[addr];
|
|
IP ++;
|
|
|
|
ModRM modrm = parse_modrm(modrm_byte);
|
|
uint16_t gv_value = get_reg_word(modrm.reg);
|
|
uint16_t ev_value;
|
|
uint32_t ev_addr;
|
|
bool ev_is_mem = false;
|
|
|
|
if (modrm.mod == 3) {
|
|
ev_value = get_reg_word(modrm.rm);
|
|
} else {
|
|
uint16_t seg = (modrm.rm == 4 || modrm.rm == 5 || modrm.rm == 6) ? SS : DS;
|
|
uint16_t eff_addr = calc_effective_addr(modrm);
|
|
ev_addr = physical_addr(seg, eff_addr);
|
|
|
|
ev_value = ram[ev_addr] | (ram[ev_addr + 1] << 8);
|
|
ev_is_mem = true;
|
|
}
|
|
|
|
uint16_t result = ev_value + gv_value;
|
|
|
|
if (ev_is_mem) {
|
|
ram[ev_addr] = result & 0xFF;
|
|
ram[ev_addr + 1] = result >> 8;
|
|
} else {
|
|
set_reg_word(modrm.rm, result);
|
|
}
|
|
|
|
update_flags_add16(ev_value, gv_value, result);
|
|
std::cout << "AX = " << std::hex << AX.value
|
|
<< " (AL=" << (int)AX.low << ")\n";
|
|
}
|
|
|
|
void hlt() {
|
|
std::cout << "HLT\n";
|
|
exit(0);
|
|
}
|
|
|
|
using instrHandler = void(*)();
|
|
instrHandler instr_table[256] = { nullptr };
|
|
|
|
void init_instr_table() {
|
|
instr_table[0x00] = add_eb_gb;
|
|
instr_table[0x01] = add_ev_gv;
|
|
instr_table[0xf4] = hlt;
|
|
} |