port bt*,bs*,popcnt,saturate*

This commit is contained in:
Awal Garg 2017-07-27 16:46:24 +05:30 committed by Fabian
parent 3140cce77f
commit 6d8b086231
4 changed files with 310 additions and 19 deletions

View file

@ -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); },

View file

@ -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'];

View file

@ -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;
}

View file

@ -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);