performance-aware-programming/8086_sim/sim86.cpp

109 lines
2.4 KiB
C++

#include "include/aliases.h"
#include "include/reg_access.h"
#include "include/sim86_lib.h"
#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
void decode_operand(instruction_operand operand);
void mov_to_register(const register_access &reg,
const instruction_operand &source);
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: sim86 BINARY_FILE\n");
return 1;
}
const char *filename = argv[1];
printf("Filename: %s\n", filename);
FILE *fp = fopen(filename, "rb");
if (!fp) {
printf("Failed to open file %s\n", filename);
}
fseek(fp, 0, SEEK_END);
u32 size = ftell(fp);
fseek(fp, 0, SEEK_SET);
u8 buffer[size + 1];
memset((void *)buffer, 0, size + 1);
fread((void *)buffer, sizeof(u8), size, fp);
fclose(fp);
instruction_table table;
Sim86_Get8086InstructionTable(&table);
u32 offset = 0;
bool accessed_registers[REGISTER_COUNT] = {false};
while (offset < size) {
instruction decoded;
Sim86_Decode8086Instruction(size - offset, buffer + offset, &decoded);
if (decoded.Op) {
offset += decoded.Size;
if (decoded.Op == Op_mov) {
instruction_operand dest = decoded.Operands[0];
instruction_operand source = decoded.Operands[1];
if (dest.Type == Operand_Register) {
mov_to_register(dest.Register, source);
accessed_registers[dest.Register.Index] = true;
}
}
}
}
for (u32 i = 0; i < REGISTER_COUNT; ++i) {
if (accessed_registers[i]) {
register_access reg = {i, 0, 2};
u16 value = get_register(reg);
printf("%s: 0x%04x (%d)\n", get_register_name(reg), value, value);
}
}
return 0;
}
void decode_operand(instruction_operand operand) {
switch (operand.Type) {
case Operand_Register:
printf("Register operand: %d, %d, %d\n", operand.Register.Index,
operand.Register.Offset, operand.Register.Count);
break;
case Operand_Memory:
// printf("Memory operand\n");
break;
case Operand_Immediate:
// printf("Immediate operand\n");
break;
default:
break;
}
}
void mov_to_register(const register_access &reg,
const instruction_operand &source) {
switch (source.Type) {
case Operand_Immediate:
set_register(reg, source.Immediate.Value);
break;
case Operand_Register:
set_register(reg, get_register(source.Register));
break;
default:
break;
}
}