// // Dis VM // File: address_decoding.inc // Author: arr // // This file should only be used by the thread class // Decode source register template void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(false && "Unknown source addressing"); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::offset_indirect_fp); reg.src = reinterpret_cast(reinterpret_cast(reg.stack.peek_frame()->base()) + inst.source.register1); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::offset_indirect_mp); reg.src = reinterpret_cast(reinterpret_cast(reg.mp_base->get_allocation()) + inst.source.register1); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::offset_double_indirect_fp); const auto frame_offset = *reinterpret_cast(reinterpret_cast(reg.stack.peek_frame()->base()) + inst.source.register1); if (frame_offset != disvm::runtime::runtime_constants::nil) reg.src = reinterpret_cast(frame_offset + inst.source.register2); else reg.src = reinterpret_cast(disvm::runtime::runtime_constants::nil); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::offset_double_indirect_mp); const auto mp_offset = *reinterpret_cast(reinterpret_cast(reg.mp_base->get_allocation()) + inst.source.register1); if (mp_offset != disvm::runtime::runtime_constants::nil) reg.src = reinterpret_cast(mp_offset + inst.source.register2); else reg.src = reinterpret_cast(disvm::runtime::runtime_constants::nil); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::immediate); reg.src = reinterpret_cast(const_cast(&inst.source.register1)); } template<> void dec_src(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.source.mode == address_mode_t::none); #ifndef NDEBUG reg.src = nullptr; #endif } // Decode destination register template void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(false && "Unknown destination addressing"); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::offset_indirect_fp); reg.dest = reinterpret_cast(reinterpret_cast(reg.stack.peek_frame()->base()) + inst.destination.register1); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::offset_indirect_mp); reg.dest = reinterpret_cast(reinterpret_cast(reg.mp_base->get_allocation()) + inst.destination.register1); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::offset_double_indirect_fp); const auto frame_offset = *reinterpret_cast(reinterpret_cast(reg.stack.peek_frame()->base()) + inst.destination.register1); if (frame_offset != disvm::runtime::runtime_constants::nil) reg.dest = reinterpret_cast(frame_offset + inst.destination.register2); else reg.dest = reinterpret_cast(disvm::runtime::runtime_constants::nil); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::offset_double_indirect_mp); const auto mp_offset = *reinterpret_cast(reinterpret_cast(reg.mp_base->get_allocation()) + inst.destination.register1); if (mp_offset != disvm::runtime::runtime_constants::nil) reg.dest = reinterpret_cast(mp_offset + inst.destination.register2); else reg.dest = reinterpret_cast(disvm::runtime::runtime_constants::nil); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::immediate); reg.dest = reinterpret_cast(const_cast(&inst.destination.register1)); } template<> void dec_dest(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.destination.mode == address_mode_t::none); #ifndef NDEBUG reg.dest = nullptr; #endif } // Decode middle register template void dec_mid(const vm_exec_op_t &inst, vm_registers_t ®); template<> void dec_mid(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.middle.mode == address_mode_middle_t::small_offset_indirect_fp); reg.mid = reinterpret_cast(reinterpret_cast(reg.stack.peek_frame()->base()) + inst.middle.register1); } template<> void dec_mid(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.middle.mode == address_mode_middle_t::small_offset_indirect_mp); reg.mid = reinterpret_cast(reinterpret_cast(reg.mp_base->get_allocation()) + inst.middle.register1); } template<> void dec_mid(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.middle.mode == address_mode_middle_t::small_immediate); reg.mid = reinterpret_cast(const_cast(&inst.middle.register1)); } template<> void dec_mid(const vm_exec_op_t &inst, vm_registers_t ®) { assert(inst.middle.mode == address_mode_middle_t::none); // [SPEC] This is an undocumented expectation but required in many operations (e.g. i++). reg.mid = reg.dest; } template void da(const vm_exec_op_t &inst, vm_registers_t ®) { dec_src(inst, reg); dec_dest(inst, reg); dec_mid(inst, reg); } // // The elements' of the decode table were printed out using the following function. // //void print_decode_table() //{ //#define PRINT_CASE(c) case c: ::printf(#c); break; // // static const auto mid_mask = uint8_t{ 0xc0 }; // static const auto src_mask = uint8_t{ 0x38 }; // static const auto dest_mask = uint8_t{ 0x07 }; // // for (auto i = uint32_t{ 0 }; i <= uint8_t(~0); ++i) // { // ::printf("da<"); // const uint8_t mid = (i & mid_mask) >> 6; // switch (static_cast(mid)) // { // PRINT_CASE(address_mode_middle_t::none) // PRINT_CASE(address_mode_middle_t::small_immediate) // PRINT_CASE(address_mode_middle_t::small_offset_indirect_fp) // PRINT_CASE(address_mode_middle_t::small_offset_indirect_mp) // } // ::printf(","); // const uint8_t src = (i & src_mask) >> 3; // switch (static_cast(src)) // { // PRINT_CASE(address_mode_t::offset_indirect_mp) // PRINT_CASE(address_mode_t::offset_indirect_fp) // PRINT_CASE(address_mode_t::immediate) // PRINT_CASE(address_mode_t::none) // PRINT_CASE(address_mode_t::offset_double_indirect_mp) // PRINT_CASE(address_mode_t::offset_double_indirect_fp) // PRINT_CASE(address_mode_t::reserved_1) // PRINT_CASE(address_mode_t::reserved_2) // } // ::printf(","); // const uint8_t dest = (i & dest_mask); // switch (static_cast(dest)) // { // PRINT_CASE(address_mode_t::offset_indirect_mp) // PRINT_CASE(address_mode_t::offset_indirect_fp) // PRINT_CASE(address_mode_t::immediate) // PRINT_CASE(address_mode_t::none) // PRINT_CASE(address_mode_t::offset_double_indirect_mp) // PRINT_CASE(address_mode_t::offset_double_indirect_fp) // PRINT_CASE(address_mode_t::reserved_1) // PRINT_CASE(address_mode_t::reserved_2) // } // ::printf(">,\n"); // } // //#undef PRINT_CASE //} void(*decode_table[])(const vm_exec_op_t &, vm_registers_t &) = { da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, da, };