| 1 |
2 |
alfik |
#include <cstdio>
|
| 2 |
|
|
#include <cstdlib>
|
| 3 |
|
|
|
| 4 |
|
|
#include <sys/mman.h>
|
| 5 |
|
|
#include <sys/types.h>
|
| 6 |
|
|
#include <sys/stat.h>
|
| 7 |
|
|
#include <fcntl.h>
|
| 8 |
|
|
#include <unistd.h>
|
| 9 |
|
|
|
| 10 |
|
|
#include "bochs.h"
|
| 11 |
|
|
#include "cpu.h"
|
| 12 |
|
|
#include "iodev/iodev.h"
|
| 13 |
|
|
|
| 14 |
|
|
//------------------------------------------------------------------------------
|
| 15 |
|
|
//------------------------------------------------------------------------------
|
| 16 |
|
|
//------------------------------------------------------------------------------
|
| 17 |
|
|
|
| 18 |
|
|
typedef unsigned char uint8;
|
| 19 |
|
|
typedef unsigned short uint16;
|
| 20 |
|
|
typedef unsigned int uint32;
|
| 21 |
|
|
typedef unsigned long long uint64;
|
| 22 |
|
|
|
| 23 |
|
|
//------------------------------------------------------------------------------
|
| 24 |
|
|
//------------------------------------------------------------------------------
|
| 25 |
|
|
//------------------------------------------------------------------------------ logfunctions
|
| 26 |
|
|
|
| 27 |
|
|
void logfunctions::panic(const char *fmt, ...) {
|
| 28 |
|
|
printf("#bochs486_reader::logfunctions::panic(): ");
|
| 29 |
|
|
|
| 30 |
|
|
va_list ap;
|
| 31 |
|
|
va_start(ap, fmt);
|
| 32 |
|
|
vprintf(fmt, ap);
|
| 33 |
|
|
va_end(ap);
|
| 34 |
|
|
|
| 35 |
|
|
printf("\n");
|
| 36 |
|
|
fflush(stdout);
|
| 37 |
|
|
|
| 38 |
|
|
if(strstr(fmt, "exception with no resolution") != NULL) {
|
| 39 |
|
|
printf("start_shutdown: 0\n");
|
| 40 |
|
|
printf("\n");
|
| 41 |
|
|
fflush(stdout);
|
| 42 |
|
|
exit(0);
|
| 43 |
|
|
}
|
| 44 |
|
|
else {
|
| 45 |
|
|
exit(-1);
|
| 46 |
|
|
}
|
| 47 |
|
|
}
|
| 48 |
|
|
void logfunctions::error(const char *fmt, ...) {
|
| 49 |
|
|
printf("#bochs486_reader::logfunctions::error(): ");
|
| 50 |
|
|
|
| 51 |
|
|
va_list ap;
|
| 52 |
|
|
va_start(ap, fmt);
|
| 53 |
|
|
vprintf(fmt, ap);
|
| 54 |
|
|
va_end(ap);
|
| 55 |
|
|
|
| 56 |
|
|
printf("\n");
|
| 57 |
|
|
fflush(stdout);
|
| 58 |
|
|
}
|
| 59 |
|
|
void logfunctions::ldebug(const char *fmt, ...) {
|
| 60 |
|
|
printf("#bochs486_reader::logfunctions::debug(): ");
|
| 61 |
|
|
|
| 62 |
|
|
va_list ap;
|
| 63 |
|
|
va_start(ap, fmt);
|
| 64 |
|
|
vprintf(fmt, ap);
|
| 65 |
|
|
va_end(ap);
|
| 66 |
|
|
|
| 67 |
|
|
printf("\n");
|
| 68 |
|
|
fflush(stdout);
|
| 69 |
|
|
}
|
| 70 |
|
|
void logfunctions::info(const char *fmt, ...) {
|
| 71 |
|
|
printf("#bochs486_reader::logfunctions::info(): ");
|
| 72 |
|
|
|
| 73 |
|
|
va_list ap;
|
| 74 |
|
|
va_start(ap, fmt);
|
| 75 |
|
|
vprintf(fmt, ap);
|
| 76 |
|
|
va_end(ap);
|
| 77 |
|
|
|
| 78 |
|
|
printf("\n");
|
| 79 |
|
|
fflush(stdout);
|
| 80 |
|
|
}
|
| 81 |
|
|
void logfunctions::put(const char *n, const char *p) {
|
| 82 |
|
|
}
|
| 83 |
|
|
logfunctions::logfunctions() {
|
| 84 |
|
|
}
|
| 85 |
|
|
logfunctions::~logfunctions() {
|
| 86 |
|
|
}
|
| 87 |
|
|
|
| 88 |
|
|
static logfunctions theLog;
|
| 89 |
|
|
logfunctions *pluginlog = &theLog;
|
| 90 |
|
|
logfunctions *siminterface_log = &theLog;
|
| 91 |
|
|
|
| 92 |
|
|
//------------------------------------------------------------------------------
|
| 93 |
|
|
//------------------------------------------------------------------------------
|
| 94 |
|
|
//------------------------------------------------------------------------------ menu
|
| 95 |
|
|
|
| 96 |
|
|
void bx_param_string_c::text_print(FILE *fp) {
|
| 97 |
|
|
printf("#bochs486_reader::bx_param_string_c::text_print()\n");
|
| 98 |
|
|
}
|
| 99 |
|
|
void bx_param_enum_c::text_print(FILE *fp) {
|
| 100 |
|
|
printf("#bochs486_reader::bx_param_enum_c::text_print()\n");
|
| 101 |
|
|
}
|
| 102 |
|
|
void bx_param_bool_c::text_print(FILE *fp) {
|
| 103 |
|
|
printf("#bochs486_reader::bx_param_bool_c::text_print()\n");
|
| 104 |
|
|
}
|
| 105 |
|
|
void bx_param_num_c::text_print(FILE *fp) {
|
| 106 |
|
|
printf("#bochs486_reader::bx_param_num_c::text_print()\n");
|
| 107 |
|
|
}
|
| 108 |
|
|
void bx_list_c::text_print(FILE *fp) {
|
| 109 |
|
|
printf("#bochs486_reader::bx_list_c::text_print()\n");
|
| 110 |
|
|
}
|
| 111 |
|
|
int bx_param_enum_c::text_ask(FILE *fpin, FILE *fpout) {
|
| 112 |
|
|
printf("#bochs486_reader::bx_param_enum_c::text_ask()\n");
|
| 113 |
|
|
return 0;
|
| 114 |
|
|
}
|
| 115 |
|
|
int bx_param_bool_c::text_ask(FILE *fpin, FILE *fpout) {
|
| 116 |
|
|
printf("#bochs486_reader::bx_param_bool_c::text_ask()\n");
|
| 117 |
|
|
return 0;
|
| 118 |
|
|
}
|
| 119 |
|
|
int bx_param_num_c::text_ask(FILE *fpin, FILE *fpout) {
|
| 120 |
|
|
printf("#bochs486_reader::bx_param_num_c::text_ask()\n");
|
| 121 |
|
|
return 0;
|
| 122 |
|
|
}
|
| 123 |
|
|
int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout) {
|
| 124 |
|
|
printf("#bochs486_reader::bx_param_string_c::text_ask()\n");
|
| 125 |
|
|
return 0;
|
| 126 |
|
|
}
|
| 127 |
|
|
int bx_list_c::text_ask(FILE *fpin, FILE *fpout) {
|
| 128 |
|
|
printf("#bochs486_reader::bx_list_c::text_ask()\n");
|
| 129 |
|
|
return 0;
|
| 130 |
|
|
}
|
| 131 |
|
|
|
| 132 |
|
|
bx_list_c *root_param = NULL;
|
| 133 |
|
|
|
| 134 |
|
|
bx_gui_c *bx_gui = NULL;
|
| 135 |
|
|
|
| 136 |
|
|
//------------------------------------------------------------------------------
|
| 137 |
|
|
//------------------------------------------------------------------------------
|
| 138 |
|
|
//------------------------------------------------------------------------------ cpu
|
| 139 |
|
|
|
| 140 |
|
|
void BX_CPU_C::enter_system_management_mode(void) {
|
| 141 |
|
|
printf("#bochs486_reader: enter_system_management_mod()\n");
|
| 142 |
|
|
}
|
| 143 |
|
|
void BX_CPU_C::init_SMRAM(void) {
|
| 144 |
|
|
printf("#bochs486_reader: init_SMRAM()\n");
|
| 145 |
|
|
}
|
| 146 |
|
|
void BX_CPU_C::debug(bx_address offset) {
|
| 147 |
|
|
printf("#bochs486_reader: debug(offset=%08x)\n", offset);
|
| 148 |
|
|
}
|
| 149 |
|
|
void BX_CPU_C::debug_disasm_instruction(bx_address offset) {
|
| 150 |
|
|
printf("#bochs486_reader: debug_disasm_instruction(offset=%08x)\n", offset);
|
| 151 |
|
|
}
|
| 152 |
|
|
|
| 153 |
|
|
//------------------------------------------------------------------------------
|
| 154 |
|
|
//------------------------------------------------------------------------------
|
| 155 |
|
|
//------------------------------------------------------------------------------ pc_system
|
| 156 |
|
|
|
| 157 |
|
|
void bx_pc_system_c::countdownEvent(void) {
|
| 158 |
|
|
}
|
| 159 |
|
|
bx_pc_system_c::bx_pc_system_c() {
|
| 160 |
|
|
}
|
| 161 |
|
|
int bx_pc_system_c::Reset(unsigned type) {
|
| 162 |
|
|
printf("#bochs486_reader: bx_pc_system_c::Reset(%d) unimplemented.\n", type);
|
| 163 |
|
|
std::exit(-1);
|
| 164 |
|
|
}
|
| 165 |
|
|
|
| 166 |
|
|
bx_pc_system_c bx_pc_system;
|
| 167 |
|
|
|
| 168 |
|
|
const char* cpu_mode_string(unsigned cpu_mode) {
|
| 169 |
|
|
static const char *cpu_mode_name[] = {
|
| 170 |
|
|
"real mode",
|
| 171 |
|
|
"v8086 mode",
|
| 172 |
|
|
"protected mode",
|
| 173 |
|
|
"compatibility mode",
|
| 174 |
|
|
"long mode",
|
| 175 |
|
|
"unknown mode"
|
| 176 |
|
|
};
|
| 177 |
|
|
|
| 178 |
|
|
if(cpu_mode >= 5) cpu_mode = 5;
|
| 179 |
|
|
return cpu_mode_name[cpu_mode];
|
| 180 |
|
|
}
|
| 181 |
|
|
|
| 182 |
|
|
const char *choices[] = { "0_choice", NULL };
|
| 183 |
|
|
|
| 184 |
|
|
class bochs486_sim : public bx_simulator_interface_c {
|
| 185 |
|
|
|
| 186 |
|
|
bx_param_bool_c *get_param_bool(const char *pname, bx_param_c *base) {
|
| 187 |
|
|
if(strcmp(pname, BXPN_CPUID_LIMIT_WINNT) == 0) return new bx_param_bool_c( NULL, "b0", "", "", 0);
|
| 188 |
|
|
if(strcmp(pname, BXPN_CPUID_SSE4A) == 0) return new bx_param_bool_c( NULL, "b1", "", "", 0);
|
| 189 |
|
|
if(strcmp(pname, BXPN_CPUID_SEP) == 0) return new bx_param_bool_c( NULL, "b2", "", "", 0);
|
| 190 |
|
|
if(strcmp(pname, BXPN_CPUID_XSAVE) == 0) return new bx_param_bool_c( NULL, "b3", "", "", 0);
|
| 191 |
|
|
if(strcmp(pname, BXPN_CPUID_XSAVEOPT) == 0) return new bx_param_bool_c( NULL, "b4", "", "", 0);
|
| 192 |
|
|
if(strcmp(pname, BXPN_CPUID_AES) == 0) return new bx_param_bool_c( NULL, "b5", "", "", 0);
|
| 193 |
|
|
if(strcmp(pname, BXPN_CPUID_MOVBE) == 0) return new bx_param_bool_c( NULL, "b6", "", "", 0);
|
| 194 |
|
|
if(strcmp(pname, BXPN_CPUID_SMEP) == 0) return new bx_param_bool_c( NULL, "b7", "", "", 0);
|
| 195 |
|
|
if(strcmp(pname, BXPN_RESET_ON_TRIPLE_FAULT) == 0) return new bx_param_bool_c( NULL, "b8", "", "", 0);
|
| 196 |
|
|
return NULL;
|
| 197 |
|
|
}
|
| 198 |
|
|
bx_param_string_c *get_param_string(const char *pname, bx_param_c *base) {
|
| 199 |
|
|
if(strcmp(pname, BXPN_VENDOR_STRING) == 0) return new bx_param_string_c(NULL, "s0", "", "", "GeniuneAO486");
|
| 200 |
|
|
if(strcmp(pname, BXPN_BRAND_STRING) == 0) return new bx_param_string_c(NULL, "s1", "", "", "ao486 ");
|
| 201 |
|
|
return NULL;
|
| 202 |
|
|
}
|
| 203 |
|
|
bx_param_enum_c *get_param_enum(const char *pname, bx_param_c *base) {
|
| 204 |
|
|
if(strcmp(pname, BXPN_CPU_MODEL) == 0) return new bx_param_enum_c( NULL, "e0", "", "", choices, 0);
|
| 205 |
|
|
if(strcmp(pname, BXPN_CPUID_SSE) == 0) return new bx_param_enum_c( NULL, "e1", "", "", choices, 0);
|
| 206 |
|
|
return NULL;
|
| 207 |
|
|
}
|
| 208 |
|
|
bx_param_num_c *get_param_num(const char *pname, bx_param_c *base) {
|
| 209 |
|
|
if(strcmp(pname, BXPN_CPUID_STEPPING) == 0) return new bx_param_num_c( NULL, "n0", "", "", 0xB,0xB,0xB);
|
| 210 |
|
|
if(strcmp(pname, BXPN_CPUID_MODEL) == 0) return new bx_param_num_c( NULL, "n1", "", "", 0x5,0x5,0x5);
|
| 211 |
|
|
if(strcmp(pname, BXPN_CPUID_FAMILY) == 0) return new bx_param_num_c( NULL, "n2", "", "", 0x4,0x4,0x4);
|
| 212 |
|
|
if(strcmp(pname, BXPN_CPUID_LEVEL) == 0) return new bx_param_num_c( NULL, "n3", "", "", 0x4,0x4,0x4);
|
| 213 |
|
|
return NULL;
|
| 214 |
|
|
}
|
| 215 |
|
|
};
|
| 216 |
|
|
|
| 217 |
|
|
//------------------------------------------------------------------------------
|
| 218 |
|
|
|
| 219 |
|
|
FILE *check_fp = NULL;
|
| 220 |
|
|
|
| 221 |
|
|
char check_line[256];
|
| 222 |
|
|
char check_next[256];
|
| 223 |
|
|
int check_state = 0;
|
| 224 |
|
|
/*
|
| 225 |
|
|
|
| 226 |
|
|
1 - EOF is next
|
| 227 |
|
|
2 - both full; line will be used
|
| 228 |
|
|
*/
|
| 229 |
|
|
|
| 230 |
|
|
uint32 check_next_irq_at = 0;
|
| 231 |
|
|
uint32 check_next_irq_vector = 0;
|
| 232 |
|
|
|
| 233 |
|
|
union memory_t {
|
| 234 |
|
|
uint8 bytes [134217728];
|
| 235 |
|
|
uint16 shorts[67108864];
|
| 236 |
|
|
uint32 ints [33554432];
|
| 237 |
|
|
};
|
| 238 |
|
|
memory_t check_memory;
|
| 239 |
|
|
|
| 240 |
|
|
uint32 instr_counter = 0;
|
| 241 |
|
|
|
| 242 |
|
|
void load_file(const char *name, int byte_location) {
|
| 243 |
|
|
FILE *fp = fopen(name, "rb");
|
| 244 |
|
|
if(fp == NULL) {
|
| 245 |
|
|
fprintf(stderr, "#bochs486_reader: error opening file: %s\n", name);
|
| 246 |
|
|
exit(-1);
|
| 247 |
|
|
}
|
| 248 |
|
|
|
| 249 |
|
|
int int_ret = fseek(fp, 0, SEEK_END);
|
| 250 |
|
|
if(int_ret != 0) {
|
| 251 |
|
|
fclose(fp);
|
| 252 |
|
|
fprintf(stderr, "#bochs486_reader: error stat file: %s\n", name);
|
| 253 |
|
|
exit(-1);
|
| 254 |
|
|
}
|
| 255 |
|
|
|
| 256 |
|
|
long size = ftell(fp);
|
| 257 |
|
|
rewind(fp);
|
| 258 |
|
|
|
| 259 |
|
|
int_ret = fread((void *)&check_memory.bytes[byte_location], size, 1, fp);
|
| 260 |
|
|
if(int_ret != 1) {
|
| 261 |
|
|
fclose(fp);
|
| 262 |
|
|
fprintf(stderr, "#bochs486_reader: error loading file: %s\n", name);
|
| 263 |
|
|
exit(-1);
|
| 264 |
|
|
}
|
| 265 |
|
|
fclose(fp);
|
| 266 |
|
|
}
|
| 267 |
|
|
|
| 268 |
|
|
bool check_read_fp(char *line) {
|
| 269 |
|
|
while(true) {
|
| 270 |
|
|
char *endoffile = fgets(line, 256, check_fp);
|
| 271 |
|
|
if(endoffile == NULL) return false;
|
| 272 |
|
|
printf("line: %s\n", line);
|
| 273 |
|
|
uint32 val1 = 0, val2 = 0;
|
| 274 |
|
|
int scan_ret = sscanf(line, "Exception 0x%x at %x", &val1, &val2);
|
| 275 |
|
|
if(scan_ret == 2) {
|
| 276 |
|
|
//ignore
|
| 277 |
|
|
continue;
|
| 278 |
|
|
}
|
| 279 |
|
|
|
| 280 |
|
|
val1 = val2 = 0;
|
| 281 |
|
|
scan_ret = sscanf(line, "IAC 0x%x at %d", &val1, &val2);
|
| 282 |
|
|
if(scan_ret == 2) {
|
| 283 |
|
|
check_next_irq_vector = val1;
|
| 284 |
|
|
check_next_irq_at = val2;
|
| 285 |
|
|
|
| 286 |
|
|
continue;
|
| 287 |
|
|
}
|
| 288 |
|
|
break;
|
| 289 |
|
|
}
|
| 290 |
|
|
return true;
|
| 291 |
|
|
}
|
| 292 |
|
|
|
| 293 |
|
|
uint64 total_size = 0;
|
| 294 |
|
|
uint64 last_percent = 0;
|
| 295 |
|
|
|
| 296 |
|
|
void check_init() {
|
| 297 |
|
|
if(check_fp == NULL) {
|
| 298 |
|
|
//const char *filename = "./../backup/run-10/track.txt";
|
| 299 |
|
|
const char *filename = "./../ao486/io_win95pipeline_1_bochs.txt";
|
| 300 |
|
|
|
| 301 |
|
|
check_fp = fopen(filename, "rb");
|
| 302 |
|
|
if(check_fp == NULL) {
|
| 303 |
|
|
fprintf(stderr, "#bochs486_reader: can not open reader file.\n");
|
| 304 |
|
|
exit(-1);
|
| 305 |
|
|
}
|
| 306 |
|
|
|
| 307 |
|
|
struct stat st;
|
| 308 |
|
|
memset(&st, 0, sizeof(struct stat));
|
| 309 |
|
|
stat(filename, &st);
|
| 310 |
|
|
total_size = st.st_size;
|
| 311 |
|
|
fprintf(stderr, "#bochs486_reader: total file size: %d\n", total_size);
|
| 312 |
|
|
}
|
| 313 |
|
|
|
| 314 |
|
|
uint64 curr_pos = ftell(check_fp);
|
| 315 |
|
|
uint64 curr_percent = curr_pos * 100 / total_size;
|
| 316 |
|
|
if(curr_percent != last_percent) {
|
| 317 |
|
|
last_percent = curr_percent;
|
| 318 |
|
|
fprintf(stderr, "#bochs486_reader: %d percent\n", (uint32)last_percent);
|
| 319 |
|
|
}
|
| 320 |
|
|
|
| 321 |
|
|
if(check_state == 0) {
|
| 322 |
|
|
if(check_read_fp(check_line) == false) {
|
| 323 |
|
|
fprintf(stderr, "#bochs486_reader: EOF\n");
|
| 324 |
|
|
exit(0);
|
| 325 |
|
|
}
|
| 326 |
|
|
if(check_read_fp(check_next) == false) {
|
| 327 |
|
|
check_state = 1;
|
| 328 |
|
|
return;
|
| 329 |
|
|
}
|
| 330 |
|
|
check_state = 2;
|
| 331 |
|
|
}
|
| 332 |
|
|
else if(check_state == 1) {
|
| 333 |
|
|
fprintf(stderr, "#bochs486_reader: EOF\n");
|
| 334 |
|
|
exit(0);
|
| 335 |
|
|
}
|
| 336 |
|
|
else if(check_state == 2) {
|
| 337 |
|
|
memcpy(check_line, check_next, 256);
|
| 338 |
|
|
|
| 339 |
|
|
if(check_read_fp(check_next) == false) {
|
| 340 |
|
|
check_state = 1;
|
| 341 |
|
|
return;
|
| 342 |
|
|
}
|
| 343 |
|
|
check_state = 2;
|
| 344 |
|
|
}
|
| 345 |
|
|
}
|
| 346 |
|
|
|
| 347 |
|
|
uint32 check_io_rd(uint32 address, uint32 byteenable) {
|
| 348 |
|
|
check_init();
|
| 349 |
|
|
|
| 350 |
|
|
uint32 io_addr = 0, io_byteena = 0, io_data = 0;
|
| 351 |
|
|
int scan_ret = sscanf(check_line, "io rd %x %x %x", &io_addr, &io_byteena, &io_data);
|
| 352 |
|
|
|
| 353 |
|
|
if(scan_ret == 3) {
|
| 354 |
|
|
if(address != io_addr) {
|
| 355 |
|
|
fprintf(stderr, "#check_io_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
|
| 356 |
|
|
exit(-1);
|
| 357 |
|
|
}
|
| 358 |
|
|
if(byteenable != io_byteena) {
|
| 359 |
|
|
fprintf(stderr, "#check_io_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
|
| 360 |
|
|
exit(-1);
|
| 361 |
|
|
}
|
| 362 |
|
|
}
|
| 363 |
|
|
else {
|
| 364 |
|
|
fprintf(stderr, "#check_io_rd MISMATCH: f:%s != l:%04x %x\n", check_line, address, byteenable);
|
| 365 |
|
|
exit(-1);
|
| 366 |
|
|
}
|
| 367 |
|
|
return io_data;
|
| 368 |
|
|
}
|
| 369 |
|
|
|
| 370 |
|
|
void check_io_wr(uint32 address, uint32 byteenable, uint32 data) {
|
| 371 |
|
|
check_init();
|
| 372 |
|
|
|
| 373 |
|
|
uint32 io_addr = 0, io_byteena = 0, io_data = 0;
|
| 374 |
|
|
int scan_ret = sscanf(check_line, "io wr %x %x %x", &io_addr, &io_byteena, &io_data);
|
| 375 |
|
|
|
| 376 |
|
|
if(scan_ret == 3) {
|
| 377 |
|
|
if(((byteenable>>0) & 1) == 0) { data &= 0xFFFFFF00; io_data &= 0xFFFFFF00; }
|
| 378 |
|
|
if(((byteenable>>1) & 1) == 0) { data &= 0xFFFF00FF; io_data &= 0xFFFF00FF; }
|
| 379 |
|
|
if(((byteenable>>2) & 1) == 0) { data &= 0xFF00FFFF; io_data &= 0xFF00FFFF; }
|
| 380 |
|
|
if(((byteenable>>3) & 1) == 0) { data &= 0x00FFFFFF; io_data &= 0x00FFFFFF; }
|
| 381 |
|
|
|
| 382 |
|
|
if(address != io_addr) {
|
| 383 |
|
|
fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
|
| 384 |
|
|
exit(-1);
|
| 385 |
|
|
}
|
| 386 |
|
|
if(byteenable != io_byteena) {
|
| 387 |
|
|
fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
|
| 388 |
|
|
exit(-1);
|
| 389 |
|
|
}
|
| 390 |
|
|
if(data != io_data) {
|
| 391 |
|
|
fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
|
| 392 |
|
|
exit(-1);
|
| 393 |
|
|
}
|
| 394 |
|
|
}
|
| 395 |
|
|
else {
|
| 396 |
|
|
fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
|
| 397 |
|
|
exit(-1);
|
| 398 |
|
|
}
|
| 399 |
|
|
}
|
| 400 |
|
|
|
| 401 |
|
|
void check_mem_wr(uint32 address, uint32 byteenable, uint32 data) {
|
| 402 |
|
|
check_init();
|
| 403 |
|
|
|
| 404 |
|
|
uint32 mem_addr = 0, mem_byteena = 0, mem_data = 0;
|
| 405 |
|
|
int scan_ret = sscanf(check_line, "mem wr %x %x %x", &mem_addr, &mem_byteena, &mem_data);
|
| 406 |
|
|
|
| 407 |
|
|
if(scan_ret == 3) {
|
| 408 |
|
|
if(((byteenable>>0) & 1) == 0) { data &= 0xFFFFFF00; mem_data &= 0xFFFFFF00; }
|
| 409 |
|
|
if(((byteenable>>1) & 1) == 0) { data &= 0xFFFF00FF; mem_data &= 0xFFFF00FF; }
|
| 410 |
|
|
if(((byteenable>>2) & 1) == 0) { data &= 0xFF00FFFF; mem_data &= 0xFF00FFFF; }
|
| 411 |
|
|
if(((byteenable>>3) & 1) == 0) { data &= 0x00FFFFFF; mem_data &= 0x00FFFFFF; }
|
| 412 |
|
|
|
| 413 |
|
|
if(address != mem_addr) {
|
| 414 |
|
|
fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
|
| 415 |
|
|
exit(-1);
|
| 416 |
|
|
}
|
| 417 |
|
|
if(byteenable != mem_byteena) {
|
| 418 |
|
|
fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
|
| 419 |
|
|
exit(-1);
|
| 420 |
|
|
}
|
| 421 |
|
|
if(data != mem_data) {
|
| 422 |
|
|
fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
|
| 423 |
|
|
exit(-1);
|
| 424 |
|
|
}
|
| 425 |
|
|
|
| 426 |
|
|
for(uint32 i=0; i<4; i++) {
|
| 427 |
|
|
if(byteenable & 1) {
|
| 428 |
|
|
check_memory.bytes[address + i] = data & 0xFF;
|
| 429 |
|
|
}
|
| 430 |
|
|
byteenable >>= 1;
|
| 431 |
|
|
data >>= 8;
|
| 432 |
|
|
}
|
| 433 |
|
|
}
|
| 434 |
|
|
else {
|
| 435 |
|
|
fprintf(stderr, "#check_io_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
|
| 436 |
|
|
exit(-1);
|
| 437 |
|
|
}
|
| 438 |
|
|
}
|
| 439 |
|
|
|
| 440 |
|
|
uint32 check_mem_rd(uint32 address, uint32 byteenable) {
|
| 441 |
|
|
check_init();
|
| 442 |
|
|
|
| 443 |
|
|
uint32 mem_addr = 0, mem_byteena = 0, mem_data = 0;
|
| 444 |
|
|
int scan_ret = sscanf(check_line, "mem rd %x %x %x", &mem_addr, &mem_byteena, &mem_data);
|
| 445 |
|
|
|
| 446 |
|
|
if(scan_ret == 3) {
|
| 447 |
|
|
if(address != mem_addr) {
|
| 448 |
|
|
fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%08x %x\n", check_line, address, byteenable);
|
| 449 |
|
|
exit(-1);
|
| 450 |
|
|
}
|
| 451 |
|
|
if(byteenable != mem_byteena) {
|
| 452 |
|
|
fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%08x %x\n", check_line, address, byteenable);
|
| 453 |
|
|
exit(-1);
|
| 454 |
|
|
}
|
| 455 |
|
|
}
|
| 456 |
|
|
else {
|
| 457 |
|
|
fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
|
| 458 |
|
|
exit(-1);
|
| 459 |
|
|
}
|
| 460 |
|
|
return mem_data;
|
| 461 |
|
|
}
|
| 462 |
|
|
|
| 463 |
|
|
//------------------------------------------------------------------------------
|
| 464 |
|
|
|
| 465 |
|
|
bx_simulator_interface_c *SIM;
|
| 466 |
|
|
|
| 467 |
|
|
BOCHSAPI BX_CPU_C bx_cpu;
|
| 468 |
|
|
int interrupt_vector;
|
| 469 |
|
|
|
| 470 |
|
|
//------------------------------------------------------------------------------
|
| 471 |
|
|
//------------------------------------------------------------------------------
|
| 472 |
|
|
//------------------------------------------------------------------------------ devices
|
| 473 |
|
|
|
| 474 |
|
|
class bochs486_pic : public bx_pic_stub_c {
|
| 475 |
|
|
Bit8u IAC(void) { bx_cpu.clear_INTR(); return interrupt_vector & 0xFF; }
|
| 476 |
|
|
};
|
| 477 |
|
|
|
| 478 |
|
|
int is_io_ignored(Bit16u address, Bit32u byteena) {
|
| 479 |
|
|
|
| 480 |
|
|
bool read_ff =
|
| 481 |
|
|
(address >= 0x0010 && address < 0x0020) ||
|
| 482 |
|
|
(address == 0x0020 && (byteena & 0x3) == 0) ||
|
| 483 |
|
|
(address >= 0x0024 && address < 0x0040) ||
|
| 484 |
|
|
(address >= 0x0044 && address < 0x0060) ||
|
| 485 |
|
|
(address >= 0x0068 && address < 0x0070) ||
|
| 486 |
|
|
(address == 0x0070 && (byteena & 0x3) == 0) ||
|
| 487 |
|
|
(address >= 0x0074 && address < 0x0080) ||
|
| 488 |
|
|
(address == 0x00A0 && (byteena & 0x3) == 0) ||
|
| 489 |
|
|
(address >= 0x00A4 && address < 0x00C0) ||
|
| 490 |
|
|
(address >= 0x00E0 && address < 0x01F0) ||
|
| 491 |
|
|
(address >= 0x01F8 && address < 0x0220) ||
|
| 492 |
|
|
(address >= 0x0230 && address < 0x0388) ||
|
| 493 |
|
|
(address == 0x0388 && (byteena & 0x3) == 0) ||
|
| 494 |
|
|
(address >= 0x038C && address < 0x03B0) ||
|
| 495 |
|
|
(address >= 0x03E0 && address < 0x03F0) ||
|
| 496 |
|
|
(address >= 0x03F8 && address < 0x8888) ||
|
| 497 |
|
|
(address >= 0x8890);
|
| 498 |
|
|
|
| 499 |
|
|
bool read_ff_part =
|
| 500 |
|
|
(address == 0x0020) ||
|
| 501 |
|
|
(address == 0x0070) ||
|
| 502 |
|
|
(address == 0x00A0) ||
|
| 503 |
|
|
(address == 0x0388);
|
| 504 |
|
|
|
| 505 |
|
|
if(read_ff) return 1;
|
| 506 |
|
|
if(read_ff_part) return 2;
|
| 507 |
|
|
return 0;
|
| 508 |
|
|
}
|
| 509 |
|
|
|
| 510 |
|
|
Bit32u BX_CPP_AttrRegparmN(2)
|
| 511 |
|
|
bx_devices_c::inp(Bit16u addr, unsigned io_len) {
|
| 512 |
|
|
//printf("#bochs486_pc:inp(%04x, %d)\n", addr, io_len);
|
| 513 |
|
|
// read aligned to 4 bytes, with byteena
|
| 514 |
|
|
|
| 515 |
|
|
bool two_reads = (addr & 0x3) + io_len > 4;
|
| 516 |
|
|
|
| 517 |
|
|
Bit16u addr1 = addr & 0xFFFC;
|
| 518 |
|
|
unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
|
| 519 |
|
|
byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
|
| 520 |
|
|
|
| 521 |
|
|
Bit16u addr2 = (addr + 4) & 0xFFFC;
|
| 522 |
|
|
unsigned byteena2 = (byteena1 >> 4) & 0xF;
|
| 523 |
|
|
|
| 524 |
|
|
//-------------------------------------------------------------------------- first read
|
| 525 |
|
|
int int_ret = is_io_ignored(addr1, byteena1 & 0xF);
|
| 526 |
|
|
unsigned int data1 = 0xFFFFFFFF;
|
| 527 |
|
|
|
| 528 |
|
|
if(int_ret == 0 || int_ret == 2) {
|
| 529 |
|
|
data1 = ((int_ret == 2)? 0xFFFF0000 : 0x00000000) | check_io_rd(addr1, byteena1 & 0xF);
|
| 530 |
|
|
}
|
| 531 |
|
|
//-------------------------------------------------------------------------- second read
|
| 532 |
|
|
unsigned long long data = data1;
|
| 533 |
|
|
//printf("#bochs486_pc:inp() read_one %d\n", two_reads);
|
| 534 |
|
|
if(two_reads) {
|
| 535 |
|
|
int_ret = is_io_ignored(addr2, byteena2 & 0xF);
|
| 536 |
|
|
unsigned int data2 = 0xFFFFFFFF;
|
| 537 |
|
|
|
| 538 |
|
|
if(int_ret == 0 || int_ret == 2) {
|
| 539 |
|
|
data2 = ((int_ret == 2)? 0xFFFF0000 : 0x00000000) | check_io_rd(addr2, byteena2 & 0xF);
|
| 540 |
|
|
}
|
| 541 |
|
|
data = ((unsigned long long)data2 << 32) | data1;
|
| 542 |
|
|
}
|
| 543 |
|
|
|
| 544 |
|
|
while((byteena1 & 1) == 0) {
|
| 545 |
|
|
byteena1 >>= 1;
|
| 546 |
|
|
data >>= 8;
|
| 547 |
|
|
}
|
| 548 |
|
|
Bit32u ret_val = (io_len == 1)? (data & 0xFFL) : (io_len == 2)? (data & 0xFFFFL) : (io_len == 3)? (data & 0xFFFFFFL) : (data & 0xFFFFFFFFL);
|
| 549 |
|
|
printf("#bochs486_pc:inp(%04x, %d, =%08x)\n", addr, io_len, ret_val);
|
| 550 |
|
|
return ret_val;
|
| 551 |
|
|
}
|
| 552 |
|
|
|
| 553 |
|
|
void BX_CPP_AttrRegparmN(3)
|
| 554 |
|
|
bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) {
|
| 555 |
|
|
printf("#bochs486_pc:outp(%04x, %d, %08x)\n", addr, io_len, value);
|
| 556 |
|
|
// write aligned to 4 bytes, with byteena
|
| 557 |
|
|
|
| 558 |
|
|
bool two_writes = (addr & 0x3) + io_len > 4;
|
| 559 |
|
|
|
| 560 |
|
|
Bit16u addr1 = addr & 0xFFFC;
|
| 561 |
|
|
unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
|
| 562 |
|
|
byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
|
| 563 |
|
|
|
| 564 |
|
|
Bit16u addr2 = (addr + 4) & 0xFFFC;
|
| 565 |
|
|
unsigned byteena2 = (byteena1 >> 4) & 0xF;
|
| 566 |
|
|
|
| 567 |
|
|
if(io_len == 1) value &= 0x000000FF;
|
| 568 |
|
|
if(io_len == 2) value &= 0x0000FFFF;
|
| 569 |
|
|
if(io_len == 3) value &= 0x00FFFFFF;
|
| 570 |
|
|
|
| 571 |
|
|
Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
|
| 572 |
|
|
Bit32u value1 = value_full;
|
| 573 |
|
|
Bit32u value2 = (value_full >> 32);
|
| 574 |
|
|
|
| 575 |
|
|
//-------------------------------------------------------------------------- first write
|
| 576 |
|
|
int int_ret = is_io_ignored(addr1, byteena1 & 0xF);
|
| 577 |
|
|
|
| 578 |
|
|
if(int_ret == 0 || int_ret == 2) {
|
| 579 |
|
|
check_io_wr(addr1, byteena1 & 0xF, value1);
|
| 580 |
|
|
}
|
| 581 |
|
|
//printf("#bochs486_pc:outp() write_one %d\n", two_writes);
|
| 582 |
|
|
//-------------------------------------------------------------------------- second write
|
| 583 |
|
|
|
| 584 |
|
|
if(two_writes) {
|
| 585 |
|
|
int_ret = is_io_ignored(addr2, byteena2 & 0xF);
|
| 586 |
|
|
|
| 587 |
|
|
if(int_ret == 0 || int_ret == 2) {
|
| 588 |
|
|
check_io_wr(addr2, byteena2 & 0xF, value2);
|
| 589 |
|
|
}
|
| 590 |
|
|
}
|
| 591 |
|
|
//printf("#bochs486_pc:outp() write_two\n");
|
| 592 |
|
|
}
|
| 593 |
|
|
|
| 594 |
|
|
bx_devices_c::bx_devices_c() {
|
| 595 |
|
|
pluginPicDevice = new bochs486_pic();
|
| 596 |
|
|
}
|
| 597 |
|
|
|
| 598 |
|
|
bx_devices_c::~bx_devices_c() {
|
| 599 |
|
|
}
|
| 600 |
|
|
|
| 601 |
|
|
bx_devices_c bx_devices;
|
| 602 |
|
|
|
| 603 |
|
|
//------------------------------------------------------------------------------
|
| 604 |
|
|
//------------------------------------------------------------------------------
|
| 605 |
|
|
//------------------------------------------------------------------------------ memory
|
| 606 |
|
|
|
| 607 |
|
|
void BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
|
| 608 |
|
|
printf("#bochs486_reader: writePhysicalPage: addr=%08x, len=%d ", addr, len);
|
| 609 |
|
|
for(unsigned i=0; i<len; i++) printf("%02x ", ((uint8 *)data)[i]); printf("\n");
|
| 610 |
|
|
|
| 611 |
|
|
addr &= 0x07FFFFFF;
|
| 612 |
|
|
|
| 613 |
|
|
if(len > 4) {
|
| 614 |
|
|
printf("#bochs486_pc: writePhysicalPage() with len = %d\n", len);
|
| 615 |
|
|
exit(-1);
|
| 616 |
|
|
}
|
| 617 |
|
|
|
| 618 |
|
|
bool two_writes = (addr & 0x3) + len > 4;
|
| 619 |
|
|
|
| 620 |
|
|
Bit32u addr1 = addr & 0xFFFFFFFC;
|
| 621 |
|
|
unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
|
| 622 |
|
|
byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
|
| 623 |
|
|
|
| 624 |
|
|
Bit32u addr2 = (addr + 4) & 0xFFFFFFFC;
|
| 625 |
|
|
unsigned byteena2 = (byteena1 >> 4) & 0xF;
|
| 626 |
|
|
|
| 627 |
|
|
Bit32u value = ((unsigned int *)data)[0];
|
| 628 |
|
|
if(len == 1) value &= 0x000000FF;
|
| 629 |
|
|
if(len == 2) value &= 0x0000FFFF;
|
| 630 |
|
|
if(len == 3) value &= 0x00FFFFFF;
|
| 631 |
|
|
|
| 632 |
|
|
Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
|
| 633 |
|
|
Bit32u value1 = value_full;
|
| 634 |
|
|
Bit32u value2 = (value_full >> 32);
|
| 635 |
|
|
|
| 636 |
|
|
//-------------------------------------------------------------------------- first write
|
| 637 |
|
|
check_mem_wr(addr1, byteena1 & 0xF, value1);
|
| 638 |
|
|
|
| 639 |
|
|
//printf("#bochs486_pc: writePhysicalPage: write_one, %d\n", two_writes);
|
| 640 |
|
|
if(two_writes) {
|
| 641 |
|
|
//---------------------------------------------------------------------- second write
|
| 642 |
|
|
check_mem_wr(addr2, byteena2 & 0xF, value2);
|
| 643 |
|
|
}
|
| 644 |
|
|
//printf("#bochs486_pc: writePhysicalPage: write_two\n");
|
| 645 |
|
|
}
|
| 646 |
|
|
|
| 647 |
|
|
void BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
|
| 648 |
|
|
printf("#bochs486_pc: readPhysicalPage: addr=%08x, len=%d\n", addr, len);
|
| 649 |
|
|
|
| 650 |
|
|
if(addr >= 0xFFFFF000) addr &= 0x000FFFFF;
|
| 651 |
|
|
addr &= 0x07FFFFFF;
|
| 652 |
|
|
|
| 653 |
|
|
if(len == 4096) {
|
| 654 |
|
|
if((addr & 3) != 0) {
|
| 655 |
|
|
printf("#bochs486_pc: readPhysicalPage() with len = 4096 and addr not aligned to 4.\n");
|
| 656 |
|
|
exit(-1);
|
| 657 |
|
|
}
|
| 658 |
|
|
|
| 659 |
|
|
if(addr >= 0xA0000 && addr <= 0xBFFFF) {
|
| 660 |
|
|
printf("#bochs486_pc: readPhysicalPage() with len = 4096 and addr in vga buffer.\n");
|
| 661 |
|
|
fflush(stdout);
|
| 662 |
|
|
exit(-1);
|
| 663 |
|
|
}
|
| 664 |
|
|
|
| 665 |
|
|
memcpy((unsigned char *)data, (void *)(check_memory.bytes + addr), len);
|
| 666 |
|
|
return;
|
| 667 |
|
|
}
|
| 668 |
|
|
|
| 669 |
|
|
//check if read crosses line boundry (16 bytes)
|
| 670 |
|
|
if( ((addr) & 0xFFFFFFF0) != ((addr + len - 1) & 0xFFFFFFF0) ) {
|
| 671 |
|
|
unsigned char *ptr = (unsigned char*)data;
|
| 672 |
|
|
readPhysicalPage(cpu, addr, (addr | 0xF) - addr + 1, ptr);
|
| 673 |
|
|
readPhysicalPage(cpu, (addr | 0xF) + 1, len - (addr | 0xF) + addr - 1, ptr + ((addr | 0xF) - addr + 1));
|
| 674 |
|
|
return;
|
| 675 |
|
|
}
|
| 676 |
|
|
|
| 677 |
|
|
if(addr < 0xA0000 || addr > 0xBFFFF) {
|
| 678 |
|
|
memcpy((unsigned char *)data, (void *)(check_memory.bytes + addr), len);
|
| 679 |
|
|
uint32 *val = (uint32 *)data;
|
| 680 |
|
|
printf("read: %08x %08x\n", val[0], (len > 4)? val[1] : 0);
|
| 681 |
|
|
return;
|
| 682 |
|
|
}
|
| 683 |
|
|
//printf("#bochs486_pc: readPhysicalPage: vga read.\n");
|
| 684 |
|
|
bool two_reads = ((addr & 0x3) + len > 4) && ((addr & 0x3) + len <= 8);
|
| 685 |
|
|
bool three_reads = ((addr & 0x3) + len > 8);
|
| 686 |
|
|
|
| 687 |
|
|
Bit32u addr1 = addr & 0xFFFFFFFC;
|
| 688 |
|
|
unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
|
| 689 |
|
|
byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
|
| 690 |
|
|
|
| 691 |
|
|
Bit32u addr2 = (addr + 4) & 0xFFFFFFFC;
|
| 692 |
|
|
Bit32u addr3 = (addr + 8) & 0xFFFFFFFC;
|
| 693 |
|
|
|
| 694 |
|
|
if(two_reads || three_reads) byteena1 = 0xF;
|
| 695 |
|
|
byteena1 &= 0xF;
|
| 696 |
|
|
|
| 697 |
|
|
//-------------------------------------------------------------------------- first read
|
| 698 |
|
|
unsigned int data_read[3] = { 0,0,0 };
|
| 699 |
|
|
|
| 700 |
|
|
data_read[0] = check_mem_rd(addr1, byteena1 & 0xF);
|
| 701 |
|
|
|
| 702 |
|
|
if(two_reads || three_reads) {
|
| 703 |
|
|
//---------------------------------------------------------------------- second read
|
| 704 |
|
|
data_read[1] = check_mem_rd(addr2, 0xF);
|
| 705 |
|
|
|
| 706 |
|
|
if(three_reads) {
|
| 707 |
|
|
//------------------------------------------------------------------ third read
|
| 708 |
|
|
data_read[2] = check_mem_rd(addr3, 0xF);
|
| 709 |
|
|
}
|
| 710 |
|
|
}
|
| 711 |
|
|
|
| 712 |
|
|
unsigned char *ptr = (unsigned char *)data_read;
|
| 713 |
|
|
|
| 714 |
|
|
for(int i=0; i<(addr & 0x3); i++) ptr++;
|
| 715 |
|
|
|
| 716 |
|
|
memcpy((unsigned char *)data, ptr, len);
|
| 717 |
|
|
}
|
| 718 |
|
|
|
| 719 |
|
|
Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw) {
|
| 720 |
|
|
//printf("#bochs486_pc: getHostMemAddr: addr=%08x, rw=%d\n", addr, rw);
|
| 721 |
|
|
|
| 722 |
|
|
if(addr >= 0xA0000 && addr < 0xC0000) return NULL;
|
| 723 |
|
|
if(rw != BX_EXECUTE) return NULL;
|
| 724 |
|
|
|
| 725 |
|
|
if(addr >= 0xFFFFF000) addr &= 0x000FFFFF;
|
| 726 |
|
|
addr &= 0x07FFFFFF;
|
| 727 |
|
|
|
| 728 |
|
|
return (Bit8u *)(check_memory.bytes + addr);
|
| 729 |
|
|
}
|
| 730 |
|
|
BX_MEM_C::BX_MEM_C() {
|
| 731 |
|
|
}
|
| 732 |
|
|
BX_MEM_C::~BX_MEM_C() {
|
| 733 |
|
|
}
|
| 734 |
|
|
|
| 735 |
|
|
BOCHSAPI BX_MEM_C bx_mem;
|
| 736 |
|
|
|
| 737 |
|
|
//------------------------------------------------------------------------------
|
| 738 |
|
|
//------------------------------------------------------------------------------
|
| 739 |
|
|
//------------------------------------------------------------------------------ interrupt
|
| 740 |
|
|
|
| 741 |
|
|
void print_segment(bx_segment_reg_t *seg, const char *prefix) {
|
| 742 |
|
|
|
| 743 |
|
|
printf("%s: %04x ", prefix, seg->selector.value);
|
| 744 |
|
|
printf("val: %01x ", seg->cache.valid & 1);
|
| 745 |
|
|
printf("rpl: %01hhx ", seg->selector.rpl);
|
| 746 |
|
|
printf("base: %08x ", seg->cache.u.segment.base);
|
| 747 |
|
|
printf("limit: %08x ", (seg->cache.u.segment.g)? seg->cache.u.segment.limit_scaled >> 12 : seg->cache.u.segment.limit_scaled);
|
| 748 |
|
|
printf("g: %01x ", seg->cache.u.segment.g);
|
| 749 |
|
|
printf("d_b: %01x ", seg->cache.u.segment.d_b);
|
| 750 |
|
|
printf("avl: %01x ", seg->cache.u.segment.avl);
|
| 751 |
|
|
printf("p: %01x ", seg->cache.p);
|
| 752 |
|
|
printf("dpl: %01x ", seg->cache.dpl);
|
| 753 |
|
|
printf("s: %01x ", seg->cache.segment);
|
| 754 |
|
|
printf("type: %01x\n", seg->cache.type);
|
| 755 |
|
|
}
|
| 756 |
|
|
|
| 757 |
|
|
void output_cpu_state() {
|
| 758 |
|
|
printf("eax: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EAX));
|
| 759 |
|
|
printf("ebx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EBX));
|
| 760 |
|
|
printf("ecx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_ECX));
|
| 761 |
|
|
printf("edx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EDX));
|
| 762 |
|
|
printf("esi: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_ESI));
|
| 763 |
|
|
printf("edi: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EDI));
|
| 764 |
|
|
printf("ebp: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EBP));
|
| 765 |
|
|
printf("esp: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_ESP));
|
| 766 |
|
|
|
| 767 |
|
|
printf("eip: %08x\n", bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
| 768 |
|
|
|
| 769 |
|
|
printf("cflag: %01x ", bx_cpu.getB_CF());
|
| 770 |
|
|
printf("pflag: %01x ", bx_cpu.getB_PF());
|
| 771 |
|
|
printf("aflag: %01x ", bx_cpu.getB_AF());
|
| 772 |
|
|
printf("zflag: %01x ", bx_cpu.getB_ZF());
|
| 773 |
|
|
printf("sflag: %01x ", bx_cpu.getB_SF());
|
| 774 |
|
|
printf("tflag: %01x ", bx_cpu.getB_TF()&1);
|
| 775 |
|
|
printf("iflag: %01x ", bx_cpu.getB_IF()&1);
|
| 776 |
|
|
printf("dflag: %01x ", bx_cpu.getB_DF()&1);
|
| 777 |
|
|
printf("oflag: %01x ", bx_cpu.getB_OF()&1);
|
| 778 |
|
|
printf("iopl: %01x ", bx_cpu.get_IOPL()&3);
|
| 779 |
|
|
printf("ntflag: %01x ", bx_cpu.getB_NT()&1);
|
| 780 |
|
|
printf("rflag: %01x ", bx_cpu.getB_RF()&1);
|
| 781 |
|
|
printf("vmflag: %01x ", bx_cpu.getB_VM()&1);
|
| 782 |
|
|
printf("acflag: %01x ", bx_cpu.getB_AC()&1);
|
| 783 |
|
|
printf("idflag: %01x\n", bx_cpu.getB_ID()&1);
|
| 784 |
|
|
|
| 785 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_CS]), "cs");
|
| 786 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_DS]), "ds");
|
| 787 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_ES]), "es");
|
| 788 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_FS]), "fs");
|
| 789 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_GS]), "gs");
|
| 790 |
|
|
print_segment(&(bx_cpu.sregs[BX_SEG_REG_SS]), "ss");
|
| 791 |
|
|
print_segment(&(bx_cpu.ldtr), "ldtr");
|
| 792 |
|
|
print_segment(&(bx_cpu.tr), "tr");
|
| 793 |
|
|
|
| 794 |
|
|
printf("gdtr_base: %08x ", bx_cpu.gdtr.base);
|
| 795 |
|
|
printf("gdtr_limit: %02x\n", bx_cpu.gdtr.limit & 0xFFFF);
|
| 796 |
|
|
|
| 797 |
|
|
printf("idtr_base: %08x ", bx_cpu.idtr.base);
|
| 798 |
|
|
printf("idtr_limit: %02x\n", bx_cpu.idtr.limit & 0xFFFF);
|
| 799 |
|
|
|
| 800 |
|
|
printf("cr0_pe: %01x ", bx_cpu.cr0.get_PE() & 1);
|
| 801 |
|
|
printf("cr0_mp: %01x ", bx_cpu.cr0.get_MP() & 1);
|
| 802 |
|
|
printf("cr0_em: %01x ", bx_cpu.cr0.get_EM() & 1);
|
| 803 |
|
|
printf("cr0_ts: %01x ", bx_cpu.cr0.get_TS() & 1);
|
| 804 |
|
|
printf("cr0_ne: %01x ", bx_cpu.cr0.get_NE() & 1);
|
| 805 |
|
|
printf("cr0_wp: %01x ", bx_cpu.cr0.get_WP() & 1);
|
| 806 |
|
|
printf("cr0_am: %01x ", bx_cpu.cr0.get_AM() & 1);
|
| 807 |
|
|
printf("cr0_nw: %01x ", bx_cpu.cr0.get_NW() & 1);
|
| 808 |
|
|
printf("cr0_cd: %01x ", bx_cpu.cr0.get_CD() & 1);
|
| 809 |
|
|
printf("cr0_pg: %01x\n", bx_cpu.cr0.get_PG() & 1);
|
| 810 |
|
|
|
| 811 |
|
|
printf("cr2: %08x ", bx_cpu.cr2);
|
| 812 |
|
|
printf("cr3: %08x\n", bx_cpu.cr3);
|
| 813 |
|
|
|
| 814 |
|
|
printf("dr0: %08x ", bx_cpu.dr[0]);
|
| 815 |
|
|
printf("dr1: %08x ", bx_cpu.dr[1]);
|
| 816 |
|
|
printf("dr2: %08x ", bx_cpu.dr[2]);
|
| 817 |
|
|
printf("dr3: %08x ", bx_cpu.dr[3]);
|
| 818 |
|
|
|
| 819 |
|
|
printf("dr6: %08x ", bx_cpu.dr6.val32);
|
| 820 |
|
|
printf("dr7: %08x\n", bx_cpu.dr7.val32);
|
| 821 |
|
|
|
| 822 |
|
|
fflush(stdout);
|
| 823 |
|
|
}
|
| 824 |
|
|
|
| 825 |
|
|
uint32 seg_word_1(bx_segment_reg_t *seg) {
|
| 826 |
|
|
return (seg->cache.u.segment.base & 0xFF000000) |
|
| 827 |
|
|
(seg->cache.u.segment.g? 0x00800000 : 0x00) |
|
| 828 |
|
|
(seg->cache.u.segment.d_b? 0x00400000 : 0x00) |
|
| 829 |
|
|
(seg->cache.u.segment.avl? 0x00100000 : 0x00) |
|
| 830 |
|
|
(((seg->cache.u.segment.limit_scaled >> (seg->cache.u.segment.g? 12 : 0)) << 16) & 0xF) |
|
| 831 |
|
|
(seg->cache.p? 0x00008000 : 0x0) |
|
| 832 |
|
|
((seg->cache.dpl & 0x3) << 13) |
|
| 833 |
|
|
((seg->cache.segment & 0x1) << 12) |
|
| 834 |
|
|
((seg->cache.type & 0xF) << 8) |
|
| 835 |
|
|
((seg->cache.u.segment.base >> 16) & 0xFF);
|
| 836 |
|
|
}
|
| 837 |
|
|
|
| 838 |
|
|
uint32 seg_word_2(bx_segment_reg_t *seg) {
|
| 839 |
|
|
return ((seg->cache.u.segment.base & 0xFFFF) << 16) |
|
| 840 |
|
|
((seg->cache.u.segment.limit_scaled >> (seg->cache.u.segment.g? 12 : 0)) & 0xFFFF);
|
| 841 |
|
|
}
|
| 842 |
|
|
|
| 843 |
|
|
//------------------------------------------------------------------------------
|
| 844 |
|
|
//------------------------------------------------------------------------------
|
| 845 |
|
|
//------------------------------------------------------------------------------ instrument
|
| 846 |
|
|
|
| 847 |
|
|
bool bochs486_skip_rep_finish = false;
|
| 848 |
|
|
|
| 849 |
|
|
|
| 850 |
|
|
void bx_instr_init_env(void) { }
|
| 851 |
|
|
void bx_instr_exit_env(void) { }
|
| 852 |
|
|
|
| 853 |
|
|
void bx_instr_debug_promt() { }
|
| 854 |
|
|
void bx_instr_debug_cmd(const char *cmd) { }
|
| 855 |
|
|
|
| 856 |
|
|
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip) { }
|
| 857 |
|
|
void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip) { }
|
| 858 |
|
|
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip) { }
|
| 859 |
|
|
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) { }
|
| 860 |
|
|
|
| 861 |
|
|
void bx_instr_opcode(unsigned cpu, bxInstruction_c *i, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) { }
|
| 862 |
|
|
|
| 863 |
|
|
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) { }
|
| 864 |
|
|
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) { }
|
| 865 |
|
|
|
| 866 |
|
|
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3) { }
|
| 867 |
|
|
void bx_instr_cache_cntrl(unsigned cpu, unsigned what) { }
|
| 868 |
|
|
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset) { }
|
| 869 |
|
|
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr) { }
|
| 870 |
|
|
|
| 871 |
|
|
void bx_instr_initialize(unsigned cpu) { }
|
| 872 |
|
|
void bx_instr_exit(unsigned cpu) { }
|
| 873 |
|
|
void bx_instr_reset(unsigned cpu, unsigned type) { }
|
| 874 |
|
|
|
| 875 |
|
|
void bx_instr_inp(Bit16u addr, unsigned len) { }
|
| 876 |
|
|
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val) { }
|
| 877 |
|
|
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val) { }
|
| 878 |
|
|
|
| 879 |
|
|
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw) { }
|
| 880 |
|
|
void bx_instr_phy_access(unsigned cpu, bx_address phy, unsigned len, unsigned rw) { }
|
| 881 |
|
|
|
| 882 |
|
|
void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value) { }
|
| 883 |
|
|
|
| 884 |
|
|
|
| 885 |
|
|
//uint32 check_next_irq_at = 0;
|
| 886 |
|
|
//uint32 check_next_irq_vector = 0;
|
| 887 |
|
|
|
| 888 |
|
|
bool intr_pending = false;
|
| 889 |
|
|
bool double_exception = false;
|
| 890 |
|
|
|
| 891 |
|
|
void bx_instr_interrupt(unsigned cpu, unsigned vector, unsigned type, bx_bool push_error, Bit16u error_code) {
|
| 892 |
|
|
|
| 893 |
|
|
bochs486_skip_rep_finish = false;
|
| 894 |
|
|
if(type == BX_EXTERNAL_INTERRUPT) intr_pending = false;
|
| 895 |
|
|
|
| 896 |
|
|
if(type == BX_HARDWARE_EXCEPTION || type == BX_EXTERNAL_INTERRUPT) {
|
| 897 |
|
|
printf("bx_instr_interrupt(%d): %02x at %d\n", type, vector, instr_counter);
|
| 898 |
|
|
if(double_exception == false) instr_counter++;
|
| 899 |
|
|
else {
|
| 900 |
|
|
fprintf(stderr, "double exception: type: %d\n", type);
|
| 901 |
|
|
}
|
| 902 |
|
|
double_exception = true;
|
| 903 |
|
|
|
| 904 |
|
|
if(instr_counter == check_next_irq_at) {
|
| 905 |
|
|
interrupt_vector = check_next_irq_vector;
|
| 906 |
|
|
printf("raise_INTR(): %02x at %d\n", interrupt_vector, instr_counter);
|
| 907 |
|
|
bx_cpu.raise_INTR();
|
| 908 |
|
|
intr_pending = true;
|
| 909 |
|
|
}
|
| 910 |
|
|
else if(intr_pending && check_next_irq_at == 0) {
|
| 911 |
|
|
printf("clear_INTR() at %d\n", instr_counter);
|
| 912 |
|
|
bx_cpu.clear_INTR();
|
| 913 |
|
|
intr_pending = false;
|
| 914 |
|
|
}
|
| 915 |
|
|
}
|
| 916 |
|
|
}
|
| 917 |
|
|
|
| 918 |
|
|
void instr_after_execution() {
|
| 919 |
|
|
|
| 920 |
|
|
instr_counter++;
|
| 921 |
|
|
|
| 922 |
|
|
bx_cpu.TLB_flush();
|
| 923 |
|
|
|
| 924 |
|
|
if(instr_counter > 0) {
|
| 925 |
|
|
output_cpu_state();
|
| 926 |
|
|
}
|
| 927 |
|
|
//if(instr_counter > 11491275) exit(0);
|
| 928 |
|
|
|
| 929 |
|
|
if(instr_counter == check_next_irq_at) {
|
| 930 |
|
|
interrupt_vector = check_next_irq_vector;
|
| 931 |
|
|
printf("raise_INTR(): %02x at %d\n", interrupt_vector, instr_counter);
|
| 932 |
|
|
bx_cpu.raise_INTR();
|
| 933 |
|
|
intr_pending = true;
|
| 934 |
|
|
}
|
| 935 |
|
|
else if(intr_pending && check_next_irq_at == 0) {
|
| 936 |
|
|
printf("clear_INTR() at %d\n", instr_counter);
|
| 937 |
|
|
bx_cpu.clear_INTR();
|
| 938 |
|
|
intr_pending = false;
|
| 939 |
|
|
}
|
| 940 |
|
|
|
| 941 |
|
|
}
|
| 942 |
|
|
|
| 943 |
|
|
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) {
|
| 944 |
|
|
double_exception = false;
|
| 945 |
|
|
//printf("cs: %04x eip: %08x len: %d op: %02x\n", bx_cpu.sregs[BX_SEG_REG_CS].selector.value, bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx, i->ilen(), i->bochs486_opcode);
|
| 946 |
|
|
|
| 947 |
|
|
}
|
| 948 |
|
|
|
| 949 |
|
|
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i) {
|
| 950 |
|
|
//printf("AFT cs: %04x eip: %08x len: %d op: %02x\n", bx_cpu.sregs[BX_SEG_REG_CS].selector.value, bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx, i->ilen(), i->bochs486_opcode);
|
| 951 |
|
|
|
| 952 |
|
|
if(bochs486_skip_rep_finish) {
|
| 953 |
|
|
printf("#bx_instr_after_execution: bochs486_skip_rep_finished at %d\n", instr_counter);
|
| 954 |
|
|
bochs486_skip_rep_finish = false;
|
| 955 |
|
|
return;
|
| 956 |
|
|
}
|
| 957 |
|
|
|
| 958 |
|
|
printf("#instr: %02x %d\n", i->bochs486_opcode, instr_counter);
|
| 959 |
|
|
instr_after_execution();
|
| 960 |
|
|
}
|
| 961 |
|
|
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i) {
|
| 962 |
|
|
bochs486_skip_rep_finish = true;
|
| 963 |
|
|
|
| 964 |
|
|
printf("#repeat: %d\n", instr_counter);
|
| 965 |
|
|
instr_after_execution();
|
| 966 |
|
|
}
|
| 967 |
|
|
void bx_instr_hlt(unsigned cpu) {
|
| 968 |
|
|
instr_after_execution();
|
| 969 |
|
|
}
|
| 970 |
|
|
|
| 971 |
|
|
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags) { }
|
| 972 |
|
|
|
| 973 |
|
|
// memory trace callbacks from CPU, len=1,2,4 or 8
|
| 974 |
|
|
void bx_dbg_lin_memory_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned pl, unsigned rw, Bit8u *data) {
|
| 975 |
|
|
}
|
| 976 |
|
|
void bx_dbg_phy_memory_access(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw, unsigned attr, Bit8u *data) {
|
| 977 |
|
|
}
|
| 978 |
|
|
|
| 979 |
|
|
//------------------------------------------------------------------------------
|
| 980 |
|
|
//------------------------------------------------------------------------------
|
| 981 |
|
|
//------------------------------------------------------------------------------ main
|
| 982 |
|
|
|
| 983 |
|
|
int main(int argc, char **argv) {
|
| 984 |
|
|
|
| 985 |
|
|
load_file("./../sd/bios/bochs_legacy", 0xF0000);
|
| 986 |
|
|
load_file("./../sd/vgabios/vgabios_lgpl", 0xC0000);
|
| 987 |
|
|
|
| 988 |
|
|
bx_pc_system.a20_mask = 0xFFFFFFFF;
|
| 989 |
|
|
|
| 990 |
|
|
SIM = new bochs486_sim();
|
| 991 |
|
|
|
| 992 |
|
|
bx_cpu.initialize();
|
| 993 |
|
|
bx_cpu.reset(BX_RESET_HARDWARE);
|
| 994 |
|
|
|
| 995 |
|
|
printf("START\n");
|
| 996 |
|
|
bx_cpu.gen_reg[BX_32BIT_REG_EDX].dword.erx = 0x0000045b; //after reset EDX value
|
| 997 |
|
|
instr_counter++; //ao486 has extra instruction at 0xFFFFFFF0
|
| 998 |
|
|
|
| 999 |
|
|
bx_cpu.async_event = 0;
|
| 1000 |
|
|
bx_cpu.handleCpuModeChange();
|
| 1001 |
|
|
|
| 1002 |
|
|
bx_cpu.cpu_loop();
|
| 1003 |
|
|
|
| 1004 |
|
|
printf("#bochs486_pc: finishing.\n");
|
| 1005 |
|
|
|
| 1006 |
|
|
return 0;
|
| 1007 |
|
|
}
|