Showing the changes to src/vm/execution_table.cpp (1 of 5 files). Show all
Unified · Split
| @@ -105,18 +105,44 @@ namespace · 104 unmodified lines | |||
| 105 | vt_ref<word_t>(r.dest) = static_cast<word_t>(f); | 105 | vt_ref<word_t>(r.dest) = static_cast<word_t>(f); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | // [SPEC] Op code for converting 'Fixed point' value to word_t | ||
| 109 | // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html) | ||
| 108 | EXEC_DECL(cvtxx) | 110 | EXEC_DECL(cvtxx) |
| 109 | { | 111 | { |
| 110 | const auto p = vt_ref<word_t>(r.mid); | 112 | const auto pow2_scale = vt_ref<word_t>(r.mid); |
| 111 | auto res = static_cast<big_t>(vt_ref<word_t>(r.src)); | 113 | auto res = big_t{ vt_ref<word_t>(r.src) }; |
| 112 | if (p >= 0) | 114 | if (pow2_scale >= 0) |
| 113 | res <<= p; | 115 | res <<= pow2_scale; |
| 114 | else | 116 | else |
| 115 | res >>= (-p); | 117 | res >>= (-pow2_scale); |
| 116 | 118 | ||
| 117 | vt_ref<word_t>(r.dest) = static_cast<word_t>(res); | 119 | vt_ref<word_t>(r.dest) = static_cast<word_t>(res); |
| 118 | } | 120 | } |
| 119 | 121 | ||
| 122 | // [SPEC] Op code for converting 'Fixed point' value to word_t | ||
| 123 | // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html) | ||
| 124 | EXEC_DECL(cvtxx0) | ||
| 125 | { | ||
| 126 | auto tmp = big_t{ vt_ref<word_t>(r.src) }; | ||
| 127 | if (tmp == 0) | ||
| 128 | { | ||
| 129 | vt_ref<word_t>(r.dest) = 0; | ||
| 130 | return; | ||
| 131 | } | ||
| 132 | |||
| 133 | const auto pow2_scale = vt_ref<word_t>(r.mid); | ||
| 134 | if (pow2_scale >= 0) | ||
| 135 | tmp <<= pow2_scale; | ||
| 136 | else | ||
| 137 | tmp >>= (-pow2_scale); | ||
| 138 | |||
| 139 | const auto residual_scale = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_1()); | ||
| 140 | assert(residual_scale != 0); | ||
| 141 | |||
| 142 | const auto result = tmp / residual_scale; | ||
| 143 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); | ||
| 144 | } | ||
| 145 | |||
| 120 | EXEC_DECL(cvtca) | 146 | EXEC_DECL(cvtca) |
| 121 | { | 147 | { |
| 122 | dec_ref_count_and_free(at_val<vm_alloc_t>(r.dest)); | 148 | dec_ref_count_and_free(at_val<vm_alloc_t>(r.dest)); |
| @@ -320,33 +346,113 @@ namespace · 197 unmodified lines | |||
| 320 | // [SPEC] 'Fixed point' op codes | 346 | // [SPEC] 'Fixed point' op codes |
| 321 | // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html) | 347 | // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html) |
| 322 | // Limbo reference: (http://www.vitanuova.com/inferno/papers/addendum.pdf) | 348 | // Limbo reference: (http://www.vitanuova.com/inferno/papers/addendum.pdf) |
| 349 | |||
| 350 | // Multiply for fixed point types with final scaling as a power of 2. | ||
| 351 | // mulx src1 src2 dst | ||
| 352 | // src1 - integer 1 | ||
| 353 | // src2 - integer 2 | ||
| 354 | // fpr_2 - result scaling factor (2^x) | ||
| 355 | // dest - result integer | ||
| 323 | EXEC_DECL(mulx) | 356 | EXEC_DECL(mulx) |
| 324 | { | 357 | { |
| 325 | const auto m = big_t{ vt_ref<word_t>(r.mid) }; | 358 | const auto m = big_t{ vt_ref<word_t>(r.mid) }; |
| 326 | const auto s = big_t{ vt_ref<word_t>(r.src) }; | 359 | const auto s = big_t{ vt_ref<word_t>(r.src) }; |
| 327 | auto result = m * s; | 360 | auto result = m * s; |
| 328 | 361 | ||
| 329 | const auto p = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2()); | 362 | const auto pow2_scale = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2()); |
| 330 | if (p >= 0) | 363 | if (pow2_scale >= 0) |
| 331 | result <<= p; | 364 | result <<= pow2_scale; |
| 332 | else | 365 | else |
| 333 | result >>= (-p); | 366 | result >>= (-pow2_scale); |
| 334 | 367 | ||
| 335 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); | 368 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); |
| 336 | } | 369 | } |
| 337 | 370 | ||
| 371 | // Division for fixed point types with final scaling as a power of 2. | ||
| 372 | // divx src1 src2 dst | ||
| 373 | // src1 - integer 1 | ||
| 374 | // src2 - integer 2 | ||
| 375 | // fpr_2 - result scaling factor (2^x) | ||
| 376 | // dest - result integer | ||
| 338 | EXEC_DECL(divx) | 377 | EXEC_DECL(divx) |
| 339 | { | 378 | { |
| 340 | auto denom = big_t{ vt_ref<word_t>(r.mid) }; | 379 | auto numerator = big_t{ vt_ref<word_t>(r.mid) }; |
| 341 | const auto p = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2()); | 380 | const auto pow2_scale = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2()); |
| 342 | if (p >= 0) | 381 | if (pow2_scale >= 0) |
| 343 | denom <<= p; | 382 | numerator <<= pow2_scale; |
| 383 | else | ||
| 384 | numerator >>= (-pow2_scale); | ||
| 385 | |||
| 386 | const auto denom = big_t{ vt_ref<word_t>(r.src) }; | ||
| 387 | if (denom == 0) | ||
| 388 | throw divide_by_zero{}; | ||
| 389 | |||
| 390 | const auto result = numerator / denom; | ||
| 391 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); | ||
| 392 | } | ||
| 393 | |||
| 394 | // mulx0 src1 src2 dst | ||
| 395 | // src1 - integer 1 | ||
| 396 | // src2 - integer 2 | ||
| 397 | // fpr_1 - residual factor | ||
| 398 | // fpr_2 - result scaling factor (2^x) | ||
| 399 | // dest - result integer | ||
| 400 | EXEC_DECL(mulx0) | ||
| 401 | { | ||
| 402 | const auto m = big_t{ vt_ref<word_t>(r.mid) }; | ||
| 403 | const auto s = big_t{ vt_ref<word_t>(r.src) }; | ||
| 404 | auto tmp = m * s; | ||
| 405 | |||
| 406 | if (m == 0 || s == 0) | ||
| 407 | { | ||
| 408 | vt_ref<word_t>(r.dest) = 0; | ||
| 409 | return; | ||
| 410 | } | ||
| 411 | |||
| 412 | const auto frame = r.stack.peek_frame(); | ||
| 413 | const auto pow2_scale = *reinterpret_cast<word_t *>(frame->fixed_point_register_2()); | ||
| 414 | if (pow2_scale >= 0) | ||
| 415 | tmp <<= pow2_scale; | ||
| 344 | else | 416 | else |
| 345 | denom >>= (-p); | 417 | tmp >>= (-pow2_scale); |
| 346 | 418 | ||
| 347 | const auto numerator = big_t{ vt_ref<word_t>(r.src) }; | 419 | const auto residual_scale = big_t{ *reinterpret_cast<word_t *>(frame->fixed_point_register_1()) }; |
| 348 | auto result = denom / numerator; | 420 | assert(residual_scale != 0); |
| 349 | 421 | ||
| 422 | const auto result = tmp / residual_scale; | ||
| 423 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); | ||
| 424 | } | ||
| 425 | |||
| 426 | // divx0 src1 src2 dst | ||
| 427 | // src1 - integer 1 | ||
| 428 | // src2 - integer 2 | ||
| 429 | // fpr_1 - residual factor | ||
| 430 | // fpr_2 - result scaling factor (2^x) | ||
| 431 | // dest - result integer | ||
| 432 | EXEC_DECL(divx0) | ||
| 433 | { | ||
| 434 | const auto m = big_t{ vt_ref<word_t>(r.mid) }; | ||
| 435 | const auto s = big_t{ vt_ref<word_t>(r.src) }; | ||
| 436 | if (s == 0) | ||
| 437 | throw divide_by_zero{}; | ||
| 438 | |||
| 439 | if (m == 0) | ||
| 440 | { | ||
| 441 | vt_ref<word_t>(r.dest) = 0; | ||
| 442 | return; | ||
| 443 | } | ||
| 444 | |||
| 445 | const auto frame = r.stack.peek_frame(); | ||
| 446 | const auto residual_scale = big_t{ *reinterpret_cast<word_t *>(frame->fixed_point_register_1()) }; | ||
| 447 | |||
| 448 | auto tmp = m * residual_scale; | ||
| 449 | const auto pow2_scale = *reinterpret_cast<word_t *>(frame->fixed_point_register_2()); | ||
| 450 | if (pow2_scale >= 0) | ||
| 451 | tmp <<= pow2_scale; | ||
| 452 | else | ||
| 453 | tmp >>= (-pow2_scale); | ||
| 454 | |||
| 455 | const auto result = tmp / s; | ||
| 350 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); | 456 | vt_ref<word_t>(r.dest) = static_cast<word_t>(result); |
| 351 | } | 457 | } |
| 352 | 458 | ||
| @@ -1397,14 +1503,16 @@ namespace · 1044 unmodified lines | |||
| 1397 | 1503 | ||
| 1398 | if (r.module_ref->is_builtin_module()) | 1504 | if (r.module_ref->is_builtin_module()) |
| 1399 | { | 1505 | { |
| 1400 | // Execute the built-in function, then return | ||
| 1401 | const auto &inst = r.module_ref->code_section[function_pc]; | 1506 | const auto &inst = r.module_ref->code_section[function_pc]; |
| 1402 | assert(r.mp_base == nullptr && "Built-in modules shouldn't have module data (MP register)"); | 1507 | assert(r.mp_base == nullptr && "Built-in modules shouldn't have module data (MP register)"); |
| 1403 | 1508 | ||
| 1404 | r.current_thread_state = vm_thread_state_t::release; | 1509 | r.current_thread_state = vm_thread_state_t::release; |
| 1405 | inst.native(r, vm); | 1510 | inst.native(r, vm); |
| 1406 | ret(r, vm); | 1511 | ret(r, vm); |
| 1407 | r.current_thread_state = vm_thread_state_t::running; | 1512 | |
| 1513 | // Only reset the thread if it is in the state set prior to native call. | ||
| 1514 | if (r.current_thread_state == vm_thread_state_t::release) | ||
| 1515 | r.current_thread_state = vm_thread_state_t::running; | ||
| 1408 | } | 1516 | } |
| 1409 | else | 1517 | else |
| 1410 | { | 1518 | { |
| @@ -1477,7 +1585,6 @@ namespace · 66 unmodified lines | |||
| 1477 | 1585 | ||
| 1478 | EXEC_DECL(exit) | 1586 | EXEC_DECL(exit) |
| 1479 | { | 1587 | { |
| 1480 | assert(false && "test failure"); | ||
| 1481 | r.current_thread_state = vm_thread_state_t::exiting; | 1588 | r.current_thread_state = vm_thread_state_t::exiting; |
| 1482 | } | 1589 | } |
| 1483 | 1590 | ||
| @@ -1772,9 +1879,9 @@ const vm_exec_t disvm::runtime::vm_exec_table[static_cast<std::size_t>(opcode_t: · 288 unmodified lines | |||
| 1772 | mulx, | 1879 | mulx, |
| 1773 | divx, | 1880 | divx, |
| 1774 | cvtxx, | 1881 | cvtxx, |
| 1775 | notimpl, // mulx0, | 1882 | mulx0, |
| 1776 | notimpl, // divx0, | 1883 | divx0, |
| 1777 | notimpl, // cvtxx0, | 1884 | cvtxx0, |
| 1778 | notimpl, // mulx1, | 1885 | notimpl, // mulx1, |
| 1779 | notimpl, // divx1, | 1886 | notimpl, // divx1, |
| 1780 | notimpl, // cvtxx1, | 1887 | notimpl, // cvtxx1, |