port bt*,bs*,popcnt,saturate*
This commit is contained in:
parent
3140cce77f
commit
6d8b086231
|
@ -156,6 +156,8 @@ function V86Starter(options)
|
|||
"_fpu_op_DF_mem": function() { return cpu.fpu.op_DF_mem.apply(cpu.fpu, arguments); },
|
||||
"_fwait": function() { return cpu.fpu.fwait(); },
|
||||
|
||||
"_int_log2": function(val) { return v86util.int_log2(val); },
|
||||
|
||||
"_do_page_translation": function() { return cpu.do_page_translation.apply(cpu, arguments); },
|
||||
"_read_reg_e16": function() { return cpu.read_reg_e16.apply(cpu, arguments); },
|
||||
"_read_reg_e32s": function() { return cpu.read_reg_e32s.apply(cpu, arguments); },
|
||||
|
@ -173,20 +175,6 @@ function V86Starter(options)
|
|||
"_getiopl": function() { return cpu.getiopl.apply(cpu, arguments); },
|
||||
"_vm86_mode": function() { return cpu.vm86_mode.apply(cpu, arguments); },
|
||||
|
||||
"_bt_reg": function() { return cpu.bt_reg.apply(cpu, arguments); },
|
||||
"_bt_mem": function() { return cpu.bt_mem.apply(cpu, arguments); },
|
||||
"_btr_reg": function() { return cpu.btr_reg.apply(cpu, arguments); },
|
||||
"_btr_mem": function() { return cpu.btr_mem.apply(cpu, arguments); },
|
||||
"_btc_reg": function() { return cpu.btc_reg.apply(cpu, arguments); },
|
||||
"_btc_mem": function() { return cpu.btc_mem.apply(cpu, arguments); },
|
||||
"_bts_reg": function() { return cpu.bts_reg.apply(cpu, arguments); },
|
||||
"_bts_mem": function() { return cpu.bts_mem.apply(cpu, arguments); },
|
||||
|
||||
"_bsf16": function() { return cpu.bsf16.apply(cpu, arguments); },
|
||||
"_bsf32": function() { return cpu.bsf32.apply(cpu, arguments); },
|
||||
"_bsr16": function() { return cpu.bsr16.apply(cpu, arguments); },
|
||||
"_bsr32": function() { return cpu.bsr32.apply(cpu, arguments); },
|
||||
"_popcnt": function() { return cpu.popcnt.apply(cpu, arguments); },
|
||||
"_bswap": function() { return cpu.bswap.apply(cpu, arguments); },
|
||||
|
||||
"_lar": function() { return cpu.lar.apply(cpu, arguments); },
|
||||
|
|
21
src/cpu.js
21
src/cpu.js
|
@ -293,6 +293,27 @@ CPU.prototype.wasm_patch = function(wm)
|
|||
this.shld16 = this.wm.funcs['_shld16'];
|
||||
this.shld32 = this.wm.funcs['_shld32'];
|
||||
|
||||
this.bt_reg = this.wm.funcs['_bt_reg'];
|
||||
this.btc_reg = this.wm.funcs['_btc_reg'];
|
||||
this.bts_reg = this.wm.funcs['_bts_reg'];
|
||||
this.btr_reg = this.wm.funcs['_btr_reg'];
|
||||
this.bt_mem = this.wm.funcs['_bt_mem'];
|
||||
this.btc_mem = this.wm.funcs['_btc_mem'];
|
||||
this.btr_mem = this.wm.funcs['_btr_mem'];
|
||||
this.bts_mem = this.wm.funcs['_bts_mem'];
|
||||
this.bsf16 = this.wm.funcs['_bsf16'];
|
||||
this.bsf32 = this.wm.funcs['_bsf32'];
|
||||
this.bsr16 = this.wm.funcs['_bsr16'];
|
||||
this.bsr32 = this.wm.funcs['_bsr32'];
|
||||
this.popcnt = this.wm.funcs['_popcnt'];
|
||||
this.saturate_sw_to_ub = this.wm.funcs['_saturate_sw_to_ub'];
|
||||
this.saturate_sw_to_sb = this.wm.funcs['_saturate_sw_to_sb'];
|
||||
this.saturate_sd_to_sw = this.wm.funcs['_saturate_sd_to_sw'];
|
||||
this.saturate_sd_to_sb = this.wm.funcs['_saturate_sd_to_sb'];
|
||||
this.saturate_sd_to_ub = this.wm.funcs['_saturate_sd_to_ub'];
|
||||
this.saturate_ud_to_ub = this.wm.funcs['_saturate_ud_to_ub'];
|
||||
this.saturate_uw = this.wm.funcs['_saturate_uw'];
|
||||
|
||||
this.do_many_cycles_unsafe = this.wm.funcs['_do_many_cycles_unsafe'];
|
||||
|
||||
this.read_imm8 = this.wm.funcs['_read_imm8'];
|
||||
|
|
|
@ -1088,3 +1088,285 @@ int32_t shld32(int32_t dest_operand, int32_t source_operand, int32_t count)
|
|||
return *last_result;
|
||||
}
|
||||
|
||||
int32_t int_log2(int32_t);
|
||||
|
||||
void bt_reg(int32_t bit_base, int32_t bit_offset)
|
||||
{
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
}
|
||||
|
||||
int32_t btc_reg(int32_t bit_base, int32_t bit_offset)
|
||||
{
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
return bit_base ^ 1 << bit_offset;
|
||||
}
|
||||
|
||||
int32_t bts_reg(int32_t bit_base, int32_t bit_offset)
|
||||
{
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
return bit_base | 1 << bit_offset;
|
||||
}
|
||||
|
||||
int32_t btr_reg(int32_t bit_base, int32_t bit_offset)
|
||||
{
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
return bit_base & ~(1 << bit_offset);
|
||||
}
|
||||
|
||||
void bt_mem(int32_t virt_addr, int32_t bit_offset)
|
||||
{
|
||||
int32_t bit_base = safe_read8(virt_addr + (bit_offset >> 3) | 0);
|
||||
bit_offset &= 7;
|
||||
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
}
|
||||
|
||||
void btc_mem(int32_t virt_addr, int32_t bit_offset)
|
||||
{
|
||||
int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
|
||||
int32_t bit_base = read8(phys_addr);
|
||||
|
||||
bit_offset &= 7;
|
||||
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
write8(phys_addr, bit_base ^ 1 << bit_offset);
|
||||
}
|
||||
|
||||
void btr_mem(int32_t virt_addr, int32_t bit_offset)
|
||||
{
|
||||
int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
|
||||
int32_t bit_base = read8(phys_addr);
|
||||
|
||||
bit_offset &= 7;
|
||||
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
write8(phys_addr, bit_base & ~(1 << bit_offset));
|
||||
}
|
||||
|
||||
void bts_mem(int32_t virt_addr, int32_t bit_offset)
|
||||
{
|
||||
int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
|
||||
int32_t bit_base = read8(phys_addr);
|
||||
|
||||
bit_offset &= 7;
|
||||
|
||||
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
|
||||
*flags_changed &= ~1;
|
||||
|
||||
write8(phys_addr, bit_base | 1 << bit_offset);
|
||||
}
|
||||
|
||||
int32_t bsf16(int32_t old, int32_t bit_base)
|
||||
{
|
||||
*flags_changed = FLAGS_ALL & ~FLAG_ZERO;
|
||||
*last_op_size = OPSIZE_16;
|
||||
|
||||
if(bit_base == 0)
|
||||
{
|
||||
*flags |= FLAG_ZERO;
|
||||
*last_result = bit_base;
|
||||
|
||||
// not defined in the docs, but value doesn't change on my intel machine
|
||||
return old;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags &= ~FLAG_ZERO;
|
||||
|
||||
// http://jsperf.com/lowest-bit-index
|
||||
return *last_result = int_log2(-bit_base & bit_base);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t bsf32(int32_t old, int32_t bit_base)
|
||||
{
|
||||
*flags_changed = FLAGS_ALL & ~FLAG_ZERO;
|
||||
*last_op_size = OPSIZE_32;
|
||||
|
||||
if(bit_base == 0)
|
||||
{
|
||||
*flags |= FLAG_ZERO;
|
||||
*last_result = bit_base;
|
||||
|
||||
return old;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags &= ~FLAG_ZERO;
|
||||
|
||||
return *last_result = int_log2(((uint32_t) (-bit_base & bit_base)) >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t bsr16(int32_t old, int32_t bit_base)
|
||||
{
|
||||
*flags_changed = FLAGS_ALL & ~FLAG_ZERO;
|
||||
*last_op_size = OPSIZE_16;
|
||||
|
||||
if(bit_base == 0)
|
||||
{
|
||||
*flags |= FLAG_ZERO;
|
||||
*last_result = bit_base;
|
||||
|
||||
return old;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags &= ~FLAG_ZERO;
|
||||
|
||||
return *last_result = int_log2(bit_base);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t bsr32(int32_t old, int32_t bit_base)
|
||||
{
|
||||
*flags_changed = FLAGS_ALL & ~FLAG_ZERO;
|
||||
*last_op_size = OPSIZE_32;
|
||||
|
||||
if(bit_base == 0)
|
||||
{
|
||||
*flags |= FLAG_ZERO;
|
||||
*last_result = bit_base;
|
||||
|
||||
return old;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags &= ~FLAG_ZERO;
|
||||
return *last_result = int_log2(((uint32_t) bit_base) >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t popcnt(int32_t v)
|
||||
{
|
||||
*flags_changed = 0;
|
||||
*flags &= ~FLAGS_ALL;
|
||||
|
||||
if(v)
|
||||
{
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
||||
v = v - ((v >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags |= FLAG_ZERO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t saturate_sw_to_ub(uint32_t v)
|
||||
{
|
||||
dbg_assert((v & 0xFFFF0000) == 0);
|
||||
|
||||
uint32_t ret = v >> 0;
|
||||
if (ret >= 0x8000) {
|
||||
ret = 0;
|
||||
}
|
||||
else if (ret > 0xFF) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFFFF00) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t saturate_sw_to_sb(int32_t v)
|
||||
{
|
||||
dbg_assert((v & 0xFFFF0000) == 0);
|
||||
|
||||
int32_t ret = v;
|
||||
|
||||
if (ret > 0xFF80) {
|
||||
ret = ret & 0xFF;
|
||||
}
|
||||
else if (ret > 0x7FFF) {
|
||||
ret = 0x80;
|
||||
}
|
||||
else if (ret > 0x7F) {
|
||||
ret = 0x7F;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFFFF00) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t saturate_sd_to_sw(uint32_t v)
|
||||
{
|
||||
uint32_t ret = v >> 0;
|
||||
|
||||
if (ret > 0xFFFF8000) {
|
||||
ret = ret & 0xFFFF;
|
||||
}
|
||||
else if (ret > 0x7FFFFFFF) {
|
||||
ret = 0x8000;
|
||||
}
|
||||
else if (ret > 0x7FFF) {
|
||||
ret = 0x7FFF;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFF0000) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t saturate_sd_to_sb(uint32_t v)
|
||||
{
|
||||
uint32_t ret = v >> 0;
|
||||
|
||||
if (ret > 0xFFFFFF80) {
|
||||
ret = ret & 0xFF;
|
||||
}
|
||||
else if (ret > 0x7FFFFFFF) {
|
||||
ret = 0x80;
|
||||
}
|
||||
else if (ret > 0x7F) {
|
||||
ret = 0x7F;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFFFF00) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t saturate_sd_to_ub(int32_t v)
|
||||
{
|
||||
int32_t ret = v | 0;
|
||||
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFFFF00) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t saturate_ud_to_ub(uint32_t v)
|
||||
{
|
||||
uint32_t ret = v >> 0;
|
||||
|
||||
if (ret > 0xFF) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
|
||||
dbg_assert((ret & 0xFFFFFF00) == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t saturate_uw(int32_t v)
|
||||
{
|
||||
dbg_assert(v >= 0);
|
||||
return v > 0xFFFF ? 0xFFFF : v;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@ void jmpcc32(bool);
|
|||
void setcc(bool);
|
||||
void cpuid();
|
||||
|
||||
int32_t bt_mem(int32_t, int32_t);
|
||||
int32_t bt_reg(int32_t, int32_t);
|
||||
int32_t bts_mem(int32_t, int32_t);
|
||||
void bt_mem(int32_t, int32_t);
|
||||
void bt_reg(int32_t, int32_t);
|
||||
void bts_mem(int32_t, int32_t);
|
||||
int32_t bts_reg(int32_t, int32_t);
|
||||
int32_t btc_mem(int32_t, int32_t);
|
||||
void btc_mem(int32_t, int32_t);
|
||||
int32_t btc_reg(int32_t, int32_t);
|
||||
int32_t btr_mem(int32_t, int32_t);
|
||||
void btr_mem(int32_t, int32_t);
|
||||
int32_t btr_reg(int32_t, int32_t);
|
||||
int32_t bsf16(int32_t, int32_t);
|
||||
int32_t bsf32(int32_t, int32_t);
|
||||
|
|
Loading…
Reference in a new issue