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
105105 vt_ref<word_t>(r.dest) = static_cast<word_t>(f);
106106 }
107107
108+ // [SPEC] Op code for converting 'Fixed point' value to word_t
109+ // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html)
108110 EXEC_DECL(cvtxx)
109111 {
110− const auto p = vt_ref<word_t>(r.mid);
111− auto res = static_cast<big_t>(vt_ref<word_t>(r.src));
112− if (p >= 0)
113− res <<= p;
112+ const auto pow2_scale = vt_ref<word_t>(r.mid);
113+ auto res = big_t{ vt_ref<word_t>(r.src) };
114+ if (pow2_scale >= 0)
115+ res <<= pow2_scale;
114116 else
115− res >>= (-p);
117+ res >>= (-pow2_scale);
116118
117119 vt_ref<word_t>(r.dest) = static_cast<word_t>(res);
118120 }
119121
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+
120146 EXEC_DECL(cvtca)
121147 {
122148 dec_ref_count_and_free(at_val<vm_alloc_t>(r.dest));
@@ -320,33 +346,113 @@ namespace · 197 unmodified lines
320346 // [SPEC] 'Fixed point' op codes
321347 // Undocumented: (http://www.vitanuova.com/inferno/papers/dis.html)
322348 // 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
323356 EXEC_DECL(mulx)
324357 {
325358 const auto m = big_t{ vt_ref<word_t>(r.mid) };
326359 const auto s = big_t{ vt_ref<word_t>(r.src) };
327360 auto result = m * s;
328361
329− const auto p = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2());
330− if (p >= 0)
331− result <<= p;
362+ const auto pow2_scale = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2());
363+ if (pow2_scale >= 0)
364+ result <<= pow2_scale;
332365 else
333− result >>= (-p);
366+ result >>= (-pow2_scale);
334367
335368 vt_ref<word_t>(r.dest) = static_cast<word_t>(result);
336369 }
337370
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
338377 EXEC_DECL(divx)
339378 {
340− auto denom = big_t{ vt_ref<word_t>(r.mid) };
341− const auto p = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2());
342− if (p >= 0)
343− denom <<= p;
379+ auto numerator = big_t{ vt_ref<word_t>(r.mid) };
380+ const auto pow2_scale = *reinterpret_cast<word_t *>(r.stack.peek_frame()->fixed_point_register_2());
381+ if (pow2_scale >= 0)
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;
344416 else
345− denom >>= (-p);
417+ tmp >>= (-pow2_scale);
346418
347− const auto numerator = big_t{ vt_ref<word_t>(r.src) };
348− auto result = denom / numerator;
419+ const auto residual_scale = big_t{ *reinterpret_cast<word_t *>(frame->fixed_point_register_1()) };
420+ assert(residual_scale != 0);
349421
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;
350456 vt_ref<word_t>(r.dest) = static_cast<word_t>(result);
351457 }
352458
@@ -1397,14 +1503,16 @@ namespace · 1044 unmodified lines
13971503
13981504 if (r.module_ref->is_builtin_module())
13991505 {
1400− // Execute the built-in function, then return
14011506 const auto &inst = r.module_ref->code_section[function_pc];
14021507 assert(r.mp_base == nullptr && "Built-in modules shouldn't have module data (MP register)");
14031508
14041509 r.current_thread_state = vm_thread_state_t::release;
14051510 inst.native(r, vm);
14061511 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;
14081516 }
14091517 else
14101518 {
@@ -1477,7 +1585,6 @@ namespace · 66 unmodified lines
14771585
14781586 EXEC_DECL(exit)
14791587 {
1480− assert(false && "test failure");
14811588 r.current_thread_state = vm_thread_state_t::exiting;
14821589 }
14831590
@@ -1772,9 +1879,9 @@ const vm_exec_t disvm::runtime::vm_exec_table[static_cast<std::size_t>(opcode_t: · 288 unmodified lines
17721879 mulx,
17731880 divx,
17741881 cvtxx,
1775− notimpl, // mulx0,
1776− notimpl, // divx0,
1777− notimpl, // cvtxx0,
1882+ mulx0,
1883+ divx0,
1884+ cvtxx0,
17781885 notimpl, // mulx1,
17791886 notimpl, // divx1,
17801887 notimpl, // cvtxx1,