OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [main.cpp] - Rev 2

Compare with Previous | Blame | View Log

#include <cstdio>
#include <cstdlib>
 
#include "bochs.h"
#include "cpu.h"
#include "iodev/iodev.h"
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
 
int test_type;
 
bool load_segment(bx_segment_reg_t *seg, const char *prefix, char *name, unsigned long long value) {
 
    if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "cache_valid:") == 0) { seg->cache.valid = value & 1; }
 
    else if( (strncmp(name, "cs:", 3) == 0   && strcmp(prefix, "cs_") == 0) ||
             (strncmp(name, "ds:", 3) == 0   && strcmp(prefix, "ds_") == 0) ||
             (strncmp(name, "es:", 3) == 0   && strcmp(prefix, "es_") == 0) ||
             (strncmp(name, "fs:", 3) == 0   && strcmp(prefix, "fs_") == 0) ||
             (strncmp(name, "gs:", 3) == 0   && strcmp(prefix, "gs_") == 0) ||
             (strncmp(name, "ss:", 3) == 0   && strcmp(prefix, "ss_") == 0) ||
             (strncmp(name, "ldtr:", 5) == 0 && strcmp(prefix, "ldtr_") == 0) ||
             (strncmp(name, "tr:", 3) == 0   && strcmp(prefix, "tr_") == 0) )
    {
        seg->selector.value = value & 0xFFFF;
        seg->selector.index = value >> 3;
        seg->selector.ti    = (value >> 2) & 1;
        seg->selector.rpl   = value & 3;
    }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "rpl:") == 0)   { seg->selector.rpl = value & 3; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "base:") == 0)  { seg->cache.u.segment.base = value & 0xFFFFFFFF; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "limit:") == 0) {
        seg->cache.u.segment.limit_scaled = value & 0xFFFFF;
        if(seg->cache.u.segment.g) seg->cache.u.segment.limit_scaled = (seg->cache.u.segment.limit_scaled << 12) | 0xFFF;
    }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "g:") == 0) {
        seg->cache.u.segment.g = value & 1;
        if(seg->cache.u.segment.g) seg->cache.u.segment.limit_scaled = (seg->cache.u.segment.limit_scaled << 12) | 0xFFF;
    }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "d_b:")  == 0)  { seg->cache.u.segment.d_b = value & 1; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "avl:")  == 0)  { seg->cache.u.segment.avl = value & 1; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "p:")    == 0)  { seg->cache.p             = value & 1; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "dpl:")  == 0)  { seg->cache.dpl           = value & 3; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "s:")    == 0)  { seg->cache.segment       = value & 1; }
    else if(strncmp(name, prefix, strlen(prefix)) == 0 && strcmp(name+strlen(prefix), "type:") == 0)  { seg->cache.type          = value & 15; }
    else return false;
 
    return true;
}
 
void initialize() {
    printf("start_input: 0\n");
    printf("\n");
    fflush(stdout);
 
    bool do_loop = true;
 
    char name[256];
    unsigned long long value;
 
    while(do_loop) {
 
        fscanf(stdin, "%s", name);
        fscanf(stdin, "%x", &value);
 
        if     (strcmp(name, "quit:") == 0)      { exit(0); }
        else if(strcmp(name, "continue:") == 0)  { do_loop = false; }
 
        else if(strcmp(name, "test_type:") == 0) { test_type = value; }
 
        else if(strcmp(name, "eax:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_EAX, value); }
        else if(strcmp(name, "ebx:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_EBX, value); }
        else if(strcmp(name, "ecx:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_ECX, value); }
        else if(strcmp(name, "edx:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_EDX, value); }
        else if(strcmp(name, "esi:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_ESI, value); }
        else if(strcmp(name, "edi:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_EDI, value); }
        else if(strcmp(name, "ebp:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_EBP, value); }
        else if(strcmp(name, "esp:") == 0)       { bx_cpu.set_reg32(BX_32BIT_REG_ESP, value); }
 
        else if(strcmp(name, "eip:") == 0)       { bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx = value; }
 
        else if(strcmp(name, "cflag:") == 0)     { bx_cpu.set_CF(value); }
        else if(strcmp(name, "pflag:") == 0)     { bx_cpu.set_PF(value); }
        else if(strcmp(name, "aflag:") == 0)     { bx_cpu.set_AF(value); }
        else if(strcmp(name, "zflag:") == 0)     { bx_cpu.set_ZF(value); }
        else if(strcmp(name, "sflag:") == 0)     { bx_cpu.set_SF(value); }
        else if(strcmp(name, "tflag:") == 0)     { bx_cpu.set_TF(value); }
        else if(strcmp(name, "iflag:") == 0)     { bx_cpu.set_IF(value); }
        else if(strcmp(name, "dflag:") == 0)     { bx_cpu.set_DF(value); }
        else if(strcmp(name, "oflag:") == 0)     { bx_cpu.set_OF(value); }
        else if(strcmp(name, "iopl:") == 0)      { bx_cpu.set_IOPL(value); }
        else if(strcmp(name, "ntflag:") == 0)    { bx_cpu.set_NT(value); }
        else if(strcmp(name, "rflag:") == 0)     { bx_cpu.set_RF(value); }
        else if(strcmp(name, "vmflag:") == 0)    { bx_cpu.set_VM(value); }
        else if(strcmp(name, "acflag:") == 0)    { bx_cpu.set_AC(value); }
        else if(strcmp(name, "idflag:") == 0)    { bx_cpu.set_ID(value); }
 
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_CS]), "cs_", name, value)) { }
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_DS]), "ds_", name, value)) { }
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_ES]), "es_", name, value)) { }
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_FS]), "fs_", name, value)) { }
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_GS]), "gs_", name, value)) { }
        else if(load_segment(&(bx_cpu.sregs[BX_SEG_REG_SS]), "ss_", name, value)) { }
        else if(load_segment(&(bx_cpu.ldtr), "ldtr_", name, value)) { }
        else if(load_segment(&(bx_cpu.tr),   "tr_",   name, value)) { }
 
        else if(strcmp(name, "gdtr_base:") == 0) { bx_cpu.gdtr.base  = value & 0xFFFFFFFF; }
        else if(strcmp(name, "gdtr_limit:") == 0){ bx_cpu.gdtr.limit = value & 0xFFFF; }
 
        else if(strcmp(name, "idtr_base:") == 0) { bx_cpu.idtr.base  = value & 0xFFFFFFFF; }
        else if(strcmp(name, "idtr_limit:") == 0){ bx_cpu.idtr.limit = value & 0xFFFF; }
 
        else if(strcmp(name, "cr0_pe:") == 0) { bx_cpu.cr0.set_PE(value & 1); }
        else if(strcmp(name, "cr0_mp:") == 0) { bx_cpu.cr0.set_MP(value & 1); }
        else if(strcmp(name, "cr0_em:") == 0) { bx_cpu.cr0.set_EM(value & 1); }
        else if(strcmp(name, "cr0_ts:") == 0) { bx_cpu.cr0.set_TS(value & 1); }
        else if(strcmp(name, "cr0_ne:") == 0) { bx_cpu.cr0.set_NE(value & 1); }
        else if(strcmp(name, "cr0_wp:") == 0) { bx_cpu.cr0.set_WP(value & 1); }
        else if(strcmp(name, "cr0_am:") == 0) { bx_cpu.cr0.set_AM(value & 1); }
        else if(strcmp(name, "cr0_nw:") == 0) { bx_cpu.cr0.set_NW(value & 1); }
        else if(strcmp(name, "cr0_cd:") == 0) { bx_cpu.cr0.set_CD(value & 1); }
        else if(strcmp(name, "cr0_pg:") == 0) { bx_cpu.cr0.set_PG(value & 1); }
 
        else if(strcmp(name, "cr2:") == 0)    { bx_cpu.cr2 = value & 0xFFFFFFFF; }
        else if(strcmp(name, "cr3:") == 0)    { bx_cpu.cr3 = value & 0xFFFFFFFF; }
 
        else if(strcmp(name, "dr0:") == 0)    { bx_cpu.dr[0] = value & 0xFFFFFFFF; }
        else if(strcmp(name, "dr1:") == 0)    { bx_cpu.dr[1] = value & 0xFFFFFFFF; }
        else if(strcmp(name, "dr2:") == 0)    { bx_cpu.dr[2] = value & 0xFFFFFFFF; }
        else if(strcmp(name, "dr3:") == 0)    { bx_cpu.dr[3] = value & 0xFFFFFFFF; }
 
        else if(strcmp(name, "dr6:") == 0)    { bx_cpu.dr6.val32 = (bx_cpu.dr6.val32 & 0xffff0ff0) | (value & 0x0000f00f); }
        else if(strcmp(name, "dr7:") == 0)    { bx_cpu.dr7.val32 = value | 0x00000400; }
 
        else {
            printf("#bochs486: unknown input: %s %x\n", name, value);
            exit(-1);
        }
    }
}
 
void print_segment(bx_segment_reg_t *seg, const char *prefix) {
 
    printf("%s_cache_valid: %01x\n",   prefix, seg->cache.valid & 1);
    printf("%s:             %04x\n",   prefix, seg->selector.value);
    printf("%s_rpl:         %01hhx\n", prefix, seg->selector.rpl);
 
    printf("%s_base:        %08x\n",   prefix, seg->cache.u.segment.base);
    printf("%s_limit:       %08x\n",   prefix, (seg->cache.u.segment.g)? seg->cache.u.segment.limit_scaled >> 12 : seg->cache.u.segment.limit_scaled);
    printf("%s_g:           %01x\n",   prefix, seg->cache.u.segment.g);
    printf("%s_d_b:         %01x\n",   prefix, seg->cache.u.segment.d_b);
    printf("%s_avl:         %01x\n",   prefix, seg->cache.u.segment.avl);
    printf("%s_p:           %01x\n",   prefix, seg->cache.p);
    printf("%s_dpl:         %01x\n",   prefix, seg->cache.dpl);
    printf("%s_s:           %01x\n",   prefix, seg->cache.segment);
    printf("%s_type:        %01x\n",   prefix, seg->cache.type);
}
 
void output_cpu_state() {
    printf("start_output: 0\n");
 
    //used only in verilog testbench
    printf("tb_wr_cmd_last: 0\n");
    printf("tb_can_ignore:  0\n");
 
    printf("eax: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_EAX));
    printf("ebx: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_EBX));
    printf("ecx: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_ECX));
    printf("edx: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_EDX));
    printf("esi: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_ESI));
    printf("edi: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_EDI));
    printf("ebp: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_EBP));
    printf("esp: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_ESP));
 
    printf("eip: %08x\n", bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx);
 
    printf("cflag:  %01x\n", bx_cpu.getB_CF());
    printf("pflag:  %01x\n", bx_cpu.getB_PF());
    printf("aflag:  %01x\n", bx_cpu.getB_AF());
    printf("zflag:  %01x\n", bx_cpu.getB_ZF());
    printf("sflag:  %01x\n", bx_cpu.getB_SF());
    printf("tflag:  %01x\n", bx_cpu.getB_TF()&1);
    printf("iflag:  %01x\n", bx_cpu.getB_IF()&1);
    printf("dflag:  %01x\n", bx_cpu.getB_DF()&1);
    printf("oflag:  %01x\n", bx_cpu.getB_OF()&1);
    printf("iopl:   %01x\n", bx_cpu.get_IOPL()&3);
    printf("ntflag: %01x\n", bx_cpu.getB_NT()&1);
    printf("rflag:  %01x\n", bx_cpu.getB_RF()&1);
    printf("vmflag: %01x\n", bx_cpu.getB_VM()&1);
    printf("acflag: %01x\n", bx_cpu.getB_AC()&1);
    printf("idflag: %01x\n", bx_cpu.getB_ID()&1);
 
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_CS]), "cs");
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_DS]), "ds");
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_ES]), "es");
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_FS]), "fs");
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_GS]), "gs");
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_SS]), "ss");
    print_segment(&(bx_cpu.ldtr), "ldtr");
    print_segment(&(bx_cpu.tr),   "tr");
 
    printf("gdtr_base:  %08x\n", bx_cpu.gdtr.base);
    printf("gdtr_limit: %02x\n", bx_cpu.gdtr.limit & 0xFFFF);
 
    printf("idtr_base:  %08x\n", bx_cpu.idtr.base);
    printf("idtr_limit: %02x\n", bx_cpu.idtr.limit & 0xFFFF);
 
    printf("cr0_pe: %01x\n", bx_cpu.cr0.get_PE() & 1);
    printf("cr0_mp: %01x\n", bx_cpu.cr0.get_MP() & 1);
    printf("cr0_em: %01x\n", bx_cpu.cr0.get_EM() & 1);
    printf("cr0_ts: %01x\n", bx_cpu.cr0.get_TS() & 1);
    printf("cr0_ne: %01x\n", bx_cpu.cr0.get_NE() & 1);
    printf("cr0_wp: %01x\n", bx_cpu.cr0.get_WP() & 1);
    printf("cr0_am: %01x\n", bx_cpu.cr0.get_AM() & 1);
    printf("cr0_nw: %01x\n", bx_cpu.cr0.get_NW() & 1);
    printf("cr0_cd: %01x\n", bx_cpu.cr0.get_CD() & 1);
    printf("cr0_pg: %01x\n", bx_cpu.cr0.get_PG() & 1);
 
    printf("cr2: %08x\n", bx_cpu.cr2);
    printf("cr3: %08x\n", bx_cpu.cr3);
 
    printf("dr0: %08x\n", bx_cpu.dr[0]);
    printf("dr1: %08x\n", bx_cpu.dr[1]);
    printf("dr2: %08x\n", bx_cpu.dr[2]);
    printf("dr3: %08x\n", bx_cpu.dr[3]);
 
    printf("dr6: %08x\n", bx_cpu.dr6.val32);
    printf("dr7: %08x\n", bx_cpu.dr7.val32);
 
    printf("\n");
    fflush(stdout);
}
 
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ logfunctions
 
void logfunctions::panic(const char *fmt, ...) {
    printf("#bochs486::logfunctions::panic(): ");
 
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
 
    printf("\n");
    fflush(stdout);
 
    if(strstr(fmt, "exception with no resolution") != NULL) {
        printf("start_shutdown: 0\n");
        printf("\n");
        fflush(stdout);
        exit(0);
    }
    else {
        exit(-1);
    }
}
void logfunctions::error(const char *fmt, ...) {
    printf("#bochs486::logfunctions::error(): ");
 
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
 
    printf("\n");
    fflush(stdout);
}
void logfunctions::ldebug(const char *fmt, ...) {
    printf("#bochs486::logfunctions::debug(): ");
 
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);   
 
    printf("\n");
    fflush(stdout);
}
void logfunctions::info(const char *fmt, ...) {
    printf("#bochs486::logfunctions::info(): ");
 
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);   
 
    printf("\n");
    fflush(stdout);
}
void logfunctions::put(const char *n, const char *p) {
}
logfunctions::logfunctions() {
}
logfunctions::~logfunctions() {
}
 
static logfunctions theLog;
logfunctions *pluginlog         = &theLog;
logfunctions *siminterface_log  = &theLog;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ menu
 
void bx_param_string_c::text_print(FILE *fp) {
printf("#bochs486::bx_param_string_c::text_print()\n");
}
void bx_param_enum_c::text_print(FILE *fp) {
printf("#bochs486::bx_param_enum_c::text_print()\n");
}
void bx_param_bool_c::text_print(FILE *fp) {
printf("#bochs486::bx_param_bool_c::text_print()\n");
}
void bx_param_num_c::text_print(FILE *fp) {
printf("#bochs486::bx_param_num_c::text_print()\n");
}
void bx_list_c::text_print(FILE *fp) {
printf("#bochs486::bx_list_c::text_print()\n");
}
int bx_param_enum_c::text_ask(FILE *fpin, FILE *fpout) {
printf("#bochs486::bx_param_enum_c::text_ask()\n");
    return 0;
}
int bx_param_bool_c::text_ask(FILE *fpin, FILE *fpout) {
printf("#bochs486::bx_param_bool_c::text_ask()\n");
    return 0;
}
int bx_param_num_c::text_ask(FILE *fpin, FILE *fpout) {
printf("#bochs486::bx_param_num_c::text_ask()\n");
    return 0;
}
int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout) {
printf("#bochs486::bx_param_string_c::text_ask()\n");
    return 0;
}
int bx_list_c::text_ask(FILE *fpin, FILE *fpout) {
printf("#bochs486::bx_list_c::text_ask()\n");
    return 0;
}
 
bx_list_c *root_param = NULL;
 
bx_gui_c *bx_gui = NULL;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ cpu
 
void BX_CPU_C::enter_system_management_mode(void) {
printf("#bochs486: enter_system_management_mod()\n");
}
void BX_CPU_C::init_SMRAM(void) {
printf("#bochs486: init_SMRAM()\n");
}
void BX_CPU_C::debug(bx_address offset) {
printf("#bochs486: debug(offset=%08x)\n", offset);
}
void BX_CPU_C::debug_disasm_instruction(bx_address offset) {
printf("#bochs486: debug_disasm_instruction(offset=%08x)\n", offset);
}
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ pc_system
 
void bx_pc_system_c::countdownEvent(void) {
}
bx_pc_system_c::bx_pc_system_c() {
}
int bx_pc_system_c::Reset(unsigned type) {
    printf("#bochs486: bx_pc_system_c::Reset(%d) unimplemented.\n", type);
    std::exit(-1);
}
 
bx_pc_system_c bx_pc_system;
 
const char* cpu_mode_string(unsigned cpu_mode) {
  static const char *cpu_mode_name[] = {
     "real mode",
     "v8086 mode",
     "protected mode",
     "compatibility mode",
     "long mode",
     "unknown mode"
  };
 
  if(cpu_mode >= 5) cpu_mode = 5;
  return cpu_mode_name[cpu_mode];
}
 
bx_param_string_c        *param_vendor_string;
bx_param_string_c        *param_brand_string;
bx_param_bool_c          *param_bool_false;
bx_param_enum_c          *param_enum_zero;
bx_param_num_c           *param_stepping, *param_model, *param_family;
bx_param_num_c           *param_cpulevel_for_cpuid;
 
class bochs486_sim : public bx_simulator_interface_c {
 
    bx_param_bool_c *get_param_bool(const char *pname, bx_param_c *base) {
        if(strcmp(pname, BXPN_CPUID_LIMIT_WINNT) == 0)      return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_SSE4A) == 0)            return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_SEP) == 0)              return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_XSAVE) == 0)            return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_XSAVEOPT) == 0)         return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_AES) == 0)              return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_MOVBE) == 0)            return param_bool_false;
        if(strcmp(pname, BXPN_CPUID_SMEP) == 0)             return param_bool_false;
        if(strcmp(pname, BXPN_RESET_ON_TRIPLE_FAULT) == 0)  return param_bool_false;
        return NULL;
    }
    bx_param_string_c *get_param_string(const char *pname, bx_param_c *base) {
        if(strcmp(pname, BXPN_VENDOR_STRING) == 0) return param_vendor_string;
        if(strcmp(pname, BXPN_BRAND_STRING) == 0)  return param_brand_string;
        return NULL;
    }
    bx_param_enum_c *get_param_enum(const char *pname, bx_param_c *base) {
        if(strcmp(pname, BXPN_CPU_MODEL) == 0)  return param_enum_zero;
        if(strcmp(pname, BXPN_CPUID_SSE) == 0)  return param_enum_zero;
        return NULL;
    }
    bx_param_num_c *get_param_num(const char *pname, bx_param_c *base) {
        if(strcmp(pname, BXPN_CPUID_STEPPING) == 0)  return param_stepping;
        if(strcmp(pname, BXPN_CPUID_MODEL) == 0)     return param_model;
        if(strcmp(pname, BXPN_CPUID_FAMILY) == 0)    return param_family;
        if(strcmp(pname, BXPN_CPUID_LEVEL) == 0)     return param_cpulevel_for_cpuid;
        return NULL;
    }
};
 
bx_simulator_interface_c *SIM;
 
BOCHSAPI BX_CPU_C bx_cpu;
int interrupt_vector;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ devices
 
class bochs486_pic : public bx_pic_stub_c {
    Bit8u IAC(void) { bx_cpu.clear_INTR(); return interrupt_vector & 0xFF; }
 
};
 
  Bit32u BX_CPP_AttrRegparmN(2)
bx_devices_c::inp(Bit16u addr, unsigned io_len) {
    // read aligned to 4 bytes, with byteena
 
    bool two_reads = (addr & 0x3) + io_len > 4;
 
    Bit16u   addr1    = addr & 0xFFFC;
    unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
 
    Bit16u   addr2    = (addr + 4) & 0xFFFC;
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
 
    printf("start_io_read: 0\n");
    printf("address: %04hx\n", addr1);
    printf("byteena: %02x\n",  byteena1 & 0xF);
    printf("can_ignore: 0\n");
    printf("\n");
    fflush(stdout);
 
    unsigned int data1 = 0;
    fscanf(stdin, "%x", &data1);
 
    unsigned long long data = data1;
 
    if(two_reads) {
        printf("start_io_read: 0\n");
        printf("address: %04hx\n", addr2);
        printf("byteena: %02x\n",  byteena2);
        printf("can_ignore: 0\n");
        printf("\n");
        fflush(stdout);
 
        unsigned int data2 = 0;
        fscanf(stdin, "%x", &data2);
 
        data = ((unsigned long long)data2 << 32) | data1;
    }
 
    while((byteena1 & 1) == 0) {
        byteena1 >>= 1;
        data >>= 8;
    }
 
    return (io_len == 1)? (data & 0xFF) : (io_len == 2)? (data & 0xFFFF) : (io_len == 3)? (data & 0xFFFFFF) : (data & 0xFFFFFFFF);
 
}
 
  void BX_CPP_AttrRegparmN(3)
bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) {
    // write aligned to 4 bytes, with byteena
 
    bool two_writes = (addr & 0x3) + io_len > 4;
 
    Bit16u   addr1    = addr & 0xFFFC;
    unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
 
    Bit16u   addr2    = (addr + 4) & 0xFFFC;
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
 
    Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
    Bit32u value1 = value_full;
    Bit32u value2   = (value_full >> 32);
 
    printf("start_io_write: 0\n");
    printf("address: %04hx\n", addr1);
    printf("data:    %08x\n",  value1);
    printf("byteena: %02x\n",  byteena1 & 0xF);
    printf("can_ignore: 0\n");
 
    printf("\n");
    fflush(stdout);
 
    if(two_writes) {
        printf("start_io_write: 0\n");
        printf("address: %04hx\n", addr2);
        printf("data:    %08x\n",  value2);
        printf("byteena: %02x\n",  byteena2);
        printf("can_ignore: 0\n");
 
        printf("\n");
        fflush(stdout);
    }    
}
bx_devices_c::bx_devices_c() {
    pluginPicDevice = new bochs486_pic();
}
bx_devices_c::~bx_devices_c() {
}
 
bx_devices_c bx_devices;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ memory
 
struct bochs486_page_t {
    Bit8u page_buf[4096*2];
    Bit8u *page;
    bx_phy_address paddr;
    struct bochs486_page_t *next;
};
struct bochs486_page_t *bochs486_pages = NULL;
 
void BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
printf("#bochs486: writePhysicalPage: addr=%08x, len=%d\n", addr, len);
 
    if(len > 4) {
        printf("#bochs486: writePhysicalPage() with len = %d\n", len);
        exit(-1);
    }
 
    bool two_writes = (addr & 0x3) + len > 4;
 
    Bit32u   addr1    = addr & 0xFFFFFFFC;
    unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
 
    Bit32u   addr2    = (addr + 4) & 0xFFFFFFFC;
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
 
    Bit32u value = ((unsigned int *)data)[0];
 
    Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
    Bit32u value1 = value_full;
    Bit32u value2   = (value_full >> 32);
 
    printf("start_write: 0\n");
    printf("address: %08x\n",  addr1);
    printf("data:    %08x\n",  value1);
    printf("byteena: %02x\n",  byteena1 & 0xF);
    printf("can_ignore: 0\n");
 
    printf("\n");
    fflush(stdout);
 
    if(two_writes) {
        printf("start_write: 0\n");
        printf("address: %08x\n",  addr2);
        printf("data:    %08x\n",  value2);
        printf("byteena: %02x\n",  byteena2);
        printf("can_ignore: 0\n");
 
        printf("\n");
        fflush(stdout);
    }    
 
    //update host memory pages
    unsigned char *ptr = (unsigned char *)data;
 
    struct bochs486_page_t *page_ptr = bochs486_pages;
    while(page_ptr != NULL) {
        if(page_ptr->paddr == (addr & 0xFFFFF000) && page_ptr->page != NULL) {
            for(int i=0; i<len; i++) page_ptr->page[(addr & 0xFFF) + i] = ptr[i];
        }
        page_ptr = page_ptr->next;
    }
}
 
void BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
printf("#bochs486: readPhysicalPage: addr=%08x, len=%d\n", addr, len);
 
    if(len == 4096) {
        if((addr & 3) != 0) {
            printf("#bochs486: readPhysicalPage() with len = 4096 and addr not aligned to 4.");
            exit(-1);
        }
 
        unsigned int *ptr = (unsigned int*)data;
 
        for(unsigned i=0; i<len; i+=4) {
            printf("start_read_code: 0\n");
            printf("address: %08x\n", addr);
            printf("byteena: F\n");
            printf("\n");
            fflush(stdout);
 
            fscanf(stdin, "%x", &(ptr[i/4]));
 
            addr += 4;
        }
        return;
    }
 
    //check if read crosses line boundry (16 bytes)
    if( ((addr) & 0xFFFFFFF0) != ((addr + len - 1) & 0xFFFFFFF0) ) {
        unsigned char *ptr = (unsigned char*)data;
        readPhysicalPage(cpu, addr,             (addr | 0xF) - addr + 1,       ptr);
        readPhysicalPage(cpu, (addr | 0xF) + 1, len - (addr | 0xF) + addr - 1, ptr + ((addr | 0xF) - addr + 1));
        return;
    }
 
    bool two_reads   = ((addr & 0x3) + len > 4) && ((addr & 0x3) + len <= 8);
    bool three_reads = ((addr & 0x3) + len > 8);
 
    Bit32u   addr1    = addr & 0xFFFFFFFC;
    unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
 
    Bit32u   addr2    = (addr + 4) & 0xFFFFFFFC;
    Bit32u   addr3    = (addr + 8) & 0xFFFFFFFC;
 
    if(two_reads || three_reads) byteena1 = 0xF;
    byteena1 &= 0xF;
    printf("start_read: 0\n");
    printf("address: %08x\n", addr1);
    printf("byteena: %02x\n", byteena1);
    printf("can_ignore: 0\n");
 
    printf("\n");
    fflush(stdout);
 
    unsigned int data_read[3] = { 0,0,0 };
    fscanf(stdin, "%x", &data_read[0]);
 
    if(two_reads || three_reads) {
        printf("start_read: 0\n");
        printf("address: %08x\n", addr2);
        printf("byteena: F\n");
        printf("can_ignore: 0\n");
 
        printf("\n");
        fflush(stdout);
 
        unsigned int data2 = 0;
        fscanf(stdin, "%x", &data_read[1]);
 
        if(three_reads) {
            printf("start_read: 0\n");
            printf("address: %08x\n", addr3);
            printf("byteena: F\n");
            printf("can_ignore: 0\n");
 
            printf("\n");
            fflush(stdout);
 
            unsigned int data3 = 0;
            fscanf(stdin, "%x", &data_read[2]);
        }
    }
 
    unsigned char *ptr = (unsigned char *)data_read;
 
    for(int i=0; i<(addr & 0x3); i++) ptr++;
 
    memcpy((unsigned char *)data, ptr, len);
 
//ptr = (unsigned char *)data;
//for(int i=0; i<len; i++) printf("#R[%d]: %hhx\n", i, ptr[i]);
}
 
Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw) {
printf("#bochs486: getHostMemAddr: addr=%08x, rw=%d\n", addr, rw);
 
    // find page
    struct bochs486_page_t *ptr = bochs486_pages;
 
    while(ptr != NULL) {
        if(ptr->paddr == addr) {
printf("#bochs486: getHostMemAddr: hostPtr[old]: %p\n", ptr->page);
            return ptr->page;
        }
 
        if(ptr->next != NULL) ptr = ptr->next;
        else break;
    }
 
    // create new page
    struct bochs486_page_t *new_page = new struct bochs486_page_t();
    new_page->paddr = addr;
    new_page->next = NULL;
 
    // find address at 4096 boundry
    new_page->page = new_page->page_buf;
    while( ( ((unsigned long long)new_page->page) % 4096) != 0 ) new_page->page++;
 
    readPhysicalPage(cpu, addr, 4096, new_page->page);
 
    // link new page
    if(bochs486_pages == NULL) {
        bochs486_pages = new_page;
    }
    else {
        ptr->next = new_page;
    }
 
printf("#bochs486: getHostMemAddr: hostPtr[new]: %p\n", new_page->page);
    return new_page->page;
}
BX_MEM_C::BX_MEM_C() {
}
BX_MEM_C::~BX_MEM_C() {
}
 
BOCHSAPI BX_MEM_C bx_mem;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ interrupt
 
bool bochs486_skip_rep_finish = false;
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ instrument
 
int instruction_count = 0;
 
int bochs486_rep;
int bochs486_seg;
int bochs486_lock;
int bochs486_as32;
int bochs486_os32;
int bochs486_cmd_len;
 
void bx_instr_init_env(void) { }
void bx_instr_exit_env(void) { }
 
void bx_instr_debug_promt() { }
void bx_instr_debug_cmd(const char *cmd) { }
 
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip) { }
void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip) { }
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip) { }
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) { }
 
void bx_instr_opcode(unsigned cpu, bxInstruction_c *i, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) { }
 
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) { }
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) { }
 
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3) { }
void bx_instr_cache_cntrl(unsigned cpu, unsigned what) { }
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset) { }
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr) { }
 
void bx_instr_initialize(unsigned cpu) { }
void bx_instr_exit(unsigned cpu) { }
void bx_instr_reset(unsigned cpu, unsigned type) { }
 
void bx_instr_inp(Bit16u addr, unsigned len) { }
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val) { }
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val) { }
 
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw) { }
void bx_instr_phy_access(unsigned cpu, bx_address phy, unsigned len, unsigned rw) { }
 
void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value) { }
 
 
 
void bx_instr_interrupt(unsigned cpu, unsigned vector, unsigned type, bx_bool push_error, Bit16u error_code) {
 
    bochs486_skip_rep_finish = false;
 
    if(type != 4 && type != 5 && type != 6) { //BX_SOFTWARE_INTERRUPT; BX_PRIVILEGED_SOFTWARE_INTERRUPT; BX_SOFTWARE_EXCEPTION
 
printf("#bochs486: bx_instr_interrupt(), test_type: %d, type: %d, vector: %02x\n", test_type, type, vector); fflush(stdout);
 
        int is_interrupt = 0;
        if(type == 0) is_interrupt = 1; // BX_EXTERNAL_INTERRUPT
 
        if(is_interrupt) {
            printf("start_interrupt: 0\n");
        }
        else {
            printf("start_exception: 0\n");
            printf("push_error: %01x\n",      push_error);
            printf("error_code: %04x\n",      error_code);
        }
        printf("vector: %02x\n", vector);
        printf("\n");
        fflush(stdout);
 
        output_cpu_state();
 
        if(test_type == 0) exit(0);
 
        instruction_count++;
        if(test_type > 0 && instruction_count == test_type) exit(0);
    }
}
 
void instr_after_execution() {
    printf("#bochs486: instr_after_execution()\n"); fflush(stdout);
 
    printf("start_completed: 0\n");
    printf("rep:      %x\n", bochs486_rep);
    printf("seg:      %x\n", bochs486_seg);
    printf("lock:     %x\n", bochs486_lock);
    printf("os32:     %x\n", bochs486_os32);
    printf("as32:     %x\n", bochs486_as32);
    printf("consumed: %x\n", bochs486_cmd_len);
    printf("\n");
    fflush(stdout);
 
    output_cpu_state();
 
    instruction_count++;
    if(test_type > 0 && instruction_count == test_type) exit(0);
 
    //interrupt
    printf("start_check_interrupt: 0\n");
    printf("\n");
    fflush(stdout);
 
    fscanf(stdin, "%x", &interrupt_vector);
 
printf("#bochs486_check_interrupt: %x\n", interrupt_vector);
    if(interrupt_vector != 0x100) {
        bx_cpu.raise_INTR();
    }
    else bx_cpu.clear_INTR();
}
 
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) {
    bochs486_rep     = i->bochs486_rep;   // 0-none, 2-0xF2, 3-0xF3
    bochs486_seg     = i->seg() & 0x7;            // 0-5
    bochs486_lock    = (i->bochs486_lock)? 1 : 0;
    bochs486_as32    = (i->as32L())?  1 : 0;
    bochs486_os32    = (i->os32L())?  1 : 0;
    bochs486_cmd_len = i->ilen();
 
printf("#instr: %02x, async_event: %x\n", i->bochs486_opcode, bx_cpu.async_event);
 
    printf("#start_decoded:\n");
    printf("#decoded_rep:      %x\n", bochs486_rep);
    printf("#decoded_seg:      %x\n", bochs486_seg);
    printf("#decoded_lock:     %x\n", bochs486_lock);
    printf("#decoded_os32:     %x\n", bochs486_os32);
    printf("#decoded_as32:     %x\n", bochs486_as32);
    printf("#decoded_consumed: %x\n", bochs486_cmd_len);
    printf("\n");
    fflush(stdout);
}
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i) {
    if(bochs486_skip_rep_finish) {
        printf("#bx_instr_after_execution: bochs486_skip_rep_finished\n");
        bochs486_skip_rep_finish = false;
        return;
    }
 
    //patch XCHG
    if((i->bochs486_modregrm >> 6) != 3 && (i->bochs486_opcode == 0x86 || i->bochs486_opcode == 0x87)) bochs486_lock = 1;
 
    instr_after_execution();
}
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i) {
    bochs486_skip_rep_finish = true;
 
    instr_after_execution();
}
 
void bx_instr_hlt(unsigned cpu) {
    instr_after_execution();
 
    //if(test_type == 0) exit(0);
}
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags) { }
 
// memory trace callbacks from CPU, len=1,2,4 or 8
void bx_dbg_lin_memory_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned pl, unsigned rw, Bit8u *data) {
    if(rw == BX_READ) {
printf("#bochs486: bx_dbg_lin_memory_access() read redirect.\n");
        Bit8u buf[8];
        bx_mem.readPhysicalPage(NULL, phy, len, buf);
 
        bool read_ok = true;
        for(int i=0; i<len; i++) if(data[i] != buf[i]) read_ok = false;
 
        if(read_ok == false) {
printf("#bochs486: bx_dbg_lin_memory_access() read mismatch: lin=%08x, phy=%08x, len=%d, pl=%d, rw=%d\n", lin, phy, len, pl, rw);
            for(int i=0; i<len; i++) {
                printf("#%d: %02hhx --- %02hhx\n", i, data[i], buf[i]);
            }
            exit(-1);
        }
    }
    if(rw == BX_WRITE) {
printf("#bochs486: bx_dbg_lin_memory_access() write redirect: phy=%08x, len=%d\n", phy, len);
        bx_mem.writePhysicalPage(NULL, phy, len, data);
    }
}
void bx_dbg_phy_memory_access(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw, unsigned attr, Bit8u *data) {
}
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ main
 
int main(int argc, char **argv) {
 
    bx_pc_system.a20_mask = 0xFFFFFFFF;
 
    SIM = new bochs486_sim();
 
    const char *choices[] = { "0_choice", NULL };
 
    param_vendor_string      = new bx_param_string_c(NULL, "1_name", "1_label", "1_descr", "GeniuneAO486");
    param_brand_string       = new bx_param_string_c(NULL, "2_name", "2_label", "2_descr", "ao486                                           ");
    param_bool_false         = new bx_param_bool_c(  NULL, "3_name", "3_label", "3_descr", 0);
    param_enum_zero          = new bx_param_enum_c(  NULL, "4_name", "4_label", "4_descr", choices, 0);
    param_stepping           = new bx_param_num_c(   NULL, "5_name", "5_label", "5_descr", 0xB,0xB,0xB);
    param_model              = new bx_param_num_c(   NULL, "6_name", "6_label", "6_descr", 0x5,0x5,0x5);
    param_family             = new bx_param_num_c(   NULL, "7_name", "7_label", "7_descr", 0x4,0x4,0x4);
    param_cpulevel_for_cpuid = new bx_param_num_c(   NULL, "8_name", "8_label", "8_descr", 0x4,0x4,0x4);  
 
    bx_cpu.initialize();
    bx_cpu.reset(BX_RESET_HARDWARE);
 
    printf("START\n");
 
    initialize();
 
    bx_cpu.async_event = 0;
    bx_cpu.handleCpuModeChange();
 
    output_cpu_state();
    bx_cpu.cpu_loop();
 
    printf("#bochs486: finishing.\n");
    return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.