v86/src/memory.js

335 lines
6.8 KiB
JavaScript
Raw Normal View History

2013-11-06 01:12:55 +01:00
"use strict";
/** @const */
var A20_MASK = ~(1 << 20);
/** @const */
var A20_MASK16 = ~(1 << 20 - 1);
/** @const */
var A20_MASK32 = ~(1 << 20 - 2);
/** @const */
var USE_A20 = false;
2014-02-19 05:50:49 +01:00
// called by all memory reads and writes
2016-08-02 04:15:24 +02:00
CPU.prototype.debug_write = function(addr, size, value)
2014-02-19 05:50:49 +01:00
{
if(!DEBUG)
{
return;
}
2015-09-16 00:56:06 +02:00
dbg_assert(typeof value === "number" && !isNaN(value));
dbg_assert(value >= -0x80000000 && addr < 0x80000000);
2014-02-19 05:50:49 +01:00
this.debug_read(addr, size, true);
}
2015-09-15 21:58:40 +02:00
/**
* @param {boolean=} is_write
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.debug_read = function(addr, size, is_write)
2014-02-19 05:50:49 +01:00
{
if(!DEBUG)
{
return;
}
dbg_assert(typeof addr === "number");
dbg_assert(!isNaN(addr));
};
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_read8 = function(addr)
2014-02-19 05:50:49 +01:00
{
2014-07-14 21:33:40 +02:00
return this.memory_map_read8[addr >>> MMAP_BLOCK_BITS](addr);
};
2014-02-19 05:50:49 +01:00
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_write8 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
2014-07-14 21:33:40 +02:00
this.memory_map_write8[addr >>> MMAP_BLOCK_BITS](addr, value);
};
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_read16 = function(addr)
2014-07-14 21:33:40 +02:00
{
2014-11-01 13:56:06 +01:00
var fn = this.memory_map_read8[addr >>> MMAP_BLOCK_BITS];
return fn(addr) | fn(addr + 1 | 0) << 8;
2014-07-14 21:33:40 +02:00
};
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_write16 = function(addr, value)
2014-07-14 21:33:40 +02:00
{
2014-11-01 13:56:06 +01:00
var fn = this.memory_map_write8[addr >>> MMAP_BLOCK_BITS];
fn(addr, value & 0xFF);
fn(addr + 1 | 0, value >> 8 & 0xFF);
2014-07-14 21:33:40 +02:00
};
2014-02-19 05:50:49 +01:00
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_read32 = function(addr)
2014-02-19 05:50:49 +01:00
{
2014-07-14 21:33:40 +02:00
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
2014-02-19 05:50:49 +01:00
2014-07-14 21:33:40 +02:00
return this.memory_map_read32[aligned_addr](addr);
2014-02-19 05:50:49 +01:00
}
2016-08-02 04:15:24 +02:00
CPU.prototype.mmap_write32 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
2014-07-14 21:33:40 +02:00
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
2014-02-19 05:50:49 +01:00
2014-07-14 21:33:40 +02:00
this.memory_map_write32[aligned_addr](addr, value);
2014-02-19 05:50:49 +01:00
}
2016-08-02 04:15:24 +02:00
CPU.prototype.in_mapped_range = function(addr)
{
2016-08-02 04:15:24 +02:00
return addr < 0 || addr >= 0xA0000 && addr < 0xC0000 || addr >= this.memory_size;
};
2014-02-19 05:50:49 +01:00
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.read8 = function(addr)
2014-02-19 05:50:49 +01:00
{
this.debug_read(addr, 1);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2013-11-06 01:12:55 +01:00
if(this.in_mapped_range(addr))
2014-02-19 05:50:49 +01:00
{
return this.mmap_read8(addr);
}
else
{
2014-02-19 05:50:49 +01:00
return this.mem8[addr];
}
2014-02-19 05:50:49 +01:00
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.read16 = function(addr)
2014-02-19 05:50:49 +01:00
{
this.debug_read(addr, 2);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2013-11-06 01:12:55 +01:00
if(this.in_mapped_range(addr))
2013-11-06 01:12:55 +01:00
{
2014-07-14 21:33:40 +02:00
return this.mmap_read16(addr);
}
2014-02-19 05:50:49 +01:00
else
{
return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8;
2014-02-19 05:50:49 +01:00
}
};
2013-11-06 01:12:55 +01:00
2014-02-19 05:50:49 +01:00
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.read_aligned16 = function(addr)
2014-02-19 05:50:49 +01:00
{
2015-04-17 23:47:40 +02:00
dbg_assert(addr >= 0 && addr < 0x80000000);
2014-02-19 05:50:49 +01:00
this.debug_read(addr << 1, 2);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16;
2014-02-19 05:50:49 +01:00
if(this.in_mapped_range(addr << 1))
2014-02-19 05:50:49 +01:00
{
2014-07-14 21:33:40 +02:00
return this.mmap_read16(addr << 1);
2014-02-19 05:50:49 +01:00
}
else
{
2014-02-19 05:50:49 +01:00
return this.mem16[addr];
}
2014-02-19 05:50:49 +01:00
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.read32s = function(addr)
2014-02-19 05:50:49 +01:00
{
this.debug_read(addr, 4);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2013-11-06 01:12:55 +01:00
if(this.in_mapped_range(addr))
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
return this.mmap_read32(addr);
}
2014-02-19 05:50:49 +01:00
else
2013-11-06 01:12:55 +01:00
{
2015-09-15 21:58:40 +02:00
return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8 |
this.mem8[addr + 2 | 0] << 16 | this.mem8[addr + 3 | 0] << 24;
2014-02-19 05:50:49 +01:00
}
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.read_aligned32 = function(addr)
2014-02-19 05:50:49 +01:00
{
2015-04-17 23:47:40 +02:00
dbg_assert(addr >= 0 && addr < 0x40000000);
2014-02-19 05:50:49 +01:00
this.debug_read(addr << 2, 4);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32;
2014-02-19 05:50:49 +01:00
if(this.in_mapped_range(addr << 2))
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
return this.mmap_read32(addr << 2);
}
else
{
return this.mem32s[addr];
}
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
* @param {number} value
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.write8 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
this.debug_write(addr, 1, value);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2014-02-19 05:50:49 +01:00
var page = addr >>> MMAP_BLOCK_BITS;
2014-06-17 01:38:39 +02:00
2015-09-16 00:56:06 +02:00
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
if(this.in_mapped_range(addr))
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mmap_write8(addr, value);
}
else
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mem8[addr] = value;
}
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
* @param {number} value
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.write16 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
this.debug_write(addr, 2, value);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2014-02-19 05:50:49 +01:00
var page = addr >>> MMAP_BLOCK_BITS;
2014-06-17 01:38:39 +02:00
2015-09-16 00:56:06 +02:00
//if(OP_TRANSLATION)
//{
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
// this.mem_page_infos[addr + 1 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
//}
if(this.in_mapped_range(addr))
2013-11-06 01:12:55 +01:00
{
2014-07-14 21:33:40 +02:00
this.mmap_write16(addr, value);
2014-02-19 05:50:49 +01:00
}
else
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mem8[addr] = value;
this.mem8[addr + 1 | 0] = value >> 8;
2014-02-19 05:50:49 +01:00
}
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
* @param {number} value
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.write_aligned16 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
2015-04-17 23:47:40 +02:00
dbg_assert(addr >= 0 && addr < 0x80000000);
2014-02-19 05:50:49 +01:00
this.debug_write(addr << 1, 2, value);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16;
2014-02-19 05:50:49 +01:00
var page = addr >>> MMAP_BLOCK_BITS - 1;
2014-06-17 01:38:39 +02:00
2015-09-16 00:56:06 +02:00
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
if(this.in_mapped_range(addr << 1))
2013-11-06 01:12:55 +01:00
{
2014-07-14 21:33:40 +02:00
this.mmap_write16(addr << 1, value);
2014-02-19 05:50:49 +01:00
}
else
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mem16[addr] = value;
}
};
/**
2015-09-15 21:58:40 +02:00
* @param {number} addr
* @param {number} value
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.write32 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
this.debug_write(addr, 4, value);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
2014-02-19 05:50:49 +01:00
var page = addr >>> MMAP_BLOCK_BITS;
2014-06-17 01:38:39 +02:00
2015-09-16 00:56:06 +02:00
//if(OP_TRANSLATION)
//{
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
// this.mem_page_infos[addr + 3 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
//}
if(this.in_mapped_range(addr))
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mmap_write32(addr, value);
}
else
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mem8[addr] = value;
this.mem8[addr + 1 | 0] = value >> 8;
this.mem8[addr + 2 | 0] = value >> 16;
this.mem8[addr + 3 | 0] = value >> 24;
2014-02-19 05:50:49 +01:00
}
};
2016-08-02 04:15:24 +02:00
CPU.prototype.write_aligned32 = function(addr, value)
2014-02-19 05:50:49 +01:00
{
2015-04-17 23:47:40 +02:00
dbg_assert(addr >= 0 && addr < 0x40000000);
2014-02-19 05:50:49 +01:00
this.debug_write(addr << 2, 4, value);
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32;
2014-02-19 05:50:49 +01:00
var page = addr >>> MMAP_BLOCK_BITS - 2;
2014-06-17 01:38:39 +02:00
2015-09-15 21:58:40 +02:00
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
if(this.in_mapped_range(addr << 2))
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mmap_write32(addr << 2, value);
}
else
2013-11-06 01:12:55 +01:00
{
2014-02-19 05:50:49 +01:00
this.mem32s[addr] = value;
}
};
2013-11-06 01:12:55 +01:00
2014-02-19 05:50:49 +01:00
/**
* @param {Array.<number>|Uint8Array} blob
2015-09-15 21:58:40 +02:00
* @param {number} offset
2014-02-19 05:50:49 +01:00
*/
2016-08-02 04:15:24 +02:00
CPU.prototype.write_blob = function(blob, offset)
2014-02-19 05:50:49 +01:00
{
dbg_assert(blob && blob.length);
2014-02-19 05:50:49 +01:00
this.mem8.set(blob, offset);
2015-09-16 00:56:06 +02:00
//var page = offset >>> 12;
//var end = (offset + blob) >>> 12;
2015-09-16 00:56:06 +02:00
//if(OP_TRANSLATION)
//{
// for(; page <= end; page++)
// {
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
// }
//}
2014-02-19 05:50:49 +01:00
};
2013-11-06 01:12:55 +01:00
2014-02-19 05:50:49 +01:00
/**
* @param {Array.<number>|Int32Array} blob
* @param {number} offset
2014-02-19 05:50:49 +01:00
*/
CPU.prototype.write_blob32 = function(blob, offset)
2014-02-19 05:50:49 +01:00
{
dbg_assert(blob && blob.length);
this.mem32s.set(blob, offset);
2014-02-19 05:50:49 +01:00
};