port scas*

This commit is contained in:
Awal Garg 2017-08-02 19:09:03 +05:30 committed by Fabian
parent 96dfe623a2
commit c8b7c1edf4
3 changed files with 220 additions and 3 deletions

View file

@ -200,9 +200,6 @@ function V86Starter(options)
"_outsb": function() { return cpu.outsb.apply(cpu, arguments); },
"_outsw": function() { return cpu.outsw.apply(cpu, arguments); },
"_outsd": function() { return cpu.outsd.apply(cpu, arguments); },
"_scasb": function() { return cpu.scasb.apply(cpu, arguments); },
"_scasw": function() { return cpu.scasw.apply(cpu, arguments); },
"_scasd": function() { return cpu.scasd.apply(cpu, arguments); },
"_lss16": function() { return cpu.lss16.apply(cpu, arguments); },
"_lss32": function() { return cpu.lss32.apply(cpu, arguments); },
"_enter16": function() { return cpu.enter16.apply(cpu, arguments); },

View file

@ -359,6 +359,9 @@ CPU.prototype.wasm_patch = function(wm)
this.lodsb = this.wm.funcs['_lodsb'];
this.lodsw = this.wm.funcs['_lodsw'];
this.lodsd = this.wm.funcs['_lodsd'];
this.scasb = this.wm.funcs['_scasb'];
this.scasw = this.wm.funcs['_scasw'];
this.scasd = this.wm.funcs['_scasd'];
};
CPU.prototype.get_state = function()

View file

@ -834,3 +834,220 @@ void lodsd()
}
}
void scasb_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
int32_t data_dest;
int32_t data_src = reg8[AL];
int32_t count = get_reg_asize(ECX) >> 0;
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ;
int32_t cycle_counter = MAX_COUNT_PER_CYCLE;
int32_t phys_dest = translate_address_read(dest);
if(*paging)
{
cycle_counter = string_get_cycle_count(size, dest);
}
do
{
data_dest = read8(phys_dest);
phys_dest += size;
cont = --count != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
set_ecx_asize(count);
*timestamp_counter += start_count - count;
if(cont)
{
*instruction_pointer = *previous_ip;
}
cmp8(data_src, data_dest);
diverged();
}
void scasb_no_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
int32_t data_dest;
int32_t data_src = reg8[AL];
data_dest = safe_read8(dest);
add_reg_asize(EDI, size);
cmp8(data_src, data_dest);
diverged();
}
void scasb()
{
if(*prefixes & PREFIX_MASK_REP)
{
scasb_rep();
}
else
{
scasb_no_rep();
}
}
void scasw_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
int32_t data_dest;
int32_t data_src = reg16[AL];
int32_t count = get_reg_asize(ECX) >> 0;
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ;
int32_t cycle_counter = MAX_COUNT_PER_CYCLE;
if(!(dest & 1))
{
int32_t single_size = size < 0 ? -1 : 1;
int32_t phys_dest = translate_address_read(dest) >> 1;
if(*paging)
{
cycle_counter = string_get_cycle_count(size, dest);
}
do
{
data_dest = read_aligned16(phys_dest);
phys_dest += single_size;
cont = --count != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
set_ecx_asize(count);
*timestamp_counter += start_count - count;
}
else
{
do
{
data_dest = safe_read16(dest);
dest += size;
add_reg_asize(EDI, size);
cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
}
if(cont)
{
*instruction_pointer = *previous_ip;
}
cmp16(data_src, data_dest);
diverged();
}
void scasw_no_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
int32_t data_dest;
int32_t data_src = reg16[AL];
data_dest = safe_read16(dest);
add_reg_asize(EDI, size);
cmp16(data_src, data_dest);
diverged();
}
void scasw()
{
if(*prefixes & PREFIX_MASK_REP)
{
scasw_rep();
}
else
{
scasw_no_rep();
}
}
void scasd_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
int32_t data_dest;
int32_t data_src = reg32s[EAX];
int32_t count = get_reg_asize(ECX) >> 0;
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ;
int32_t cycle_counter = MAX_COUNT_PER_CYCLE;
if(!(dest & 3))
{
int32_t single_size = size < 0 ? -1 : 1;
int32_t phys_dest = translate_address_read(dest) >> 2;
if(*paging)
{
cycle_counter = string_get_cycle_count(size, dest);
}
do
{
data_dest = read_aligned32(phys_dest);
phys_dest += single_size;
cont = --count != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
set_ecx_asize(count);
*timestamp_counter += start_count - count;
}
else
{
do
{
data_dest = safe_read32s(dest);
dest += size;
add_reg_asize(EDI, size);
cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
}
if(cont)
{
*instruction_pointer = *previous_ip;
}
cmp32(data_src, data_dest);
diverged();
}
void scasd_no_rep()
{
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
int32_t data_dest;
int32_t data_src = reg32s[EAX];
data_dest = safe_read32s(dest);
add_reg_asize(EDI, size);
cmp32(data_src, data_dest);
diverged();
}
void scasd()
{
if(*prefixes & PREFIX_MASK_REP)
{
scasd_rep();
}
else
{
scasd_no_rep();
}
}