History

Implement second level of fixed point op-codes. Fix bug in exec when no arguments provided.

arr committed 10 years ago

Commit 9af40931 parent a9ef3115 files · +137 −29Browse files

Showing the changes to src/vm/execution_table.cpp (1 of 5 files). Show all

Unified · Split

src/vm/execution_table.cpp+129−22
@@ -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 else116 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 codes346 // [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 else365 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 else416 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 else1517 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,