Browse Source

Some assertions and minor changes

copy 7 years ago
parent
commit
e3e6367ccf
5 changed files with 77 additions and 29 deletions
  1. 63 22
      src/cpu.js
  2. 10 3
      src/instructions.js
  3. 2 2
      src/io.js
  4. 1 1
      src/pit.js
  5. 1 1
      src/state.js

+ 63 - 22
src/cpu.js

@@ -808,6 +808,35 @@ if(typeof window !== "undefined")
     window.__no_inline3 = CPU.prototype.hlt_loop;
 };
 
+/** @const */
+var PROFILING = false;
+
+if(PROFILING)
+{
+    var instruction_total = new Float64Array(256);
+    var instruction_count = new Uint32Array(256);
+
+    function print_profiling()
+    {
+        var prof_instructions = [];
+        for(var i = 0; i < 256; i++) prof_instructions[i] = {
+            n: h(i, 2),
+            total: instruction_total[i],
+            count: instruction_count[i],
+            per: (instruction_total[i] / instruction_count[i]) || 0,
+        }
+
+        console.log("count:");
+        console.table(prof_instructions.sort((p0, p1) => p1.count - p0.count));
+
+        console.log("time:");
+        console.table(prof_instructions.sort((p0, p1) => p1.total - p0.total));
+
+        console.log("time/count:");
+        console.table(prof_instructions.sort((p0, p1) => p1.per - p0.per));
+    }
+}
+
 /**
  * execute a single instruction cycle on the cpu
  * this includes reading all prefixes and the whole instruction
@@ -818,7 +847,13 @@ CPU.prototype.cycle_internal = function()
 
     this.timestamp_counter++;
 
+    if(PROFILING)
+    {
+        var start = performance.now();
+    }
+
     var opcode = this.read_imm8();
+    //this.translate_address_read(this.instruction_pointer + 15|0)
 
     if(DEBUG)
     {
@@ -828,6 +863,13 @@ CPU.prototype.cycle_internal = function()
     // call the instruction
     this.table[opcode](this);
 
+    if(PROFILING)
+    {
+        var end = performance.now();
+        instruction_total[opcode] += end - start;
+        instruction_count[opcode]++;
+    }
+
     if(this.flags & flag_trap)
     {
         // TODO
@@ -917,6 +959,8 @@ CPU.prototype.cr0_changed = function(old_cr0)
     }
     this.cr[0] |= CR0_ET;
 
+    this.paging_changed();
+
     dbg_assert(typeof this.paging === "boolean");
     if(new_paging !== this.paging)
     {
@@ -942,17 +986,6 @@ CPU.prototype.cpl_changed = function()
     this.last_virt_esp = -1;
 };
 
-CPU.prototype.get_phys_eip = function()
-{
-    if((this.instruction_pointer & ~0xFFF) ^ this.last_virt_eip)
-    {
-        this.eip_phys = this.translate_address_read(this.instruction_pointer) ^ this.instruction_pointer;
-        this.last_virt_eip = this.instruction_pointer & ~0xFFF;
-    }
-
-    return this.eip_phys ^ this.instruction_pointer;
-};
-
 CPU.prototype.read_imm8 = function()
 {
     if((this.instruction_pointer & ~0xFFF) ^ this.last_virt_eip)
@@ -2423,6 +2456,7 @@ CPU.prototype.do_task_switch = function(selector)
     this.writable_or_pagefault(tsr_offset, 0x66);
 
     //this.safe_write32(tsr_offset + TSR_CR3, this.cr[3]);
+
     this.safe_write32(tsr_offset + TSR_EIP, this.get_real_eip());
     this.safe_write32(tsr_offset + TSR_EFLAGS, old_eflags);
 
@@ -2457,6 +2491,7 @@ CPU.prototype.do_task_switch = function(selector)
 
     this.flags &= ~flag_vm;
 
+    dbg_assert(false);
     this.switch_seg(reg_cs, this.safe_read16(new_tsr_offset + TSR_CS));
 
     var new_eflags = this.safe_read32s(new_tsr_offset + TSR_EFLAGS);
@@ -2797,6 +2832,7 @@ CPU.prototype.read_write_e16 = function()
         this.phys_addr = this.translate_address_write(virt_addr);
         if(this.paging && (virt_addr & 0xFFF) === 0xFFF) {
             this.phys_addr_high = this.translate_address_write(virt_addr + 1 | 0);
+            dbg_assert(this.phys_addr_high);
             return this.virt_boundary_read16(this.phys_addr, this.phys_addr_high);
         } else {
             this.phys_addr_high = 0;
@@ -2826,8 +2862,8 @@ CPU.prototype.read_write_e32 = function()
         var virt_addr = this.modrm_resolve(this.modrm_byte);
         this.phys_addr = this.translate_address_write(virt_addr);
         if(this.paging && (virt_addr & 0xFFF) >= 0xFFD) {
-
             this.phys_addr_high = this.translate_address_write(virt_addr + 3 | 0);
+            dbg_assert(this.phys_addr_high);
             return this.virt_boundary_read32s(this.phys_addr, this.phys_addr_high);
         } else {
             this.phys_addr_high = 0;
@@ -2938,7 +2974,10 @@ CPU.prototype.device_raise_irq = function(i)
     }
 
     // XXX: This should be implemented by the devices themselves
-    this.device_lower_irq(i);
+    if(i !== 14 && i !== 15)
+    {
+        this.device_lower_irq(i);
+    }
 };
 
 CPU.prototype.device_lower_irq = function(i)
@@ -2963,6 +3002,8 @@ CPU.prototype.test_privileges_for_io = function(port, size)
 
         if(tsr_size >= 0x67)
         {
+            dbg_assert((tsr_offset + 0x64 + 2 & 0xFFF) < 0xFFF);
+
             var iomap_base = this.memory.read16(this.translate_address_system_read(tsr_offset + 0x64 + 2 | 0)),
                 high_port = port + size - 1 | 0;
 
@@ -2973,6 +3014,8 @@ CPU.prototype.test_privileges_for_io = function(port, size)
                     port_info = (mask & 0xFF00) ?
                         this.memory.read16(addr) : this.memory.read8(addr);
 
+                dbg_assert((addr & 0xFFF) < 0xFFF);
+
                 if(!(port_info & mask))
                 {
                     return;
@@ -2981,6 +3024,7 @@ CPU.prototype.test_privileges_for_io = function(port, size)
         }
 
         dbg_log("#GP for port io  port=" + h(port) + " size=" + size, LOG_CPU);
+        this.debug.dump_state();
         this.trigger_gp(0);
     }
 };
@@ -3023,8 +3067,9 @@ CPU.prototype.cpuid = function()
             eax = 3 | 6 << 4 | 15 << 8;
             ebx = 1 << 16 | 8 << 8; // cpu count, clflush size
             ecx = 1 << 23 | 1 << 30; // popcnt, rdrand
+            var vme = 0 << 1;
             edx = (this.fpu ? 1 : 0) |                // fpu
-                    1 << 1 | 1 << 3 | 1 << 4 | 1 << 5 |   // vme, pse, tsc, msr
+                    vme | 1 << 3 | 1 << 4 | 1 << 5 |   // vme, pse, tsc, msr
                     1 << 8 | 1 << 11 | 1 << 13 | 1 << 15; // cx8, sep, pge, cmov
 
             if(ENABLE_ACPI)
@@ -3337,6 +3382,8 @@ CPU.prototype.switch_seg = function(reg, selector)
             (info.rpl > info.dpl || this.cpl > info.dpl))
         ) {
             dbg_log("#GP for loading invalid in seg " + reg + " sel=" + h(selector, 4), LOG_CPU);
+            this.debug.dump_state();
+            this.debug.dump_regs_short();
             dbg_trace(LOG_CPU);
             this.trigger_gp(selector & ~3);
         }
@@ -3353,13 +3400,7 @@ CPU.prototype.switch_seg = function(reg, selector)
     this.segment_limits[reg] = info.effective_limit;
     //this.segment_infos[reg] = 0; // TODO
 
-    //if(OP_TRANSLATION && (reg === reg_ds || reg === reg_ss) && info.base !== this.segment_offsets[reg])
-    //{
-    //    this.translator.clear_cache();
-    //}
-
     this.segment_offsets[reg] = info.base;
-
     this.sreg[reg] = selector;
 };
 
@@ -3368,7 +3409,7 @@ CPU.prototype.load_tr = function(selector)
     var info = this.lookup_segment_selector(selector);
 
     dbg_assert(info.is_valid);
-    dbg_log("load tr: " + h(selector, 4) + " offset=" + h(info.base >>> 0, 8) + " limit=" + h(info.effective_limit >>> 0, 8), LOG_CPU);
+    //dbg_log("load tr: " + h(selector, 4) + " offset=" + h(info.base >>> 0, 8) + " limit=" + h(info.effective_limit >>> 0, 8), LOG_CPU);
 
     if(!info.from_gdt)
     {
@@ -3459,7 +3500,7 @@ CPU.prototype.load_ldt = function(selector)
     this.segment_limits[reg_ldtr] = info.effective_limit;
     this.sreg[reg_ldtr] = selector;
 
-    //dbg_log("ldt at " + h(info.base) + "; (" + info.effective_limit + " bytes)");
+    //dbg_log("ldt at " + h(info.base >>> 0) + "; (" + info.effective_limit + " bytes)", LOG_CPU);
 };
 
 CPU.prototype.arpl = function(seg, r16)

+ 10 - 3
src/instructions.js

@@ -561,6 +561,7 @@ t16[0x9C] = cpu => {
     // pushf
     if((cpu.flags & flag_vm) && cpu.getiopl() < 3)
     {
+        dbg_assert(cpu.protected_mode);
         dbg_log("pushf #gp", LOG_CPU);
         cpu.trigger_gp(0);
     }
@@ -575,6 +576,7 @@ t32[0x9C] = cpu => {
     if((cpu.flags & flag_vm) && cpu.getiopl() < 3)
     {
         // trap to virtual 8086 monitor
+        dbg_assert(cpu.protected_mode);
         dbg_log("pushf #gp", LOG_CPU);
         cpu.trigger_gp(0);
     }
@@ -879,18 +881,21 @@ t32[0xCB] = cpu => {
 
 t[0xCC] = cpu => {
     // INT3
+    // TODO: inhibit iopl checks
+    dbg_log("INT3", LOG_CPU);
     cpu.call_interrupt_vector(3, true, false);
 };
 t[0xCD] = cpu => {
     // INT
     var imm8 = cpu.read_imm8();
-
     cpu.call_interrupt_vector(imm8, true, false);
 };
 t[0xCE] = cpu => {
     // INTO
+    dbg_log("INTO", LOG_CPU);
     if(cpu.getof())
     {
+        // TODO: inhibit iopl checks
         cpu.call_interrupt_vector(4, true, false);
     }
 };
@@ -1679,7 +1684,7 @@ t[0x01] = cpu => { cpu.modrm_byte = cpu.read_imm8();
             cpu.cr[0] |= CR0_PE;
         }
 
-        dbg_log("cr0=" + h(data >>> 0), LOG_CPU);
+        //dbg_log("cr0=" + h(data >>> 0), LOG_CPU);
         cpu.cr0_changed(old_cr0);
         return;
     }
@@ -1728,7 +1733,9 @@ t[0x01] = cpu => { cpu.modrm_byte = cpu.read_imm8();
             }
 
             //dbg_log("gdt at " + h(cpu.gdtr_offset) + ", " + cpu.gdtr_size + " bytes", LOG_CPU);
-            //dump_gdt_ldt();
+            //cpu.debug.dump_state();
+            //cpu.debug.dump_regs_short();
+            //cpu.debug.dump_gdt_ldt();
             break;
         case 3:
             // lidt

+ 2 - 2
src/io.js

@@ -385,7 +385,7 @@ IO.prototype.port_read8 = function(port_addr)
         );
     }
     var value = entry.read8.call(entry.device);
-    dbg_assert(value < 0x100);
+    dbg_assert(value < 0x100, "8 bit port returned large value: " + h(port_addr));
     return value;
 };
 
@@ -401,7 +401,7 @@ IO.prototype.port_read16 = function(port_addr)
         );
     }
     var value = entry.read16.call(entry.device);
-    dbg_assert(value < 0x10000);
+    dbg_assert(value < 0x10000, "16 bit port returned large value: " + h(port_addr));
     return value;
 };
 

+ 1 - 1
src/pit.js

@@ -251,7 +251,7 @@ PIT.prototype.port43_write = function(reg_byte)
         // latch
         this.counter_latch[i] = 2;
         var value = this.get_counter_value(i, v86.microtick());
-        dbg_log("pit latch: " + value, LOG_PIT);
+        dbg_log("latch: " + value, LOG_PIT);
         this.counter_latch_value[i] = value ? value - 1 : 0
 
         return;

+ 1 - 1
src/state.js

@@ -130,8 +130,8 @@ function restore_object(base, obj, buffers)
 
         var info = buffers.infos[obj["buffer_id"]];
 
-        dbg_assert(base.constructor === constructor);
         dbg_assert(base);
+        dbg_assert(base.constructor === constructor);
 
         // restore large buffers by just returning a view on the state blob
         if(info.length >= 1024 * 1024 && constructor === Uint8Array)