/*! \file test_dbt_interp.cpp * \brief Guest memory bounds checks for the RV64 interpreter route. * * mem_check() gates every guest read and write in dbt_interp.cpp. It used * to be `addr + len <= mem->size`, which is unsigned 64-bit arithmetic and * wraps: for an addr within len of UINT64_MAX the sum becomes a small * number, compares below size, and the caller then indexes mem->data with * the unwrapped addr (#1292). * * mem_check and the accessors are file-static, so this includes the * translation unit directly rather than linking against it. That is also * why there are no stubs here -- dbt_interp.cpp depends only on * dbt_interp.h, dbt_decoder.h and the standard library. * * The wrap cases are the ones that discriminate: every other case below * behaves identically under both the old and new check, so a run that * passes them all proves nothing on its own. Reverting mem_check to * `addr + len <= mem->size` must fail exactly the WRAP cases. */ // No standard headers here. dbt_interp.cpp already includes , // , , and , and pulling any of them in // alongside the engine source breaks in this arrangement. // Everything below uses only what the engine TU already provides. // #include "dbt_interp.cpp" static int g_pass = 0; static int g_fail = 0; static void expect(bool cond, const char *what) { if (cond) { g_pass++; } else { g_fail++; printf("FAIL: %s\n", what); } } // --------------------------------------------------------------- // FCVT.{W,WU,L,LU}.D conformance // --------------------------------------------------------------- // // This is deliberately NOT a differential test against the DBT. The // differential fuzzer in this directory compares the interpreter with the // translator and reports where they disagree, which by construction cannot // see anything they get wrong in the same way -- and two such bugs lived // here: every convert truncated instead of honouring the rounding mode, and // NaN converted to 0 rather than the destination type's maximum in the // unsigned forms. Both routes agreed, so the fuzzer called it clean. // // The expected values below therefore come from qemu-riscv64 running the // same instructions, not from either implementation in this tree. Do not // "fix" a failure here by copying what dbt_interp currently returns; that // discards the only independent opinion the test has. // // Columns are the five static rounding modes, in rm-field order: // RNE, RTZ, RDN, RUP, RMM. // struct fcvt_row_t { uint64_t in; // input double, as bits uint8_t sel; // rs2: 0=W 1=WU 2=L 3=LU uint64_t expect[5]; // by rounding mode }; static const fcvt_row_t FCVT_GOLDEN[] = { { 0x0000000000000000ULL, 0, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // +0.0 fcvt.w.d { 0x0000000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // +0.0 fcvt.wu.d { 0x0000000000000000ULL, 2, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // +0.0 fcvt.l.d { 0x0000000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // +0.0 fcvt.lu.d { 0x8000000000000000ULL, 0, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.0 fcvt.w.d { 0x8000000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.0 fcvt.wu.d { 0x8000000000000000ULL, 2, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.0 fcvt.l.d { 0x8000000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.0 fcvt.lu.d { 0x3FF0000000000000ULL, 0, { 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 1.0 fcvt.w.d { 0x3FF0000000000000ULL, 1, { 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 1.0 fcvt.wu.d { 0x3FF0000000000000ULL, 2, { 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 1.0 fcvt.l.d { 0x3FF0000000000000ULL, 3, { 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 1.0 fcvt.lu.d { 0xBFF0000000000000ULL, 0, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // -1.0 fcvt.w.d { 0xBFF0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -1.0 fcvt.wu.d { 0xBFF0000000000000ULL, 2, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // -1.0 fcvt.l.d { 0xBFF0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -1.0 fcvt.lu.d { 0x3FE0000000000000ULL, 0, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 0.5 fcvt.w.d { 0x3FE0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 0.5 fcvt.wu.d { 0x3FE0000000000000ULL, 2, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 0.5 fcvt.l.d { 0x3FE0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000001ULL } }, // 0.5 fcvt.lu.d { 0x3FF8000000000000ULL, 0, { 0x0000000000000002ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000002ULL } }, // 1.5 fcvt.w.d { 0x3FF8000000000000ULL, 1, { 0x0000000000000002ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000002ULL } }, // 1.5 fcvt.wu.d { 0x3FF8000000000000ULL, 2, { 0x0000000000000002ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000002ULL } }, // 1.5 fcvt.l.d { 0x3FF8000000000000ULL, 3, { 0x0000000000000002ULL, 0x0000000000000001ULL, 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000002ULL } }, // 1.5 fcvt.lu.d { 0x4004000000000000ULL, 0, { 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.5 fcvt.w.d { 0x4004000000000000ULL, 1, { 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.5 fcvt.wu.d { 0x4004000000000000ULL, 2, { 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.5 fcvt.l.d { 0x4004000000000000ULL, 3, { 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.5 fcvt.lu.d { 0x4004CCCCCCCCCCCDULL, 0, { 0x0000000000000003ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.6 fcvt.w.d { 0x4004CCCCCCCCCCCDULL, 1, { 0x0000000000000003ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.6 fcvt.wu.d { 0x4004CCCCCCCCCCCDULL, 2, { 0x0000000000000003ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.6 fcvt.l.d { 0x4004CCCCCCCCCCCDULL, 3, { 0x0000000000000003ULL, 0x0000000000000002ULL, 0x0000000000000002ULL, 0x0000000000000003ULL, 0x0000000000000003ULL } }, // 2.6 fcvt.lu.d { 0xC004000000000000ULL, 0, { 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL } }, // -2.5 fcvt.w.d { 0xC004000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2.5 fcvt.wu.d { 0xC004000000000000ULL, 2, { 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL } }, // -2.5 fcvt.l.d { 0xC004000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2.5 fcvt.lu.d { 0xC004CCCCCCCCCCCDULL, 0, { 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL } }, // -2.6 fcvt.w.d { 0xC004CCCCCCCCCCCDULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2.6 fcvt.wu.d { 0xC004CCCCCCCCCCCDULL, 2, { 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL } }, // -2.6 fcvt.l.d { 0xC004CCCCCCCCCCCDULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2.6 fcvt.lu.d { 0x400C000000000000ULL, 0, { 0x0000000000000004ULL, 0x0000000000000003ULL, 0x0000000000000003ULL, 0x0000000000000004ULL, 0x0000000000000004ULL } }, // 3.5 fcvt.w.d { 0x400C000000000000ULL, 1, { 0x0000000000000004ULL, 0x0000000000000003ULL, 0x0000000000000003ULL, 0x0000000000000004ULL, 0x0000000000000004ULL } }, // 3.5 fcvt.wu.d { 0x400C000000000000ULL, 2, { 0x0000000000000004ULL, 0x0000000000000003ULL, 0x0000000000000003ULL, 0x0000000000000004ULL, 0x0000000000000004ULL } }, // 3.5 fcvt.l.d { 0x400C000000000000ULL, 3, { 0x0000000000000004ULL, 0x0000000000000003ULL, 0x0000000000000003ULL, 0x0000000000000004ULL, 0x0000000000000004ULL } }, // 3.5 fcvt.lu.d { 0xBFE0000000000000ULL, 0, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFFULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFFULL } }, // -0.5 fcvt.w.d { 0xBFE0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.5 fcvt.wu.d { 0xBFE0000000000000ULL, 2, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFFULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFFULL } }, // -0.5 fcvt.l.d { 0xBFE0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -0.5 fcvt.lu.d { 0x7FF0000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // +inf fcvt.w.d { 0x7FF0000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // +inf fcvt.wu.d { 0x7FF0000000000000ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // +inf fcvt.l.d { 0x7FF0000000000000ULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // +inf fcvt.lu.d { 0xFFF0000000000000ULL, 0, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -inf fcvt.w.d { 0xFFF0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -inf fcvt.wu.d { 0xFFF0000000000000ULL, 2, { 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL } }, // -inf fcvt.l.d { 0xFFF0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -inf fcvt.lu.d { 0x7FF8000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // qNaN fcvt.w.d { 0x7FF8000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // qNaN fcvt.wu.d { 0x7FF8000000000000ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // qNaN fcvt.l.d { 0x7FF8000000000000ULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // qNaN fcvt.lu.d { 0xFFF8000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // -qNaN fcvt.w.d { 0xFFF8000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // -qNaN fcvt.wu.d { 0xFFF8000000000000ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // -qNaN fcvt.l.d { 0xFFF8000000000000ULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // -qNaN fcvt.lu.d { 0x7FF0000000000001ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // sNaN fcvt.w.d { 0x7FF0000000000001ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // sNaN fcvt.wu.d { 0x7FF0000000000001ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // sNaN fcvt.l.d { 0x7FF0000000000001ULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // sNaN fcvt.lu.d { 0x41DFFFFFFFC00000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31-1 fcvt.w.d { 0x41DFFFFFFFC00000ULL, 1, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31-1 fcvt.wu.d { 0x41DFFFFFFFC00000ULL, 2, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31-1 fcvt.l.d { 0x41DFFFFFFFC00000ULL, 3, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31-1 fcvt.lu.d { 0x41E0000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31 fcvt.w.d { 0x41E0000000000000ULL, 1, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // 2^31 fcvt.wu.d { 0x41E0000000000000ULL, 2, { 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL } }, // 2^31 fcvt.l.d { 0x41E0000000000000ULL, 3, { 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL, 0x0000000080000000ULL } }, // 2^31 fcvt.lu.d { 0xC1E0000000000000ULL, 0, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -2^31 fcvt.w.d { 0xC1E0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^31 fcvt.wu.d { 0xC1E0000000000000ULL, 2, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -2^31 fcvt.l.d { 0xC1E0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^31 fcvt.lu.d { 0xC1E0000000200000ULL, 0, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -2^31-1 fcvt.w.d { 0xC1E0000000200000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^31-1 fcvt.wu.d { 0xC1E0000000200000ULL, 2, { 0xFFFFFFFF7FFFFFFFULL, 0xFFFFFFFF7FFFFFFFULL, 0xFFFFFFFF7FFFFFFFULL, 0xFFFFFFFF7FFFFFFFULL, 0xFFFFFFFF7FFFFFFFULL } }, // -2^31-1 fcvt.l.d { 0xC1E0000000200000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^31-1 fcvt.lu.d { 0x41DFFFFFFFE00000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^31-0.5 fcvt.w.d { 0x41DFFFFFFFE00000ULL, 1, { 0xFFFFFFFF80000000ULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // 2^31-0.5 fcvt.wu.d { 0x41DFFFFFFFE00000ULL, 2, { 0x0000000080000000ULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x0000000080000000ULL, 0x0000000080000000ULL } }, // 2^31-0.5 fcvt.l.d { 0x41DFFFFFFFE00000ULL, 3, { 0x0000000080000000ULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x0000000080000000ULL, 0x0000000080000000ULL } }, // 2^31-0.5 fcvt.lu.d { 0x41EFFFFFFFE00000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^32-1 fcvt.w.d { 0x41EFFFFFFFE00000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 2^32-1 fcvt.wu.d { 0x41EFFFFFFFE00000ULL, 2, { 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL } }, // 2^32-1 fcvt.l.d { 0x41EFFFFFFFE00000ULL, 3, { 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL, 0x00000000FFFFFFFFULL } }, // 2^32-1 fcvt.lu.d { 0x41F0000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^32 fcvt.w.d { 0x41F0000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 2^32 fcvt.wu.d { 0x41F0000000000000ULL, 2, { 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL } }, // 2^32 fcvt.l.d { 0x41F0000000000000ULL, 3, { 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL, 0x0000000100000000ULL } }, // 2^32 fcvt.lu.d { 0x43E0000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^63 fcvt.w.d { 0x43E0000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 2^63 fcvt.wu.d { 0x43E0000000000000ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // 2^63 fcvt.l.d { 0x43E0000000000000ULL, 3, { 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL } }, // 2^63 fcvt.lu.d { 0xC3E0000000000000ULL, 0, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -2^63 fcvt.w.d { 0xC3E0000000000000ULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^63 fcvt.wu.d { 0xC3E0000000000000ULL, 2, { 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL } }, // -2^63 fcvt.l.d { 0xC3E0000000000000ULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -2^63 fcvt.lu.d { 0x43F0000000000000ULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 2^64 fcvt.w.d { 0x43F0000000000000ULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 2^64 fcvt.wu.d { 0x43F0000000000000ULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // 2^64 fcvt.l.d { 0x43F0000000000000ULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 2^64 fcvt.lu.d { 0x7E37E43C8800759CULL, 0, { 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL, 0x000000007FFFFFFFULL } }, // 1e300 fcvt.w.d { 0x7E37E43C8800759CULL, 1, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 1e300 fcvt.wu.d { 0x7E37E43C8800759CULL, 2, { 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL } }, // 1e300 fcvt.l.d { 0x7E37E43C8800759CULL, 3, { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } }, // 1e300 fcvt.lu.d { 0xFE37E43C8800759CULL, 0, { 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL, 0xFFFFFFFF80000000ULL } }, // -1e300 fcvt.w.d { 0xFE37E43C8800759CULL, 1, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -1e300 fcvt.wu.d { 0xFE37E43C8800759CULL, 2, { 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL } }, // -1e300 fcvt.l.d { 0xFE37E43C8800759CULL, 3, { 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL } }, // -1e300 fcvt.lu.d }; static int fcvt_halt_ecall(rv64_state_t *, void *) { return 1; } // Run one FCVT through the real interpreter and return the destination // register. A guest program rather than a direct call to the conversion // helper, so the decode, the rounding-mode field and the range checks are // all covered. static uint64_t run_one_fcvt(rv64_memory_t *mem, uint64_t in, uint8_t sel, uint8_t rm) { // Must fit a *signed* 12-bit immediate, because the address is built // with a single ADDI: 0x800 would encode as -2048 and every load would // come back zero, which reads as "the interpreter converted to 0". const uint64_t DATA = 0x400; memcpy(mem->data + DATA, &in, 8); // ADDI x9, x0, DATA ; FLD f1, 0(x9) ; FCVT x5, f1 ; ECALL const uint32_t code[4] = { (uint32_t)(0x13u | (9u << 7) | (0u << 12) | (0u << 15) | ((DATA & 0xFFFu) << 20)), (uint32_t)(0x07u | (1u << 7) | (3u << 12) | (9u << 15)), (uint32_t)(0xC2000000u | (5u << 7) | ((uint32_t)rm << 12) | (1u << 15) | ((uint32_t)sel << 20) | 0x53u), 0x00000073u }; memcpy(mem->data, code, sizeof(code)); rv64_state_t st; memset(&st, 0, sizeof(st)); st.pc = 0; st.x[2] = 0x40000; rv64_interp_run(&st, mem, fcvt_halt_ecall, nullptr); return st.x[5]; } static void test_fcvt_conformance(rv64_memory_t *mem) { static const char *RM_NAME[5] = { "rne", "rtz", "rdn", "rup", "rmm" }; static const char *CVT_NAME[4] = { "fcvt.w.d", "fcvt.wu.d", "fcvt.l.d", "fcvt.lu.d" }; const size_t n = sizeof(FCVT_GOLDEN) / sizeof(FCVT_GOLDEN[0]); char desc[160]; for (size_t i = 0; i < n; i++) { const fcvt_row_t &row = FCVT_GOLDEN[i]; for (uint8_t rm = 0; rm < 5; rm++) { uint64_t got = run_one_fcvt(mem, row.in, row.sel, rm); snprintf(desc, sizeof(desc), "%s %s in=0x%016llX -> 0x%016llX (got 0x%016llX)", CVT_NAME[row.sel], RM_NAME[rm], (unsigned long long)row.in, (unsigned long long)row.expect[rm], (unsigned long long)got); expect(got == row.expect[rm], desc); } } } int main() { printf("=== DBT interpreter guest memory bounds ===\n\n"); // A plain buffer rather than std::vector: this TU includes engine // source, whose headers collide with . // static const size_t SIZE = 1u << 20; // 1 MB guest image static uint8_t backing[SIZE]; memset(backing, 0xAB, SIZE); rv64_memory_t mem; mem.data = backing; mem.size = SIZE; // --- legitimate accesses still work (guards over-tightening) --- mem_write8(&mem, 0x1000, 0x5A); expect(mem_read8(&mem, 0x1000) == 0x5A, "in-range byte round-trips"); mem_write64(&mem, SIZE - 8, 0x0123456789ABCDEFull); expect(mem_read64(&mem, SIZE - 8) == 0x0123456789ABCDEFull, "8-byte access ending exactly at the limit is allowed"); expect(mem_check(&mem, SIZE, 0), "zero-length access at the limit is allowed"); expect(mem_check(&mem, 0, SIZE), "whole-image access is allowed"); // --- ordinary out-of-range is refused (unchanged by #1292) --- expect(!mem_check(&mem, SIZE - 7, 8), "8 bytes ending one past the limit is refused"); expect(!mem_check(&mem, SIZE + 4096, 8), "far out-of-range is refused"); expect(!mem_check(&mem, SIZE, 1), "one byte at the limit is refused"); // --- WRAP: the #1292 cases. These are the only ones that // discriminate against the pre-fix check. --- expect(!mem_check(&mem, 0xFFFFFFFFFFFFFFFFull, 2), "WRAP addr=2^64-1 len=2 must be refused"); expect(!mem_check(&mem, 0xFFFFFFFFFFFFFFFCull, 8), "WRAP addr=2^64-4 len=8 must be refused"); expect(!mem_check(&mem, 0xFFFFFFFFFFFFF000ull, 8192), "WRAP addr near 2^64 with a large len must be refused"); // A wrapping read must also return the safe value rather than index // the backing store, which is what the check exists to prevent. expect(mem_read8(&mem, 0xFFFFFFFFFFFFFFFFull) == 0, "WRAP read8 returns 0 rather than indexing out of bounds"); expect(mem_read64(&mem, 0xFFFFFFFFFFFFFFFCull) == 0, "WRAP read64 returns 0 rather than indexing out of bounds"); // A wrapping write must leave the image untouched. Byte 0 is the // one an unwrapped index would be most likely to reach. const uint8_t before = backing[0]; mem_write64(&mem, 0xFFFFFFFFFFFFFFFCull, 0xDEADBEEFDEADBEEFull); expect(backing[0] == before, "WRAP write64 must not modify guest memory"); // --- FCVT conformance against qemu-derived golden values --- memset(backing, 0, SIZE); test_fcvt_conformance(&mem); printf("\n=== dbt interp: %d passed, %d failed ===\n", g_pass, g_fail); return (g_fail > 0) ? 1 : 0; }