Enable fpu instructions in nasm tests
This commit is contained in:
parent
bb0e58ace9
commit
05296b0586
|
@ -273,6 +273,78 @@ const encodings = [
|
|||
// XXX: Temporary block boundary
|
||||
{ opcode: 0xD7, skip: 1, block_boundary: 1, },
|
||||
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD8, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv (only memory). TODO: Make reg variant non-block-boundary
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg)
|
||||
{ opcode: 0xD9, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem
|
||||
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // unimplemented: fisttp (sse3)
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: Test should fail
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3)
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
// loop, jcxz, etc.
|
||||
// Conditional jumps, but condition code not supported by code generator
|
||||
// (these are never generated by modern compilers)
|
||||
|
@ -722,7 +794,7 @@ const encodings = [
|
|||
{ sse: 1, opcode: 0x660F75, e: 1, },
|
||||
{ sse: 1, opcode: 0x0F76, e: 1, },
|
||||
{ sse: 1, opcode: 0x660F76, e: 1, },
|
||||
{ sse: 1, opcode: 0x0F77 },
|
||||
{ sse: 1, opcode: 0x0F77, skip: 1 }, // emms (skip as it breaks gdb printing of float registers)
|
||||
|
||||
// vmx instructions
|
||||
{ opcode: 0x0F78, skip: 1, block_boundary: 1, },
|
||||
|
@ -892,15 +964,6 @@ for(let i = 0; i < 8; i++)
|
|||
{ opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, },
|
||||
{ opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, },
|
||||
{ opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, },
|
||||
|
||||
{ opcode: 0xD8, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xD9, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDA, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDC, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, },
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -290,6 +290,9 @@ CPU.prototype.wasm_patch = function(wm)
|
|||
|
||||
this.set_stack_reg = get_import("set_stack_reg");
|
||||
|
||||
this.fpu_load_tag_word = get_import("fpu_load_tag_word");
|
||||
this.fpu_load_status_word = get_import("fpu_load_status_word");
|
||||
|
||||
this.translate_address_read = get_import("translate_address_read_js");
|
||||
this.translate_address_system_read = get_import("translate_address_system_read_js");
|
||||
this.translate_address_system_write = get_import("translate_address_system_write_js");
|
||||
|
|
|
@ -188,7 +188,7 @@ function create_nasm(op, config)
|
|||
codes.push("mov " + reg + ", " + rand);
|
||||
}
|
||||
|
||||
if(true) // generate random mmx registers
|
||||
if(!op.is_fpu) // generate random mmx registers
|
||||
{
|
||||
codes.push("sub esp, 8");
|
||||
for(let i = 0; i < 8; i++)
|
||||
|
@ -199,6 +199,25 @@ function create_nasm(op, config)
|
|||
}
|
||||
codes.push("add esp, 8");
|
||||
}
|
||||
else // generate random fpu registers
|
||||
{
|
||||
codes.push("finit");
|
||||
codes.push("sub esp, 8");
|
||||
|
||||
for(let i = 0; i < 8; i++)
|
||||
{
|
||||
codes.push("mov dword [esp], " + op_rand.next());
|
||||
codes.push("mov dword [esp + 4], " + op_rand.next());
|
||||
codes.push("fld qword [esp]");
|
||||
}
|
||||
|
||||
for(let i = 0; i < 4; i++) // half full stack
|
||||
{
|
||||
codes.push("fstp qword [esp]");
|
||||
}
|
||||
|
||||
codes.push("add esp, 8");
|
||||
}
|
||||
|
||||
if(true) // generate random xmm registers
|
||||
{
|
||||
|
@ -294,24 +313,21 @@ function create_nasm(op, config)
|
|||
g = op.fixed_g;
|
||||
}
|
||||
|
||||
let e;
|
||||
let sib;
|
||||
|
||||
if(config.mem)
|
||||
{
|
||||
e = 0x04; // [esp]
|
||||
sib = 0x24;
|
||||
const e = 0x04; // [esp]
|
||||
const sib = 0x24;
|
||||
|
||||
codes.push("db " + (e | g << 3));
|
||||
codes.push("db " + sib);
|
||||
}
|
||||
else // op.only_mem
|
||||
{
|
||||
e = 0xc2; // edx
|
||||
sib = "<invalid>";
|
||||
}
|
||||
|
||||
codes.push("db " + (e | g << 3));
|
||||
if(e < 0xC0)
|
||||
{
|
||||
codes.push("db " + sib);
|
||||
const es = op.is_fpu ? [0, 1, 2, 3, 4, 5, 6, 7] : [
|
||||
2 // edx
|
||||
];
|
||||
const modrm_bytes = es.map(e => "db " + (0xC0 | g << 3 | e));
|
||||
codes.push(modrm_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,52 @@ define extract-state
|
|||
printf " %d,\n", $ebp
|
||||
printf " %d,\n", $esi
|
||||
printf " %d,\n", $edi
|
||||
|
||||
printf " \n"
|
||||
|
||||
# For fpu registers, check the tag register first. If the tag index is
|
||||
# invalid and you try to access to corresponding register, gdb exits with an
|
||||
# error.
|
||||
if ($ftag & (3 << 0)) != (2 << 0)
|
||||
printf " %.100e,\n", $st0
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 2)) != (2 << 2)
|
||||
printf " %.100e,\n", $st1
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 4)) != (2 << 4)
|
||||
printf " %.100e,\n", $st2
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 6)) != (2 << 6)
|
||||
printf " %.100e,\n", $st3
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 8)) != (2 << 8)
|
||||
printf " %.100e,\n", $st4
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 10)) != (2 << 10)
|
||||
printf " %.100e,\n", $st5
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 12)) != (2 << 12)
|
||||
printf " %.100e,\n", $st6
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
if ($ftag & (3 << 14)) != (2 << 14)
|
||||
printf " %.100e,\n", $st7
|
||||
else
|
||||
printf " \"invalid\","
|
||||
end
|
||||
printf " \n"
|
||||
|
||||
printf " %d,\n", $mm0.v2_int32[0]
|
||||
|
@ -97,7 +143,9 @@ define extract-state
|
|||
printf " %d,\n", *(int*)($STACK_TOP-4)
|
||||
printf " \n"
|
||||
|
||||
printf " %d\n", $eflags
|
||||
printf " %d,\n", $eflags
|
||||
printf " %d,\n", $ftag
|
||||
printf " %d\n", $fstat
|
||||
|
||||
printf "]\n"
|
||||
printf "---END JSON---\n"
|
||||
|
|
|
@ -31,7 +31,16 @@ const TERMINATE_MSG = "DONE";
|
|||
|
||||
const FORCE_JIT = process.argv.includes("--force-jit");
|
||||
|
||||
// alternative representation for infinity for json
|
||||
const JSON_POS_INFINITY = "+INFINITY";
|
||||
const JSON_NEG_INFINITY = "-INFINITY";
|
||||
const JSON_POS_NAN = "+NAN";
|
||||
const JSON_NEG_NAN = "-NAN";
|
||||
|
||||
const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11;
|
||||
const FPU_TAG_ALL_INVALID = 0xAAAA;
|
||||
const FPU_STATUS_MASK = 0xFFFF & ~(1 << 9 | 1 << 5 | 1 << 3); // bits that are not correctly implemented by v86
|
||||
const FP_COMPARISON_SIGNIFICANT_DIGITS = 7;
|
||||
|
||||
try {
|
||||
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
|
||||
|
@ -43,6 +52,39 @@ catch(e) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
function float_equal(x, y)
|
||||
{
|
||||
console.assert(typeof x === "number");
|
||||
console.assert(typeof y === "number");
|
||||
|
||||
if(x === Infinity && y === Infinity || x === -Infinity && y === -Infinity || isNaN(x) && isNaN(y))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const epsilon = Math.pow(10, -FP_COMPARISON_SIGNIFICANT_DIGITS);
|
||||
return Math.abs(x - y) < epsilon;
|
||||
}
|
||||
|
||||
function format_value(v)
|
||||
{
|
||||
if(typeof v === "number")
|
||||
{
|
||||
if((v >>> 0) !== v)
|
||||
{
|
||||
return String(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "0x" + (v >>> 0).toString(16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return String(v);
|
||||
}
|
||||
}
|
||||
|
||||
if(cluster.isMaster)
|
||||
{
|
||||
function extract_json(name, fixture_text)
|
||||
|
@ -67,7 +109,13 @@ if(cluster.isMaster)
|
|||
throw new Error("Test was killed during execution by gdb: " + name + "\n" + fixture_text);
|
||||
}
|
||||
|
||||
const json_regex = /---BEGIN JSON---([\s\[\]\w":\-,]*)---END JSON---/;
|
||||
fixture_text = fixture_text.toString()
|
||||
.replace(/-inf\b/g, JSON.stringify(JSON_NEG_INFINITY))
|
||||
.replace(/\binf\b/g, JSON.stringify(JSON_POS_INFINITY))
|
||||
.replace(/-nan\b/g, JSON.stringify(JSON_NEG_NAN))
|
||||
.replace(/\bnan\b/g, JSON.stringify(JSON_POS_NAN));
|
||||
|
||||
const json_regex = /---BEGIN JSON---([\s\[\]\.\+\w":\-,]*)---END JSON---/;
|
||||
const regex_match = json_regex.exec(fixture_text);
|
||||
if (!regex_match || regex_match.length < 2) {
|
||||
throw new Error("Could not find JSON in fixture text: " + fixture_text + "\nTest: " + name);
|
||||
|
@ -180,15 +228,9 @@ if(cluster.isMaster)
|
|||
console.error("\n[-] %s:", test_failure.img_name);
|
||||
|
||||
test_failure.failures.forEach(function(failure) {
|
||||
function format_value(v) {
|
||||
if(typeof v === "number")
|
||||
return "0x" + (v >>> 0).toString(16);
|
||||
else
|
||||
return String(v);
|
||||
}
|
||||
console.error("\n\t" + failure.name);
|
||||
console.error("\tActual: " + format_value(failure.actual));
|
||||
console.error("\tExpected: " + format_value(failure.expected));
|
||||
console.error("\tActual: " + failure.actual);
|
||||
console.error("\tExpected: " + failure.expected);
|
||||
});
|
||||
});
|
||||
process.exit(1);
|
||||
|
@ -300,23 +342,36 @@ else {
|
|||
emulator.stop();
|
||||
var cpu = emulator.v86.cpu;
|
||||
|
||||
const filename = TEST_DIR + current_test.img_name;
|
||||
const evaluated_fpu_regs = new Float64Array(8).map((_, i) => cpu.fpu_st[i + cpu.fpu_stack_ptr[0] & 7]);
|
||||
const evaluated_mmxs = cpu.reg_mmxs;
|
||||
const evaluated_xmms = cpu.reg_xmm32s;
|
||||
const esp = cpu.reg32s[4];
|
||||
const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer);
|
||||
const evaluated_fpu_tag = cpu.fpu_load_tag_word();
|
||||
const evaluated_fpu_status = cpu.fpu_load_status_word() & FPU_STATUS_MASK;
|
||||
|
||||
let individual_failures = [];
|
||||
|
||||
console.assert(current_test.fixture.array || current_test.fixture.exception);
|
||||
|
||||
const FLOAT_TRANSLATION = {
|
||||
[JSON_POS_INFINITY]: Infinity,
|
||||
[JSON_NEG_INFINITY]: -Infinity,
|
||||
[JSON_POS_NAN]: NaN,
|
||||
[JSON_NEG_NAN]: NaN, // XXX: Ignore sign of NaN
|
||||
};
|
||||
|
||||
if(current_test.fixture.array)
|
||||
{
|
||||
let offset = 0;
|
||||
const expected_reg32s = current_test.fixture.array.slice(offset, offset += 8);
|
||||
const expected_fpu_regs =
|
||||
current_test.fixture.array.slice(offset, offset += 8) .map(x => x in FLOAT_TRANSLATION ? FLOAT_TRANSLATION[x] : x);
|
||||
const expected_mmx_registers = current_test.fixture.array.slice(offset, offset += 16);
|
||||
const expected_xmm_registers = current_test.fixture.array.slice(offset, offset += 32);
|
||||
const expected_memory = current_test.fixture.array.slice(offset, offset += 16);
|
||||
const expected_eflags = current_test.fixture.array[offset] & MASK_ARITH;
|
||||
const expected_eflags = current_test.fixture.array[offset++] & MASK_ARITH;
|
||||
const fpu_tag = current_test.fixture.array[offset++];
|
||||
const fpu_status = current_test.fixture.array[offset++] & FPU_STATUS_MASK;
|
||||
|
||||
for (let i = 0; i < cpu.reg32s.length; i++) {
|
||||
let reg = cpu.reg32s[i];
|
||||
|
@ -329,15 +384,40 @@ else {
|
|||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < evaluated_mmxs.length; i++) {
|
||||
if (evaluated_mmxs[i] !== expected_mmx_registers[i]) {
|
||||
if(fpu_tag !== FPU_TAG_ALL_INVALID)
|
||||
{
|
||||
for (let i = 0; i < evaluated_fpu_regs.length; i++) {
|
||||
if (expected_fpu_regs[i] !== "invalid" &&
|
||||
!float_equal(evaluated_fpu_regs[i], expected_fpu_regs[i])) {
|
||||
individual_failures.push({
|
||||
name: "st" + i,
|
||||
expected: expected_fpu_regs[i],
|
||||
actual: evaluated_fpu_regs[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(fpu_status !== evaluated_fpu_status)
|
||||
{
|
||||
individual_failures.push({
|
||||
name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])",
|
||||
expected: expected_mmx_registers[i],
|
||||
actual: evaluated_mmxs[i],
|
||||
name: "fpu status word",
|
||||
expected: fpu_status,
|
||||
actual: evaluated_fpu_status,
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (let i = 0; i < evaluated_mmxs.length; i++) {
|
||||
if (evaluated_mmxs[i] !== expected_mmx_registers[i]) {
|
||||
individual_failures.push({
|
||||
name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])",
|
||||
expected: expected_mmx_registers[i],
|
||||
actual: evaluated_mmxs[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < evaluated_xmms.length; i++) {
|
||||
if (evaluated_xmms[i] !== expected_xmm_registers[i]) {
|
||||
|
@ -379,6 +459,14 @@ else {
|
|||
});
|
||||
}
|
||||
|
||||
individual_failures = individual_failures.map(({ name, actual, expected }) => {
|
||||
return {
|
||||
name,
|
||||
actual: format_value(actual),
|
||||
expected: format_value(expected),
|
||||
};
|
||||
});
|
||||
|
||||
recorded_exceptions = [];
|
||||
|
||||
if (individual_failures.length > 0) {
|
||||
|
|
Loading…
Reference in a new issue