diff --git a/src/alloy/README.md b/src/alloy/README.md index f3b64bcc8..2cbe29fc6 100644 --- a/src/alloy/README.md +++ b/src/alloy/README.md @@ -26,5 +26,4 @@ A backend takes optimized IR and assembles an implementation-specific result. The backend is also responsible for executing the code it generates and supporting debugging features (such as breakpoints). -* IVM: bytecode interpreter * x64: IA-64 with AVX2 code generator diff --git a/src/alloy/backend/ivm/ivm_assembler.cc b/src/alloy/backend/ivm/ivm_assembler.cc deleted file mode 100644 index a79db653e..000000000 --- a/src/alloy/backend/ivm/ivm_assembler.cc +++ /dev/null @@ -1,124 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace alloy { -namespace backend { -namespace ivm { - -using alloy::hir::HIRBuilder; -using alloy::runtime::DebugInfo; -using alloy::runtime::Function; -using alloy::runtime::FunctionInfo; - -IVMAssembler::IVMAssembler(Backend* backend) - : Assembler(backend), source_map_arena_(128 * 1024) {} - -IVMAssembler::~IVMAssembler() = default; - -int IVMAssembler::Initialize() { - int result = Assembler::Initialize(); - if (result) { - return result; - } - - return result; -} - -void IVMAssembler::Reset() { - intcode_arena_.Reset(); - source_map_arena_.Reset(); - scratch_arena_.Reset(); - Assembler::Reset(); -} - -int IVMAssembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder, - uint32_t debug_info_flags, - std::unique_ptr debug_info, - uint32_t trace_flags, Function** out_function) { - SCOPE_profile_cpu_f("alloy"); - - // Reset when we leave. - make_reset_scope(this); - - IVMFunction* fn = new IVMFunction(symbol_info); - fn->set_debug_info(std::move(debug_info)); - - TranslationContext ctx; - ctx.register_count = 0; - ctx.intcode_count = 0; - ctx.intcode_arena = &intcode_arena_; - ctx.source_map_count = 0; - ctx.source_map_arena = &source_map_arena_; - ctx.scratch_arena = &scratch_arena_; - ctx.label_ref_head = NULL; - - // Reset label tags as we use them. - builder->ResetLabelTags(); - - // Function prologue. - size_t stack_offset = 0; - auto locals = builder->locals(); - for (auto it = locals.begin(); it != locals.end(); ++it) { - auto slot = *it; - size_t type_size = GetTypeSize(slot->type); - // Align to natural size. - stack_offset = poly::align(stack_offset, type_size); - slot->set_constant((uint32_t)stack_offset); - stack_offset += type_size; - } - // Ensure 16b alignment. - stack_offset = poly::align(stack_offset, static_cast(16)); - ctx.stack_size = stack_offset; - - auto block = builder->first_block(); - while (block) { - auto label = block->label_head; - while (label) { - label->tag = (void*)(0x80000000 | ctx.intcode_count); - label = label->next; - } - - auto i = block->instr_head; - while (i) { - TranslateIntCodes(ctx, i); - i = i->next; - } - block = block->next; - } - - // Function epilogue. - - // Fixup label references. - LabelRef* label_ref = ctx.label_ref_head; - while (label_ref) { - label_ref->instr->src1_reg = - (uint32_t)(intptr_t)label_ref->label->tag & ~0x80000000; - label_ref = label_ref->next; - } - - fn->Setup(ctx); - - *out_function = fn; - return 0; -} - -} // namespace ivm -} // namespace backend -} // namespace alloy diff --git a/src/alloy/backend/ivm/ivm_assembler.h b/src/alloy/backend/ivm/ivm_assembler.h deleted file mode 100644 index 118ef69d5..000000000 --- a/src/alloy/backend/ivm/ivm_assembler.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_ -#define ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_ - -#include -#include - -namespace alloy { -namespace backend { -namespace ivm { - -class IVMAssembler : public Assembler { - public: - IVMAssembler(Backend* backend); - ~IVMAssembler() override; - - int Initialize() override; - - void Reset() override; - - int Assemble(runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder, - uint32_t debug_info_flags, - std::unique_ptr debug_info, - uint32_t trace_flags, runtime::Function** out_function) override; - - private: - Arena intcode_arena_; - Arena source_map_arena_; - Arena scratch_arena_; -}; - -} // namespace ivm -} // namespace backend -} // namespace alloy - -#endif // ALLOY_BACKEND_IVM_IVM_ASSEMBLER_H_ diff --git a/src/alloy/backend/ivm/ivm_backend.cc b/src/alloy/backend/ivm/ivm_backend.cc deleted file mode 100644 index 171765a36..000000000 --- a/src/alloy/backend/ivm/ivm_backend.cc +++ /dev/null @@ -1,56 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include - -namespace alloy { -namespace backend { -namespace ivm { - -using alloy::runtime::Runtime; - -IVMBackend::IVMBackend(Runtime* runtime) : Backend(runtime) {} - -IVMBackend::~IVMBackend() = default; - -int IVMBackend::Initialize() { - int result = Backend::Initialize(); - if (result) { - return result; - } - - machine_info_.register_sets[0] = { - 0, "gpr", MachineInfo::RegisterSet::INT_TYPES, 16, - }; - machine_info_.register_sets[1] = { - 1, "vec", MachineInfo::RegisterSet::FLOAT_TYPES | - MachineInfo::RegisterSet::VEC_TYPES, - 16, - }; - - return result; -} - -void* IVMBackend::AllocThreadData() { return new IVMStack(); } - -void IVMBackend::FreeThreadData(void* thread_data) { - auto stack = (IVMStack*)thread_data; - delete stack; -} - -std::unique_ptr IVMBackend::CreateAssembler() { - return std::make_unique(this); -} - -} // namespace ivm -} // namespace backend -} // namespace alloy diff --git a/src/alloy/backend/ivm/ivm_backend.h b/src/alloy/backend/ivm/ivm_backend.h deleted file mode 100644 index 46814353b..000000000 --- a/src/alloy/backend/ivm/ivm_backend.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef ALLOY_BACKEND_IVM_IVM_BACKEND_H_ -#define ALLOY_BACKEND_IVM_IVM_BACKEND_H_ - -#include - -namespace alloy { -namespace backend { -namespace ivm { - -#define ALLOY_HAS_IVM_BACKEND 1 - -class IVMBackend : public Backend { - public: - IVMBackend(runtime::Runtime* runtime); - ~IVMBackend() override; - - int Initialize() override; - - void* AllocThreadData() override; - void FreeThreadData(void* thread_data) override; - - std::unique_ptr CreateAssembler() override; -}; - -} // namespace ivm -} // namespace backend -} // namespace alloy - -#endif // ALLOY_BACKEND_IVM_IVM_BACKEND_H_ diff --git a/src/alloy/backend/ivm/ivm_function.cc b/src/alloy/backend/ivm/ivm_function.cc deleted file mode 100644 index fa99c5a11..000000000 --- a/src/alloy/backend/ivm/ivm_function.cc +++ /dev/null @@ -1,176 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include - -namespace alloy { -namespace backend { -namespace ivm { - -using alloy::runtime::Breakpoint; -using alloy::runtime::FunctionInfo; -using alloy::runtime::ThreadState; - -IVMFunction::IVMFunction(FunctionInfo* symbol_info) - : Function(symbol_info), - register_count_(0), - intcode_count_(0), - intcodes_(nullptr), - source_map_count_(0), - source_map_(nullptr) {} - -IVMFunction::~IVMFunction() { - free(intcodes_); - free(source_map_); -} - -void IVMFunction::Setup(TranslationContext& ctx) { - register_count_ = ctx.register_count; - stack_size_ = ctx.stack_size; - intcode_count_ = ctx.intcode_count; - intcodes_ = (IntCode*)ctx.intcode_arena->CloneContents(); - source_map_count_ = ctx.source_map_count; - source_map_ = (SourceMapEntry*)ctx.source_map_arena->CloneContents(); -} - -IntCode* IVMFunction::GetIntCodeAtSourceOffset(uint64_t offset) { - for (size_t n = 0; n < source_map_count_; n++) { - auto entry = &source_map_[n]; - if (entry->source_offset == offset) { - return &intcodes_[entry->intcode_index]; - } - } - return NULL; -} - -int IVMFunction::AddBreakpointImpl(Breakpoint* breakpoint) { - auto i = GetIntCodeAtSourceOffset(breakpoint->address()); - if (!i) { - return 1; - } - - // TEMP breakpoints always overwrite normal ones. - if (!i->debug_flags || breakpoint->type() == Breakpoint::TEMP_TYPE) { - uint64_t breakpoint_ptr = (uint64_t)breakpoint; - i->src2_reg = (uint32_t)breakpoint_ptr; - i->src3_reg = (uint32_t)(breakpoint_ptr >> 32); - } - - // Increment breakpoint counter. - ++i->debug_flags; - - return 0; -} - -int IVMFunction::RemoveBreakpointImpl(Breakpoint* breakpoint) { - auto i = GetIntCodeAtSourceOffset(breakpoint->address()); - if (!i) { - return 1; - } - - // Decrement breakpoint counter. - --i->debug_flags; - i->src2_reg = i->src3_reg = 0; - - // If there were other breakpoints, see what they were. - if (i->debug_flags) { - auto old_breakpoint = FindBreakpoint(breakpoint->address()); - if (old_breakpoint) { - uint64_t breakpoint_ptr = (uint64_t)old_breakpoint; - i->src2_reg = (uint32_t)breakpoint_ptr; - i->src3_reg = (uint32_t)(breakpoint_ptr >> 32); - } - } - - return 0; -} - -void IVMFunction::OnBreakpointHit(ThreadState* thread_state, IntCode* i) { - uint64_t breakpoint_ptr = i->src2_reg | (uint64_t(i->src3_reg) << 32); - Breakpoint* breakpoint = (Breakpoint*)breakpoint_ptr; - - // Notify debugger. - // The debugger may choose to wait (blocking us). - auto debugger = thread_state->runtime()->debugger(); - debugger->OnBreakpointHit(thread_state, breakpoint); -} - -#undef TRACE_SOURCE_OFFSET - -int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) { - // Setup register file on stack. - auto stack = (IVMStack*)thread_state->backend_data(); - auto register_file = (Register*)stack->Alloc(register_count_); - auto local_stack = (uint8_t*)alloca(stack_size_); - - Memory* memory = thread_state->memory(); - - IntCodeState ics; - ics.rf = register_file; - ics.locals = local_stack; - ics.context = (uint8_t*)thread_state->raw_context(); - ics.membase = memory->membase(); - ics.did_carry = 0; - ics.did_saturate = 0; - ics.thread_state = thread_state; - ics.return_address = return_address; - ics.call_return_address = 0; - -// TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY -// or something so the fns can set an ics flag. - -#ifdef TRACE_SOURCE_OFFSET - size_t source_index = 0; -#endif - - uint32_t ia = 0; - while (true) { -#ifdef TRACE_SOURCE_OFFSET - uint64_t source_offset = -1; - if (source_index < this->source_map_count_ && - this->source_map_[source_index].intcode_index <= ia) { - while (source_index + 1 < this->source_map_count_ && - this->source_map_[source_index + 1].intcode_index <= ia) { - source_index++; - } - source_offset = this->source_map_[source_index].source_offset; - } -#endif - - IntCode* i = &intcodes_[ia]; - - if (i->debug_flags) { - OnBreakpointHit(thread_state, i); - } - - uint32_t new_ia = i->intcode_fn(ics, i); - if (new_ia == IA_NEXT) { - ia++; - } else if (new_ia == IA_RETURN) { - break; - } else { - ia = new_ia; -#ifdef TRACE_SOURCE_OFFSET - source_index = 0; -#endif - } - } - - stack->Free(register_count_); - - return 0; -} - -} // namespace ivm -} // namespace backend -} // namespace alloy diff --git a/src/alloy/backend/ivm/ivm_function.h b/src/alloy/backend/ivm/ivm_function.h deleted file mode 100644 index 31eb07084..000000000 --- a/src/alloy/backend/ivm/ivm_function.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef ALLOY_BACKEND_IVM_IVM_FUNCTION_H_ -#define ALLOY_BACKEND_IVM_IVM_FUNCTION_H_ - -#include -#include -#include - -namespace alloy { -namespace backend { -namespace ivm { - -class IVMFunction : public runtime::Function { - public: - IVMFunction(runtime::FunctionInfo* symbol_info); - virtual ~IVMFunction(); - - void Setup(TranslationContext& ctx); - - protected: - virtual int AddBreakpointImpl(runtime::Breakpoint* breakpoint); - virtual int RemoveBreakpointImpl(runtime::Breakpoint* breakpoint); - virtual int CallImpl(runtime::ThreadState* thread_state, - uint64_t return_address); - - private: - IntCode* GetIntCodeAtSourceOffset(uint64_t offset); - void OnBreakpointHit(runtime::ThreadState* thread_state, IntCode* i); - - private: - size_t register_count_; - size_t stack_size_; - size_t intcode_count_; - IntCode* intcodes_; - size_t source_map_count_; - SourceMapEntry* source_map_; -}; - -} // namespace ivm -} // namespace backend -} // namespace alloy - -#endif // ALLOY_BACKEND_IVM_IVM_FUNCTION_H_ diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc deleted file mode 100644 index 8c2b55d7d..000000000 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ /dev/null @@ -1,4287 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - -#include -#include -#include -#include -#include -#include - -// TODO(benvanik): make a compile time flag? -//#define DYNAMIC_REGISTER_ACCESS_CHECK(address) false -#define DYNAMIC_REGISTER_ACCESS_CHECK(address) \ - ((address & 0xFF000000) == 0x7F000000) - -namespace alloy { -namespace backend { -namespace ivm { - -// TODO(benvanik): remove when enums redefined. -using namespace alloy::hir; - -using alloy::hir::Instr; -using alloy::hir::Label; -using alloy::hir::OpcodeInfo; -using alloy::hir::OpcodeSignatureType; -using alloy::hir::TypeName; -using alloy::hir::Value; -using alloy::runtime::Function; -using alloy::runtime::FunctionInfo; - -#define IPRINT(...) (void()) -#define IFLUSH() (void()) -#define DPRINT(...) (void()) -#define DFLUSH() (void()) - -//#define IPRINT \ -// if (ics.thread_state->thread_id() == 1) printf -//#define IFLUSH() fflush(stdout) -//#define DPRINT \ -// if (ics.thread_state->thread_id() == 1) printf -//#define DFLUSH() fflush(stdout) - -uint32_t IntCode_INT_LOAD_CONSTANT(IntCodeState& ics, const IntCode* i) { - // TODO(benvanik): optimize on type to avoid 16b copy per load. - ics.rf[i->dest_reg].v128 = i->constant.v128; - return IA_NEXT; -} - -uint32_t AllocConstant(TranslationContext& ctx, uint64_t value, - IntCode** out_ic = NULL) { - ctx.intcode_count++; - IntCode* ic = ctx.intcode_arena->Alloc(); - ic->intcode_fn = IntCode_INT_LOAD_CONSTANT; - ic->flags = 0; - ic->debug_flags = 0; - ic->dest_reg = ctx.register_count++; - ic->constant.u64 = value; - if (out_ic) { - *out_ic = ic; - } - return ic->dest_reg; -} - -uint32_t AllocConstant(TranslationContext& ctx, Value* value) { - ctx.intcode_count++; - IntCode* ic = ctx.intcode_arena->Alloc(); - ic->intcode_fn = IntCode_INT_LOAD_CONSTANT; - ic->flags = 0; - ic->debug_flags = 0; - ic->dest_reg = ctx.register_count++; - ic->constant.v128 = value->constant.v128; - return ic->dest_reg; -} - -uint32_t AllocLabel(TranslationContext& ctx, Label* label) { - // If it's a back-branch to an already tagged label avoid setting up - // a reference. - uint32_t value = - static_cast(reinterpret_cast(label->tag)); - if (value & 0x80000000) { - // Already set. - return AllocConstant(ctx, value & ~0x80000000); - } - - // Allocate a constant - it will be updated later. - IntCode* ic; - uint32_t reg = AllocConstant(ctx, 0, &ic); - - // Setup a label reference. After assembly is complete this will - // run through and fix up the constant with the IA. - LabelRef* label_ref = ctx.scratch_arena->Alloc(); - label_ref->next = ctx.label_ref_head; - ctx.label_ref_head = label_ref; - label_ref->label = label; - label_ref->instr = ic; - - return reg; -} - -uint32_t AllocDynamicRegister(TranslationContext& ctx, Value* value) { - if (value->flags & VALUE_IS_ALLOCATED) { - return static_cast(reinterpret_cast(value->tag)); - } else { - value->flags |= VALUE_IS_ALLOCATED; - auto reg = ctx.register_count++; - value->tag = reinterpret_cast(static_cast(reg)); - return (uint32_t)reg; - } -} - -uint32_t AllocOpRegister(TranslationContext& ctx, OpcodeSignatureType sig_type, - Instr::Op* op) { - switch (sig_type) { - case OPCODE_SIG_TYPE_X: - // Nothing. - return 0; - case OPCODE_SIG_TYPE_L: - return AllocLabel(ctx, op->label); - case OPCODE_SIG_TYPE_O: - return AllocConstant(ctx, (uint64_t)op->offset); - case OPCODE_SIG_TYPE_S: - return AllocConstant(ctx, (uint64_t)op->symbol_info); - case OPCODE_SIG_TYPE_V: - Value* value = op->value; - if (value->IsConstant()) { - return AllocConstant(ctx, value); - } else { - return AllocDynamicRegister(ctx, value); - } - } - return 0; -} - -uint32_t IntCode_INVALID(IntCodeState& ics, const IntCode* i); -uint32_t IntCode_INVALID_TYPE(IntCodeState& ics, const IntCode* i); -int DispatchToC(TranslationContext& ctx, Instr* i, IntCodeFn fn) { - assert_true(fn != IntCode_INVALID); - assert_true(fn != IntCode_INVALID_TYPE); - - const OpcodeInfo* op = i->opcode; - uint32_t sig = op->signature; - OpcodeSignatureType dest_type = GET_OPCODE_SIG_TYPE_DEST(sig); - OpcodeSignatureType src1_type = GET_OPCODE_SIG_TYPE_SRC1(sig); - OpcodeSignatureType src2_type = GET_OPCODE_SIG_TYPE_SRC2(sig); - OpcodeSignatureType src3_type = GET_OPCODE_SIG_TYPE_SRC3(sig); - - // Setup arguments. - uint32_t dest_reg = 0; - if (dest_type == OPCODE_SIG_TYPE_V) { - // Allocate dest register. - dest_reg = AllocDynamicRegister(ctx, i->dest); - } - uint32_t src1_reg = AllocOpRegister(ctx, src1_type, &i->src1); - uint32_t src2_reg = AllocOpRegister(ctx, src2_type, &i->src2); - uint32_t src3_reg = AllocOpRegister(ctx, src3_type, &i->src3); - - // Allocate last (in case we had any setup instructions for args). - ctx.intcode_count++; - IntCode* ic = ctx.intcode_arena->Alloc(); - ic->intcode_fn = fn; - ic->flags = i->flags; - ic->debug_flags = 0; - ic->dest_reg = dest_reg; - ic->src1_reg = src1_reg; - ic->src2_reg = src2_reg; - ic->src3_reg = src3_reg; - - return 0; -} - -uint32_t IntCode_INVALID(IntCodeState& ics, const IntCode* i) { - assert_always(); - return IA_NEXT; -} -uint32_t IntCode_INVALID_TYPE(IntCodeState& ics, const IntCode* i) { - assert_always(); - return IA_NEXT; -} -int TranslateInvalid(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_INVALID); -} - -uint32_t IntCode_COMMENT(IntCodeState& ics, const IntCode* i) { - char* value = (char*)(i->src1_reg | ((uint64_t)i->src2_reg << 32)); - (void)(value); - IPRINT("XE[t] :%d: %s\n", ics.thread_state->thread_id(), value); - IFLUSH(); - return IA_NEXT; -} -int Translate_COMMENT(TranslationContext& ctx, Instr* i) { - ctx.intcode_count++; - IntCode* ic = ctx.intcode_arena->Alloc(); - ic->intcode_fn = IntCode_COMMENT; - ic->flags = i->flags; - ic->debug_flags = 0; - // HACK HACK HACK - char* src = strdup(reinterpret_cast(i->src1.offset)); - uint64_t src_p = (uint64_t)src; - ic->src1_reg = (uint32_t)src_p; - ic->src2_reg = (uint32_t)(src_p >> 32); - return 0; -} - -uint32_t IntCode_NOP(IntCodeState& ics, const IntCode* i) { return IA_NEXT; } -int Translate_NOP(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_NOP); -} - -uint32_t IntCode_SOURCE_OFFSET(IntCodeState& ics, const IntCode* i) { - return IA_NEXT; -} -int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) { - int result = DispatchToC(ctx, i, IntCode_SOURCE_OFFSET); - if (result) { - return result; - } - auto entry = ctx.source_map_arena->Alloc(); - entry->intcode_index = ctx.intcode_count - 1; - entry->source_offset = i->src1.offset; - ctx.source_map_count++; - return 0; -} - -// TODO(benvanik): dispatch of register forms. -uint32_t IntCode_TRACE_SOURCE(IntCodeState& ics, const IntCode* i) { - uint64_t trace_base = ics.thread_state->memory()->trace_base(); - if (trace_base) { - auto ev = xdb::protocol::InstrEvent::Append(trace_base); - ev->type = xdb::protocol::EventType::INSTR; - ev->thread_id = ics.thread_state->thread_id(); - ev->address = ics.rf[i->src1_reg].i32; - } - return IA_NEXT; -} -int Translate_TRACE_SOURCE(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_TRACE_SOURCE); -} - -uint32_t IntCode_DEBUG_BREAK(IntCodeState& ics, const IntCode* i) { - DFLUSH(); - __debugbreak(); - return IA_NEXT; -} -int Translate_DEBUG_BREAK(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_DEBUG_BREAK); -} - -uint32_t IntCode_DEBUG_BREAK_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_DEBUG_BREAK_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_DEBUG_BREAK_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_DEBUG_BREAK_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_DEBUG_BREAK_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_DEBUG_BREAK_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IntCode_DEBUG_BREAK(ics, i); - } - return IA_NEXT; -} -int Translate_DEBUG_BREAK_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_DEBUG_BREAK_TRUE_I8, IntCode_DEBUG_BREAK_TRUE_I16, - IntCode_DEBUG_BREAK_TRUE_I32, IntCode_DEBUG_BREAK_TRUE_I64, - IntCode_DEBUG_BREAK_TRUE_F32, IntCode_DEBUG_BREAK_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_TRAP(IntCodeState& ics, const IntCode* i) { - // TODO(benvanik): post software interrupt to debugger. - switch (i->flags) { - case 20: - // 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length - return IA_NEXT; - case 22: - // Always trap? - break; - } - __debugbreak(); - return IA_NEXT; -} -int Translate_TRAP(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_TRAP); -} - -uint32_t IntCode_TRAP_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_TRAP_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_TRAP_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_TRAP_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_TRAP_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -uint32_t IntCode_TRAP_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IntCode_TRAP(ics, i); - } - return IA_NEXT; -} -int Translate_TRAP_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_TRAP_TRUE_I8, IntCode_TRAP_TRUE_I16, IntCode_TRAP_TRUE_I32, - IntCode_TRAP_TRUE_I64, IntCode_TRAP_TRUE_F32, IntCode_TRAP_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_CALL_XX(IntCodeState& ics, const IntCode* i, uint32_t reg) { - FunctionInfo* symbol_info = (FunctionInfo*)ics.rf[reg].u64; - Function* fn = symbol_info->function(); - if (!fn) { - ics.thread_state->runtime()->ResolveFunction(symbol_info->address(), &fn); - } - assert_not_null(fn); - // TODO(benvanik): proper tail call support, somehow. - uint64_t return_address = - (i->flags & CALL_TAIL) ? ics.return_address : ics.call_return_address; - fn->Call(ics.thread_state, return_address); - if (i->flags & CALL_TAIL) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_CALL(IntCodeState& ics, const IntCode* i) { - return IntCode_CALL_XX(ics, i, i->src1_reg); -} -int Translate_CALL(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_CALL); -} - -uint32_t IntCode_CALL_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IntCode_CALL_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -int Translate_CALL_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_CALL_TRUE_I8, IntCode_CALL_TRUE_I16, IntCode_CALL_TRUE_I32, - IntCode_CALL_TRUE_I64, IntCode_CALL_TRUE_F32, IntCode_CALL_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_CALL_INDIRECT_XX(IntCodeState& ics, const IntCode* i, - uint32_t reg) { - uint64_t target = ics.rf[reg].u32; - - // Check if return address - if so, return. - if (i->flags & CALL_POSSIBLE_RETURN) { - if (target == ics.return_address) { - return IA_RETURN; - } - } - - // Real call. - Function* fn = NULL; - ics.thread_state->runtime()->ResolveFunction(target, &fn); - assert_not_null(fn); - // TODO(benvanik): proper tail call support, somehow. - uint64_t return_address = - (i->flags & CALL_TAIL) ? ics.return_address : ics.call_return_address; - fn->Call(ics.thread_state, return_address); - if (i->flags & CALL_TAIL) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT(IntCodeState& ics, const IntCode* i) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src1_reg); -} -int Translate_CALL_INDIRECT(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_CALL_INDIRECT); -} - -uint32_t IntCode_CALL_INDIRECT_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_CALL_INDIRECT_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IntCode_CALL_INDIRECT_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -int Translate_CALL_INDIRECT_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_CALL_INDIRECT_TRUE_I8, IntCode_CALL_INDIRECT_TRUE_I16, - IntCode_CALL_INDIRECT_TRUE_I32, IntCode_CALL_INDIRECT_TRUE_I64, - IntCode_CALL_INDIRECT_TRUE_F32, IntCode_CALL_INDIRECT_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_CALL_EXTERN(IntCodeState& ics, const IntCode* i) { - return IntCode_CALL_XX(ics, i, i->src1_reg); -} -int Translate_CALL_EXTERN(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_CALL_EXTERN); -} - -uint32_t IntCode_RETURN(IntCodeState& ics, const IntCode* i) { - return IA_RETURN; -} -int Translate_RETURN(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_RETURN); -} - -uint32_t IntCode_RETURN_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_RETURN_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_RETURN_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_RETURN_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_RETURN_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IA_RETURN; - } - return IA_NEXT; -} -uint32_t IntCode_RETURN_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IA_RETURN; - } - return IA_NEXT; -} -int Translate_RETURN_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_RETURN_TRUE_I8, IntCode_RETURN_TRUE_I16, IntCode_RETURN_TRUE_I32, - IntCode_RETURN_TRUE_I64, IntCode_RETURN_TRUE_F32, IntCode_RETURN_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_SET_RETURN_ADDRESS(IntCodeState& ics, const IntCode* i) { - ics.call_return_address = ics.rf[i->src1_reg].u32; - return IA_NEXT; -} -int Translate_SET_RETURN_ADDRESS(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_SET_RETURN_ADDRESS); -} - -uint32_t IntCode_BRANCH_XX(IntCodeState& ics, const IntCode* i, uint32_t reg) { - return ics.rf[reg].u32; -} -uint32_t IntCode_BRANCH(IntCodeState& ics, const IntCode* i) { - return IntCode_BRANCH_XX(ics, i, i->src1_reg); -} -int Translate_BRANCH(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_BRANCH); -} - -uint32_t IntCode_BRANCH_TRUE_I8(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u8) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_TRUE_I16(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u16) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_TRUE_I32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u32) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_TRUE_I64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].u64) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_TRUE_F32(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f32) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_TRUE_F64(IntCodeState& ics, const IntCode* i) { - if (ics.rf[i->src1_reg].f64) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -int Translate_BRANCH_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_BRANCH_TRUE_I8, IntCode_BRANCH_TRUE_I16, IntCode_BRANCH_TRUE_I32, - IntCode_BRANCH_TRUE_I64, IntCode_BRANCH_TRUE_F32, IntCode_BRANCH_TRUE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_BRANCH_FALSE_I8(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].u8) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_FALSE_I16(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].u16) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_FALSE_I32(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].u32) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_FALSE_I64(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].u64) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_FALSE_F32(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].f32) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -uint32_t IntCode_BRANCH_FALSE_F64(IntCodeState& ics, const IntCode* i) { - if (!ics.rf[i->src1_reg].f64) { - return IntCode_BRANCH_XX(ics, i, i->src2_reg); - } - return IA_NEXT; -} -int Translate_BRANCH_FALSE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_BRANCH_FALSE_I8, IntCode_BRANCH_FALSE_I16, - IntCode_BRANCH_FALSE_I32, IntCode_BRANCH_FALSE_I64, - IntCode_BRANCH_FALSE_F32, IntCode_BRANCH_FALSE_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_ASSIGN_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_ASSIGN_V128(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].v128 = ics.rf[i->src1_reg].v128; - return IA_NEXT; -} -int Translate_ASSIGN(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ASSIGN_I8, IntCode_ASSIGN_I16, IntCode_ASSIGN_I32, - IntCode_ASSIGN_I64, IntCode_ASSIGN_F32, IntCode_ASSIGN_F64, - IntCode_ASSIGN_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_CAST(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].v128 = ics.rf[i->src1_reg].v128; - return IA_NEXT; -} -int Translate_CAST(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_CAST); -} - -uint32_t IntCode_ZERO_EXTEND_I8_TO_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = (uint8_t)ics.rf[i->src1_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_ZERO_EXTEND_I8_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (uint16_t)ics.rf[i->src1_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_ZERO_EXTEND_I8_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (uint64_t)ics.rf[i->src1_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_ZERO_EXTEND_I16_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (uint32_t)ics.rf[i->src1_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_ZERO_EXTEND_I16_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (uint64_t)ics.rf[i->src1_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_ZERO_EXTEND_I32_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (uint64_t)ics.rf[i->src1_reg].u32; - return IA_NEXT; -} -int Translate_ZERO_EXTEND(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ASSIGN_I8, IntCode_ZERO_EXTEND_I8_TO_I16, - IntCode_ZERO_EXTEND_I8_TO_I32, IntCode_ZERO_EXTEND_I8_TO_I64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I16, IntCode_ZERO_EXTEND_I16_TO_I32, - IntCode_ZERO_EXTEND_I16_TO_I64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I32, IntCode_ZERO_EXTEND_I32_TO_I64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_SIGN_EXTEND_I8_TO_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = (int8_t)ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SIGN_EXTEND_I8_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (int16_t)ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SIGN_EXTEND_I8_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (int64_t)ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SIGN_EXTEND_I16_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (int32_t)ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_SIGN_EXTEND_I16_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (int64_t)ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_SIGN_EXTEND_I32_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (int64_t)ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -int Translate_SIGN_EXTEND(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ASSIGN_I8, IntCode_SIGN_EXTEND_I8_TO_I16, - IntCode_SIGN_EXTEND_I8_TO_I32, IntCode_SIGN_EXTEND_I8_TO_I64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I16, IntCode_SIGN_EXTEND_I16_TO_I32, - IntCode_SIGN_EXTEND_I16_TO_I64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I32, IntCode_SIGN_EXTEND_I32_TO_I64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_TRUNCATE_I16_TO_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = (int8_t)ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_TRUNCATE_I32_TO_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = (int8_t)ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_TRUNCATE_I32_TO_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = (int16_t)ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_TRUNCATE_I64_TO_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = (int8_t)ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_TRUNCATE_I64_TO_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = (int16_t)ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_TRUNCATE_I64_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (int32_t)ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -int Translate_TRUNCATE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ASSIGN_I8, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_TRUNCATE_I16_TO_I8, - IntCode_ASSIGN_I16, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_TRUNCATE_I32_TO_I8, IntCode_TRUNCATE_I32_TO_I16, - IntCode_ASSIGN_I32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_TRUNCATE_I64_TO_I8, - IntCode_TRUNCATE_I64_TO_I16, IntCode_TRUNCATE_I64_TO_I32, - IntCode_ASSIGN_I64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_CONVERT_I32_TO_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = (float)ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_I64_TO_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = (double)ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_F32_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (int32_t)ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_F32_TO_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = (double)ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_F64_TO_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = (int32_t)ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_F64_TO_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = (int64_t)ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_CONVERT_F64_TO_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = (float)ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -int Translate_CONVERT(TranslationContext& ctx, Instr* i) { - // Can do more as needed. - static IntCodeFn fns[] = { - IntCode_ASSIGN_I8, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I16, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I32, IntCode_INVALID_TYPE, - IntCode_CONVERT_I32_TO_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_I64, IntCode_INVALID_TYPE, - IntCode_CONVERT_I64_TO_F64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_CONVERT_F32_TO_I32, IntCode_INVALID_TYPE, - IntCode_ASSIGN_F32, IntCode_CONVERT_F32_TO_F64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_CONVERT_F64_TO_I32, - IntCode_CONVERT_F64_TO_I64, IntCode_CONVERT_F64_TO_F32, - IntCode_ASSIGN_F64, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ASSIGN_V128, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_ROUND_F32(IntCodeState& ics, const IntCode* i) { - float src1 = ics.rf[i->src1_reg].f32; - float dest = src1; - switch (i->flags) { - case ROUND_TO_ZERO: - dest = truncf(src1); - break; - case ROUND_TO_NEAREST: - dest = roundf(src1); - break; - case ROUND_TO_MINUS_INFINITY: - dest = floorf(src1); - break; - case ROUND_TO_POSITIVE_INFINITY: - dest = ceilf(src1); - break; - } - ics.rf[i->dest_reg].f32 = dest; - return IA_NEXT; -} -uint32_t IntCode_ROUND_F64(IntCodeState& ics, const IntCode* i) { - double src1 = ics.rf[i->src1_reg].f64; - double dest = src1; - switch (i->flags) { - case ROUND_TO_ZERO: - dest = trunc(src1); - break; - case ROUND_TO_NEAREST: - dest = round(src1); - break; - case ROUND_TO_MINUS_INFINITY: - dest = floor(src1); - break; - case ROUND_TO_POSITIVE_INFINITY: - dest = ceil(src1); - break; - } - ics.rf[i->dest_reg].f64 = dest; - return IA_NEXT; -} -uint32_t IntCode_ROUND_V128_ZERO(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t n = 0; n < 4; n++) { - dest.f32[n] = truncf(src1.f32[n]); - } - return IA_NEXT; -} -uint32_t IntCode_ROUND_V128_NEAREST(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t n = 0; n < 4; n++) { - dest.f32[n] = roundf(src1.f32[n]); - } - return IA_NEXT; -} -uint32_t IntCode_ROUND_V128_MINUS_INFINITY(IntCodeState& ics, - const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; ++n) { - dest.f32[n] = floorf(src1.f32[n]); - } - return IA_NEXT; -} -uint32_t IntCode_ROUND_V128_POSITIVE_INFINTIY(IntCodeState& ics, - const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; ++n) { - dest.f32[n] = ceilf(src1.f32[n]); - } - return IA_NEXT; -} -int Translate_ROUND(TranslationContext& ctx, Instr* i) { - if (i->dest->type == VEC128_TYPE) { - static IntCodeFn fns[] = { - IntCode_ROUND_V128_ZERO, IntCode_ROUND_V128_NEAREST, - IntCode_ROUND_V128_MINUS_INFINITY, IntCode_ROUND_V128_POSITIVE_INFINTIY, - }; - return DispatchToC(ctx, i, fns[i->flags]); - } else { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_ROUND_F32, IntCode_ROUND_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); - } -} - -uint32_t IntCode_VECTOR_CONVERT_I2F_S(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; ++n) { - dest.f32[n] = (float)(int32_t)src1.u32[n]; - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_CONVERT_I2F_U(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; ++n) { - dest.f32[n] = (float)(uint32_t)src1.u32[n]; - } - return IA_NEXT; -} -int Translate_VECTOR_CONVERT_I2F(TranslationContext& ctx, Instr* i) { - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, IntCode_VECTOR_CONVERT_I2F_U); - } else { - return DispatchToC(ctx, i, IntCode_VECTOR_CONVERT_I2F_S); - } -} - -uint32_t IntCode_VECTOR_CONVERT_F2I(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - if (i->flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 4; ++n) { - dest.u32[n] = (uint32_t)src1.f32[n]; - } - } else { - for (int n = 0; n < 4; ++n) { - dest.u32[n] = (int32_t)src1.f32[n]; - } - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_CONVERT_F2I_SAT(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - if (i->flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 4; n++) { - float src = src1.f32[n]; - if (src < 0) { - dest.u32[n] = 0; - ics.did_saturate = 1; - } else if (src > UINT_MAX) { - dest.u32[n] = UINT_MAX; - ics.did_saturate = 1; - } else { - dest.u32[n] = (uint32_t)src; - } - } - } else { - for (int n = 0; n < 4; n++) { - float src = src1.f32[n]; - if (src < INT_MIN) { - dest.u32[n] = INT_MIN; - ics.did_saturate = 1; - } else if (src > INT_MAX) { - dest.u32[n] = INT_MAX; - ics.did_saturate = 1; - } else { - dest.u32[n] = (int32_t)src; - } - } - } - return IA_NEXT; -} -int Translate_VECTOR_CONVERT_F2I(TranslationContext& ctx, Instr* i) { - if (i->flags & ARITHMETIC_SATURATE) { - return DispatchToC(ctx, i, IntCode_VECTOR_CONVERT_F2I_SAT); - } else { - return DispatchToC(ctx, i, IntCode_VECTOR_CONVERT_F2I); - } -} - -static const vec128_t lvsl_table[16] = { - vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), - vec128b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), - vec128b(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17), - vec128b(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18), - vec128b(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), - vec128b(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20), - vec128b(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21), - vec128b(7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22), - vec128b(8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23), - vec128b(9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24), - vec128b(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25), - vec128b(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), - vec128b(12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27), - vec128b(13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28), - vec128b(14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29), - vec128b(15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30), -}; -static const vec128_t lvsr_table[16] = { - vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31), - vec128b(15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30), - vec128b(14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29), - vec128b(13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28), - vec128b(12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27), - vec128b(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), - vec128b(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25), - vec128b(9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24), - vec128b(8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23), - vec128b(7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22), - vec128b(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21), - vec128b(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20), - vec128b(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), - vec128b(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18), - vec128b(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17), - vec128b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), -}; - -uint32_t IntCode_LOAD_VECTOR_SHL(IntCodeState& ics, const IntCode* i) { - int8_t sh = ics.rf[i->src1_reg].i8 & 0xF; - ics.rf[i->dest_reg].v128 = lvsl_table[sh]; - return IA_NEXT; -} -int Translate_LOAD_VECTOR_SHL(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_LOAD_VECTOR_SHL); -} - -uint32_t IntCode_LOAD_VECTOR_SHR(IntCodeState& ics, const IntCode* i) { - int8_t sh = ics.rf[i->src1_reg].i8 & 0xF; - ics.rf[i->dest_reg].v128 = lvsr_table[sh]; - return IA_NEXT; -} -int Translate_LOAD_VECTOR_SHR(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_LOAD_VECTOR_SHR); -} - -uint32_t IntCode_LOAD_CLOCK(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = poly::threading::ticks(); - return IA_NEXT; -} -int Translate_LOAD_CLOCK(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_LOAD_CLOCK); -} - -uint32_t IntCode_LOAD_LOCAL_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = *((int8_t*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = *((int16_t*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = *((int32_t*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = *((int64_t*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = *((float*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = *((double*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_LOCAL_V128(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].v128 = - *((vec128_t*)(ics.locals + ics.rf[i->src1_reg].u32)); - return IA_NEXT; -} -int Translate_LOAD_LOCAL(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_LOAD_LOCAL_I8, IntCode_LOAD_LOCAL_I16, IntCode_LOAD_LOCAL_I32, - IntCode_LOAD_LOCAL_I64, IntCode_LOAD_LOCAL_F32, IntCode_LOAD_LOCAL_F64, - IntCode_LOAD_LOCAL_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_STORE_LOCAL_I8(IntCodeState& ics, const IntCode* i) { - *((int8_t*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_I16(IntCodeState& ics, const IntCode* i) { - *((int16_t*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_I32(IntCodeState& ics, const IntCode* i) { - *((int32_t*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_I64(IntCodeState& ics, const IntCode* i) { - *((int64_t*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_F32(IntCodeState& ics, const IntCode* i) { - *((float*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_F64(IntCodeState& ics, const IntCode* i) { - *((double*)(ics.locals + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_STORE_LOCAL_V128(IntCodeState& ics, const IntCode* i) { - *((vec128_t*)(ics.locals + ics.rf[i->src1_reg].u32)) = - ics.rf[i->src2_reg].v128; - return IA_NEXT; -} -int Translate_STORE_LOCAL(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_STORE_LOCAL_I8, IntCode_STORE_LOCAL_I16, - IntCode_STORE_LOCAL_I32, IntCode_STORE_LOCAL_I64, - IntCode_STORE_LOCAL_F32, IntCode_STORE_LOCAL_F64, - IntCode_STORE_LOCAL_V128, - }; - return DispatchToC(ctx, i, fns[i->src2.value->type]); -} - -uint32_t IntCode_LOAD_CONTEXT_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = *((int8_t*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%d (%X) = ctx i8 +%d\n", ics.rf[i->dest_reg].i8, - ics.rf[i->dest_reg].u8, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = - *((int16_t*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%d (%X) = ctx i16 +%d\n", ics.rf[i->dest_reg].i16, - ics.rf[i->dest_reg].u16, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = - *((int32_t*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%d (%X) = ctx i32 +%d\n", ics.rf[i->dest_reg].i32, - ics.rf[i->dest_reg].u32, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = - *((int64_t*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%lld (%llX) = ctx i64 +%d\n", ics.rf[i->dest_reg].i64, - ics.rf[i->dest_reg].u64, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = *((float*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%e (%X) = ctx f32 +%d\n", ics.rf[i->dest_reg].f32, - ics.rf[i->dest_reg].u32, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = *((double*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("%lle (%llX) = ctx f64 +%d\n", ics.rf[i->dest_reg].f64, - ics.rf[i->dest_reg].u64, ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_LOAD_CONTEXT_V128(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].v128 = - *((vec128_t*)(ics.context + ics.rf[i->src1_reg].u64)); - DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = ctx v128 +%d\n", - ics.rf[i->dest_reg].v128.x, ics.rf[i->dest_reg].v128.y, - ics.rf[i->dest_reg].v128.z, ics.rf[i->dest_reg].v128.w, - ics.rf[i->dest_reg].v128.ux, ics.rf[i->dest_reg].v128.uy, - ics.rf[i->dest_reg].v128.uz, ics.rf[i->dest_reg].v128.uw, - ics.rf[i->src1_reg].u64); - return IA_NEXT; -} -int Translate_LOAD_CONTEXT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_LOAD_CONTEXT_I8, IntCode_LOAD_CONTEXT_I16, - IntCode_LOAD_CONTEXT_I32, IntCode_LOAD_CONTEXT_I64, - IntCode_LOAD_CONTEXT_F32, IntCode_LOAD_CONTEXT_F64, - IntCode_LOAD_CONTEXT_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_STORE_CONTEXT_I8(IntCodeState& ics, const IntCode* i) { - *((int8_t*)(ics.context + ics.rf[i->src1_reg].u64)) = ics.rf[i->src2_reg].i8; - DPRINT("ctx i8 +%d = %d (%X)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].i8, ics.rf[i->src2_reg].u8); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_I16(IntCodeState& ics, const IntCode* i) { - *((int16_t*)(ics.context + ics.rf[i->src1_reg].u64)) = - ics.rf[i->src2_reg].i16; - DPRINT("ctx i16 +%d = %d (%X)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].i16, ics.rf[i->src2_reg].u16); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_I32(IntCodeState& ics, const IntCode* i) { - *((int32_t*)(ics.context + ics.rf[i->src1_reg].u64)) = - ics.rf[i->src2_reg].i32; - DPRINT("ctx i32 +%d = %d (%X)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].i32, ics.rf[i->src2_reg].u32); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_I64(IntCodeState& ics, const IntCode* i) { - *((int64_t*)(ics.context + ics.rf[i->src1_reg].u64)) = - ics.rf[i->src2_reg].i64; - DPRINT("ctx i64 +%d = %lld (%llX)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].i64, ics.rf[i->src2_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_F32(IntCodeState& ics, const IntCode* i) { - *((float*)(ics.context + ics.rf[i->src1_reg].u64)) = ics.rf[i->src2_reg].f32; - DPRINT("ctx f32 +%d = %e (%X)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].f32, ics.rf[i->src2_reg].u32); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_F64(IntCodeState& ics, const IntCode* i) { - *((double*)(ics.context + ics.rf[i->src1_reg].u64)) = ics.rf[i->src2_reg].f64; - DPRINT("ctx f64 +%d = %lle (%llX)\n", ics.rf[i->src1_reg].u64, - ics.rf[i->src2_reg].f64, ics.rf[i->src2_reg].u64); - return IA_NEXT; -} -uint32_t IntCode_STORE_CONTEXT_V128(IntCodeState& ics, const IntCode* i) { - *((vec128_t*)(ics.context + ics.rf[i->src1_reg].u64)) = - ics.rf[i->src2_reg].v128; - DPRINT("ctx v128 +%d = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", - ics.rf[i->src1_reg].u64, ics.rf[i->src2_reg].v128.x, - ics.rf[i->src2_reg].v128.y, ics.rf[i->src2_reg].v128.z, - ics.rf[i->src2_reg].v128.w, ics.rf[i->src2_reg].v128.ux, - ics.rf[i->src2_reg].v128.uy, ics.rf[i->src2_reg].v128.uz, - ics.rf[i->src2_reg].v128.uw); - return IA_NEXT; -} -int Translate_STORE_CONTEXT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_STORE_CONTEXT_I8, IntCode_STORE_CONTEXT_I16, - IntCode_STORE_CONTEXT_I32, IntCode_STORE_CONTEXT_I64, - IntCode_STORE_CONTEXT_F32, IntCode_STORE_CONTEXT_F64, - IntCode_STORE_CONTEXT_V128, - }; - return DispatchToC(ctx, i, fns[i->src2.value->type]); -} - -uint32_t IntCode_LOAD_I8(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.rf[i->dest_reg].i8 = ics.thread_state->memory()->LoadI8(address); - return IA_NEXT; - } - DPRINT("%d (%X) = load.i8 %.8X\n", *((int8_t*)(ics.membase + address)), - *((uint8_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].i8 = *((int8_t*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_I16(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.rf[i->dest_reg].i16 = - poly::byte_swap(ics.thread_state->memory()->LoadI16(address)); - return IA_NEXT; - } - DPRINT("%d (%X) = load.i16 %.8X\n", *((int16_t*)(ics.membase + address)), - *((uint16_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].i16 = *((int16_t*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_I32(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.rf[i->dest_reg].i32 = - poly::byte_swap(ics.thread_state->memory()->LoadI32(address)); - return IA_NEXT; - } - DFLUSH(); - DPRINT("%d (%X) = load.i32 %.8X\n", *((int32_t*)(ics.membase + address)), - *((uint32_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].i32 = *((int32_t*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_I64(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.rf[i->dest_reg].i64 = - poly::byte_swap(ics.thread_state->memory()->LoadI64(address)); - return IA_NEXT; - } - DPRINT("%lld (%llX) = load.i64 %.8X\n", *((int64_t*)(ics.membase + address)), - *((uint64_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].i64 = *((int64_t*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_F32(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - DPRINT("%e (%X) = load.f32 %.8X\n", *((float*)(ics.membase + address)), - *((uint64_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].f32 = *((float*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_F64(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - DPRINT("%lle (%llX) = load.f64 %.8X\n", *((double*)(ics.membase + address)), - *((uint64_t*)(ics.membase + address)), address); - DFLUSH(); - ics.rf[i->dest_reg].f64 = *((double*)(ics.membase + address)); - return IA_NEXT; -} -uint32_t IntCode_LOAD_V128(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = *((uint32_t*)(ics.membase + address + n * 4)); - } - DPRINT("[%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X] = load.v128 %.8X\n", dest.x, - dest.y, dest.z, dest.w, dest.ux, dest.uy, dest.uz, dest.uw, address); - DFLUSH(); - return IA_NEXT; -} -int Translate_LOAD(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_LOAD_I8, IntCode_LOAD_I16, IntCode_LOAD_I32, IntCode_LOAD_I64, - IntCode_LOAD_F32, IntCode_LOAD_F64, IntCode_LOAD_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.thread_state->memory()->StoreI8(address, ics.rf[i->src2_reg].i8); - return IA_NEXT; - } - DPRINT("store.i8 %.8X = %d (%X)\n", address, ics.rf[i->src2_reg].i8, - ics.rf[i->src2_reg].u8); - DFLUSH(); - *((int8_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_STORE_I16(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.thread_state->memory()->StoreI16( - address, poly::byte_swap(ics.rf[i->src2_reg].i16)); - return IA_NEXT; - } - DPRINT("store.i16 %.8X = %d (%X)\n", address, ics.rf[i->src2_reg].i16, - ics.rf[i->src2_reg].u16); - DFLUSH(); - *((int16_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_STORE_I32(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.thread_state->memory()->StoreI32( - address, poly::byte_swap(ics.rf[i->src2_reg].i32)); - return IA_NEXT; - } - DPRINT("store.i32 %.8X = %d (%X)\n", address, ics.rf[i->src2_reg].i32, - ics.rf[i->src2_reg].u32); - DFLUSH(); - *((int32_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_STORE_I64(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - if (DYNAMIC_REGISTER_ACCESS_CHECK(address)) { - ics.thread_state->memory()->StoreI64( - address, poly::byte_swap(ics.rf[i->src2_reg].i64)); - return IA_NEXT; - } - DPRINT("store.i64 %.8X = %lld (%llX)\n", address, ics.rf[i->src2_reg].i64, - ics.rf[i->src2_reg].u64); - DFLUSH(); - *((int64_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_STORE_F32(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - DPRINT("store.f32 %.8X = %e (%X)\n", address, ics.rf[i->src2_reg].f32, - ics.rf[i->src2_reg].u32); - DFLUSH(); - *((float*)(ics.membase + address)) = ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_STORE_F64(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - DPRINT("store.f64 %.8X = %lle (%llX)\n", address, ics.rf[i->src2_reg].f64, - ics.rf[i->src2_reg].u64); - DFLUSH(); - *((double*)(ics.membase + address)) = ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_STORE_V128(IntCodeState& ics, const IntCode* i) { - uint32_t address = ics.rf[i->src1_reg].u32; - DPRINT("store.v128 %.8X = [%e, %e, %e, %e] [%.8X, %.8X, %.8X, %.8X]\n", - address, ics.rf[i->src2_reg].v128.x, ics.rf[i->src2_reg].v128.y, - ics.rf[i->src2_reg].v128.z, ics.rf[i->src2_reg].v128.w, - ics.rf[i->src2_reg].v128.ux, ics.rf[i->src2_reg].v128.uy, - ics.rf[i->src2_reg].v128.uz, ics.rf[i->src2_reg].v128.uw); - DFLUSH(); - *((vec128_t*)(ics.membase + address)) = ics.rf[i->src2_reg].v128; - return IA_NEXT; -} -int Translate_STORE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_STORE_I8, IntCode_STORE_I16, IntCode_STORE_I32, - IntCode_STORE_I64, IntCode_STORE_F32, IntCode_STORE_F64, - IntCode_STORE_V128, - }; - return DispatchToC(ctx, i, fns[i->src2.value->type]); -} - -uint32_t IntCode_PREFETCH(IntCodeState& ics, const IntCode* i) { - return IA_NEXT; -} -int Translate_PREFETCH(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_PREFETCH); -} - -uint32_t IntCode_MAX_I8_I8(IntCodeState& ics, const IntCode* i) { - int8_t a = ics.rf[i->src1_reg].i8; - int8_t b = ics.rf[i->src2_reg].i8; - ics.rf[i->dest_reg].i8 = std::max(a, b); - return IA_NEXT; -} -uint32_t IntCode_MAX_I16_I16(IntCodeState& ics, const IntCode* i) { - int16_t a = ics.rf[i->src1_reg].i16; - int16_t b = ics.rf[i->src2_reg].i16; - ics.rf[i->dest_reg].i16 = std::max(a, b); - return IA_NEXT; -} -uint32_t IntCode_MAX_I32_I32(IntCodeState& ics, const IntCode* i) { - int32_t a = ics.rf[i->src1_reg].i32; - int32_t b = ics.rf[i->src2_reg].i32; - ics.rf[i->dest_reg].i32 = std::max(a, b); - return IA_NEXT; -} -uint32_t IntCode_MAX_I64_I64(IntCodeState& ics, const IntCode* i) { - int64_t a = ics.rf[i->src1_reg].i64; - int64_t b = ics.rf[i->src2_reg].i64; - ics.rf[i->dest_reg].i64 = std::max(a, b); - return IA_NEXT; -} -uint32_t IntCode_MAX_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = - std::max(ics.rf[i->src1_reg].f32, ics.rf[i->src2_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_MAX_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = - std::max(ics.rf[i->src1_reg].f64, ics.rf[i->src2_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_MAX_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = std::max(src1.f32[n], src2.f32[n]); - } - return IA_NEXT; -} -int Translate_MAX(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MAX_I8_I8, IntCode_MAX_I16_I16, IntCode_MAX_I32_I32, - IntCode_MAX_I64_I64, IntCode_MAX_F32_F32, IntCode_MAX_F64_F64, - IntCode_MAX_V128_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_MAX_I8_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = std::max(src1.u8[n], src2.u8[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MAX_I16_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = std::max(src1.u16[n], src2.u16[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MAX_I32_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = std::max(src1.u32[n], src2.u32[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MAX_I8_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = std::max((int8_t)src1.u8[n], (int8_t)src2.u8[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MAX_I16_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = std::max((int16_t)src1.u16[n], (int16_t)src2.u16[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MAX_I32_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = std::max((int32_t)src1.u32[n], (int32_t)src2.u32[n]); - } - return IA_NEXT; -} -int Translate_VECTOR_MAX(TranslationContext& ctx, Instr* i) { - static IntCodeFn unsigned_fns[] = { - IntCode_VECTOR_MAX_I8_UNSIGNED, IntCode_VECTOR_MAX_I16_UNSIGNED, - IntCode_VECTOR_MAX_I32_UNSIGNED, - }; - static IntCodeFn signed_fns[] = { - IntCode_VECTOR_MAX_I8_SIGNED, IntCode_VECTOR_MAX_I16_SIGNED, - IntCode_VECTOR_MAX_I32_SIGNED, - }; - uint32_t part_type = i->flags >> 8; - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, unsigned_fns[part_type]); - } else { - return DispatchToC(ctx, i, signed_fns[part_type]); - } -} - -uint32_t IntCode_MIN_I8_I8(IntCodeState& ics, const IntCode* i) { - int8_t a = ics.rf[i->src1_reg].i8; - int8_t b = ics.rf[i->src2_reg].i8; - ics.rf[i->dest_reg].i8 = std::min(a, b); - return IA_NEXT; -} -uint32_t IntCode_MIN_I16_I16(IntCodeState& ics, const IntCode* i) { - int16_t a = ics.rf[i->src1_reg].i16; - int16_t b = ics.rf[i->src2_reg].i16; - ics.rf[i->dest_reg].i16 = std::min(a, b); - return IA_NEXT; -} -uint32_t IntCode_MIN_I32_I32(IntCodeState& ics, const IntCode* i) { - int32_t a = ics.rf[i->src1_reg].i32; - int32_t b = ics.rf[i->src2_reg].i32; - ics.rf[i->dest_reg].i32 = std::min(a, b); - return IA_NEXT; -} -uint32_t IntCode_MIN_I64_I64(IntCodeState& ics, const IntCode* i) { - int64_t a = ics.rf[i->src1_reg].i64; - int64_t b = ics.rf[i->src2_reg].i64; - ics.rf[i->dest_reg].i64 = std::min(a, b); - return IA_NEXT; -} -uint32_t IntCode_MIN_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = - std::min(ics.rf[i->src1_reg].f32, ics.rf[i->src2_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_MIN_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = - std::min(ics.rf[i->src1_reg].f64, ics.rf[i->src2_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_MIN_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = std::min(src1.f32[n], src2.f32[n]); - } - return IA_NEXT; -} -int Translate_MIN(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MIN_I8_I8, IntCode_MIN_I16_I16, IntCode_MIN_I32_I32, - IntCode_MIN_I64_I64, IntCode_MIN_F32_F32, IntCode_MIN_F64_F64, - IntCode_MIN_V128_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_MIN_I8_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = std::min(src1.u8[n], src2.u8[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MIN_I16_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = std::min(src1.u16[n], src2.u16[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MIN_I32_UNSIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = std::min(src1.u32[n], src2.u32[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MIN_I8_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = std::min((int8_t)src1.u8[n], (int8_t)src2.u8[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MIN_I16_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = std::min((int16_t)src1.u16[n], (int16_t)src2.u16[n]); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_MIN_I32_SIGNED(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = std::min((int32_t)src1.u32[n], (int32_t)src2.u32[n]); - } - return IA_NEXT; -} -int Translate_VECTOR_MIN(TranslationContext& ctx, Instr* i) { - static IntCodeFn unsigned_fns[] = { - IntCode_VECTOR_MIN_I8_UNSIGNED, IntCode_VECTOR_MIN_I16_UNSIGNED, - IntCode_VECTOR_MIN_I32_UNSIGNED, - }; - static IntCodeFn signed_fns[] = { - IntCode_VECTOR_MIN_I8_SIGNED, IntCode_VECTOR_MIN_I16_SIGNED, - IntCode_VECTOR_MIN_I32_SIGNED, - }; - uint32_t part_type = i->flags >> 8; - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, unsigned_fns[part_type]); - } else { - return DispatchToC(ctx, i, signed_fns[part_type]); - } -} - -uint32_t IntCode_SELECT_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = - ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].i8 : ics.rf[i->src3_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SELECT_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].i16 - : ics.rf[i->src3_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_SELECT_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].i32 - : ics.rf[i->src3_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_SELECT_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].i64 - : ics.rf[i->src3_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_SELECT_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].f32 - : ics.rf[i->src3_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_SELECT_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].f64 - : ics.rf[i->src3_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_SELECT_V128(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].v128 = ics.rf[i->src1_reg].i8 ? ics.rf[i->src2_reg].v128 - : ics.rf[i->src3_reg].v128; - return IA_NEXT; -} -int Translate_SELECT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_SELECT_I8, IntCode_SELECT_I16, IntCode_SELECT_I32, - IntCode_SELECT_I64, IntCode_SELECT_F32, IntCode_SELECT_F64, - IntCode_SELECT_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_IS_TRUE_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !!ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_IS_TRUE_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - ics.rf[i->dest_reg].i8 = src1.high && src1.low; - return IA_NEXT; -} -int Translate_IS_TRUE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_IS_TRUE_I8, IntCode_IS_TRUE_I16, IntCode_IS_TRUE_I32, - IntCode_IS_TRUE_I64, IntCode_IS_TRUE_F32, IntCode_IS_TRUE_F64, - IntCode_IS_TRUE_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_IS_FALSE_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = !ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_IS_FALSE_V128(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = - !(ics.rf[i->src1_reg].v128.high && ics.rf[i->src1_reg].v128.low); - return IA_NEXT; -} -int Translate_IS_FALSE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_IS_FALSE_I8, IntCode_IS_FALSE_I16, IntCode_IS_FALSE_I32, - IntCode_IS_FALSE_I64, IntCode_IS_FALSE_F32, IntCode_IS_FALSE_F64, - IntCode_IS_FALSE_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_EQ_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 == ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_EQ_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 == ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_EQ_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 == ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_EQ_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 == ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_EQ_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 == ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_EQ_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 == ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_EQ(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_EQ_I8_I8, IntCode_COMPARE_EQ_I16_I16, - IntCode_COMPARE_EQ_I32_I32, IntCode_COMPARE_EQ_I64_I64, - IntCode_COMPARE_EQ_F32_F32, IntCode_COMPARE_EQ_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_NE_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 != ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_NE_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 != ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_NE_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 != ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_NE_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 != ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_NE_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 != ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_NE_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 != ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_NE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_NE_I8_I8, IntCode_COMPARE_NE_I16_I16, - IntCode_COMPARE_NE_I32_I32, IntCode_COMPARE_NE_I64_I64, - IntCode_COMPARE_NE_F32_F32, IntCode_COMPARE_NE_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_SLT_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 < ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLT_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 < ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLT_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 < ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLT_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 < ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLT_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 < ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLT_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 < ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_SLT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_SLT_I8_I8, IntCode_COMPARE_SLT_I16_I16, - IntCode_COMPARE_SLT_I32_I32, IntCode_COMPARE_SLT_I64_I64, - IntCode_COMPARE_SLT_F32_F32, IntCode_COMPARE_SLT_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_SLE_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 <= ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLE_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 <= ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLE_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 <= ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLE_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 <= ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLE_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 <= ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SLE_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 <= ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_SLE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_SLE_I8_I8, IntCode_COMPARE_SLE_I16_I16, - IntCode_COMPARE_SLE_I32_I32, IntCode_COMPARE_SLE_I64_I64, - IntCode_COMPARE_SLE_F32_F32, IntCode_COMPARE_SLE_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_SGT_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 > ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGT_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 > ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGT_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 > ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGT_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 > ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGT_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 > ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGT_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 > ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_SGT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_SGT_I8_I8, IntCode_COMPARE_SGT_I16_I16, - IntCode_COMPARE_SGT_I32_I32, IntCode_COMPARE_SGT_I64_I64, - IntCode_COMPARE_SGT_F32_F32, IntCode_COMPARE_SGT_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_SGE_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 >= ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGE_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i16 >= ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGE_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i32 >= ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGE_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i64 >= ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGE_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 >= ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_SGE_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 >= ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_SGE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_SGE_I8_I8, IntCode_COMPARE_SGE_I16_I16, - IntCode_COMPARE_SGE_I32_I32, IntCode_COMPARE_SGE_I64_I64, - IntCode_COMPARE_SGE_F32_F32, IntCode_COMPARE_SGE_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_ULT_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u8 < ics.rf[i->src2_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULT_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u16 < ics.rf[i->src2_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULT_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u32 < ics.rf[i->src2_reg].u32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULT_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u64 < ics.rf[i->src2_reg].u64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULT_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 < ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULT_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 < ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_ULT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_ULT_I8_I8, IntCode_COMPARE_ULT_I16_I16, - IntCode_COMPARE_ULT_I32_I32, IntCode_COMPARE_ULT_I64_I64, - IntCode_COMPARE_ULT_F32_F32, IntCode_COMPARE_ULT_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_ULE_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u8 <= ics.rf[i->src2_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULE_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u16 <= ics.rf[i->src2_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULE_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u32 <= ics.rf[i->src2_reg].u32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULE_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u64 <= ics.rf[i->src2_reg].u64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULE_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 <= ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_ULE_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 <= ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_ULE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_ULE_I8_I8, IntCode_COMPARE_ULE_I16_I16, - IntCode_COMPARE_ULE_I32_I32, IntCode_COMPARE_ULE_I64_I64, - IntCode_COMPARE_ULE_F32_F32, IntCode_COMPARE_ULE_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_UGT_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u8 > ics.rf[i->src2_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGT_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u16 > ics.rf[i->src2_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGT_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u32 > ics.rf[i->src2_reg].u32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGT_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u64 > ics.rf[i->src2_reg].u64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGT_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 > ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGT_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 > ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_UGT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_UGT_I8_I8, IntCode_COMPARE_UGT_I16_I16, - IntCode_COMPARE_UGT_I32_I32, IntCode_COMPARE_UGT_I64_I64, - IntCode_COMPARE_UGT_F32_F32, IntCode_COMPARE_UGT_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_COMPARE_UGE_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u8 >= ics.rf[i->src2_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGE_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u16 >= ics.rf[i->src2_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGE_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u32 >= ics.rf[i->src2_reg].u32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGE_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u64 >= ics.rf[i->src2_reg].u64; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGE_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f32 >= ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_COMPARE_UGE_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].f64 >= ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_COMPARE_UGE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_COMPARE_UGE_I8_I8, IntCode_COMPARE_UGE_I16_I16, - IntCode_COMPARE_UGE_I32_I32, IntCode_COMPARE_UGE_I64_I64, - IntCode_COMPARE_UGE_F32_F32, IntCode_COMPARE_UGE_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_DID_CARRY(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.did_carry; - return IA_NEXT; -} -int Translate_DID_CARRY(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_DID_CARRY); -} - -uint32_t IntCode_DID_SATURATE(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.did_saturate; - return IA_NEXT; -} -int Translate_DID_SATURATE(TranslationContext& ctx, Instr* i) { - return DispatchToC(ctx, i, IntCode_DID_SATURATE); -} - -#define VECTOR_COMPARER(type, value, dest_type, dest_value, count, op) \ - const vec128_t& src1 = ics.rf[i->src1_reg].v128; \ - const vec128_t& src2 = ics.rf[i->src2_reg].v128; \ - vec128_t& dest = ics.rf[i->dest_reg].v128; \ - for (int n = 0; n < count; n++) { \ - dest.dest_value[n] = ((type)src1.value[n] op(type) src2.value[n]) \ - ? (dest_type)0xFFFFFFFF \ - : 0; \ - } \ - return IA_NEXT; - -uint32_t IntCode_VECTOR_COMPARE_EQ_I8(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint8_t, u8, uint8_t, u8, 16, == )}; -uint32_t IntCode_VECTOR_COMPARE_EQ_I16(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint16_t, u16, uint16_t, u16, 8, == )}; -uint32_t IntCode_VECTOR_COMPARE_EQ_I32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint32_t, u32, uint32_t, u32, 4, == )}; -uint32_t IntCode_VECTOR_COMPARE_EQ_F32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(float, f32, uint32_t, u32, 4, == )}; -int Translate_VECTOR_COMPARE_EQ(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_COMPARE_EQ_I8, IntCode_VECTOR_COMPARE_EQ_I16, - IntCode_VECTOR_COMPARE_EQ_I32, IntCode_INVALID_TYPE, - IntCode_VECTOR_COMPARE_EQ_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_VECTOR_COMPARE_SGT_I8(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int8_t, i8, int8_t, i8, 16, > )}; -uint32_t IntCode_VECTOR_COMPARE_SGT_I16(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int16_t, i16, int16_t, i16, 8, > )}; -uint32_t IntCode_VECTOR_COMPARE_SGT_I32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int32_t, i32, int32_t, i32, 4, > )}; -uint32_t IntCode_VECTOR_COMPARE_SGT_F32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(float, f32, uint32_t, u32, 4, > )}; -int Translate_VECTOR_COMPARE_SGT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_COMPARE_SGT_I8, IntCode_VECTOR_COMPARE_SGT_I16, - IntCode_VECTOR_COMPARE_SGT_I32, IntCode_INVALID_TYPE, - IntCode_VECTOR_COMPARE_SGT_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_VECTOR_COMPARE_SGE_I8(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int8_t, i8, int8_t, i8, 16, >= )}; -uint32_t IntCode_VECTOR_COMPARE_SGE_I16(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int16_t, i16, int16_t, i16, 8, >= )}; -uint32_t IntCode_VECTOR_COMPARE_SGE_I32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(int32_t, i32, int32_t, i32, 4, >= )}; -uint32_t IntCode_VECTOR_COMPARE_SGE_F32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(float, f32, uint32_t, u32, 4, >= )}; -int Translate_VECTOR_COMPARE_SGE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_COMPARE_SGE_I8, IntCode_VECTOR_COMPARE_SGE_I16, - IntCode_VECTOR_COMPARE_SGE_I32, IntCode_INVALID_TYPE, - IntCode_VECTOR_COMPARE_SGE_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_VECTOR_COMPARE_UGT_I8(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint8_t, u8, uint8_t, u8, 16, > )}; -uint32_t IntCode_VECTOR_COMPARE_UGT_I16(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint16_t, u16, uint16_t, u16, 8, > )}; -uint32_t IntCode_VECTOR_COMPARE_UGT_I32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint32_t, u32, uint32_t, u32, 4, > )}; -uint32_t IntCode_VECTOR_COMPARE_UGT_F32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(float, f32, uint32_t, u32, 4, > )}; -int Translate_VECTOR_COMPARE_UGT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_COMPARE_UGT_I8, IntCode_VECTOR_COMPARE_UGT_I16, - IntCode_VECTOR_COMPARE_UGT_I32, IntCode_INVALID_TYPE, - IntCode_VECTOR_COMPARE_UGT_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_VECTOR_COMPARE_UGE_I8(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint8_t, u8, uint8_t, u8, 16, >= )}; -uint32_t IntCode_VECTOR_COMPARE_UGE_I16(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint16_t, u16, uint16_t, u16, 8, >= )}; -uint32_t IntCode_VECTOR_COMPARE_UGE_I32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(uint32_t, u32, uint32_t, u32, 4, >= )}; -uint32_t IntCode_VECTOR_COMPARE_UGE_F32(IntCodeState& ics, const IntCode* i){ - VECTOR_COMPARER(float, f32, uint32_t, u32, 4, >= )}; -int Translate_VECTOR_COMPARE_UGE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_COMPARE_UGE_I8, IntCode_VECTOR_COMPARE_UGE_I16, - IntCode_VECTOR_COMPARE_UGE_I32, IntCode_INVALID_TYPE, - IntCode_VECTOR_COMPARE_UGE_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -#define CHECK_DID_CARRY(v1, v2) (((uint64_t)v2) > ~((uint64_t)v1)) -#define ADD_DID_CARRY(a, b) CHECK_DID_CARRY(a, b) -uint32_t IntCode_ADD_I8_I8(IntCodeState& ics, const IntCode* i) { - int8_t a = ics.rf[i->src1_reg].i8; - int8_t b = ics.rf[i->src2_reg].i8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i8 = a + b; - return IA_NEXT; -} -uint32_t IntCode_ADD_I16_I16(IntCodeState& ics, const IntCode* i) { - int16_t a = ics.rf[i->src1_reg].i16; - int16_t b = ics.rf[i->src2_reg].i16; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i16 = a + b; - return IA_NEXT; -} -uint32_t IntCode_ADD_I32_I32(IntCodeState& ics, const IntCode* i) { - int32_t a = ics.rf[i->src1_reg].i32; - int32_t b = ics.rf[i->src2_reg].i32; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i32 = a + b; - return IA_NEXT; -} -uint32_t IntCode_ADD_I64_I64(IntCodeState& ics, const IntCode* i) { - int64_t a = ics.rf[i->src1_reg].i64; - int64_t b = ics.rf[i->src2_reg].i64; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i64 = a + b; - return IA_NEXT; -} -uint32_t IntCode_ADD_F32_F32(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 + ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_ADD_F64_F64(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 + ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_ADD(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ADD_I8_I8, IntCode_ADD_I16_I16, IntCode_ADD_I32_I32, - IntCode_ADD_I64_I64, IntCode_ADD_F32_F32, IntCode_ADD_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -#define ADD_CARRY_DID_CARRY(a, b, c) \ - (CHECK_DID_CARRY(a, b) || ((c) != 0) && CHECK_DID_CARRY((a) + (b), c)) -uint32_t IntCode_ADD_CARRY_I8_I8(IntCodeState& ics, const IntCode* i) { - int8_t a = ics.rf[i->src1_reg].i8; - int8_t b = ics.rf[i->src2_reg].i8; - uint8_t c = ics.rf[i->src3_reg].u8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_CARRY_DID_CARRY(a, b, c); - } - ics.rf[i->dest_reg].i8 = a + b + c; - return IA_NEXT; -} -uint32_t IntCode_ADD_CARRY_I16_I16(IntCodeState& ics, const IntCode* i) { - int16_t a = ics.rf[i->src1_reg].i16; - int16_t b = ics.rf[i->src2_reg].i16; - uint8_t c = ics.rf[i->src3_reg].u8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_CARRY_DID_CARRY(a, b, c); - } - ics.rf[i->dest_reg].i16 = a + b + c; - return IA_NEXT; -} -uint32_t IntCode_ADD_CARRY_I32_I32(IntCodeState& ics, const IntCode* i) { - int32_t a = ics.rf[i->src1_reg].i32; - int32_t b = ics.rf[i->src2_reg].i32; - uint8_t c = ics.rf[i->src3_reg].u8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_CARRY_DID_CARRY(a, b, c); - } - ics.rf[i->dest_reg].i32 = a + b + c; - return IA_NEXT; -} -uint32_t IntCode_ADD_CARRY_I64_I64(IntCodeState& ics, const IntCode* i) { - int64_t a = ics.rf[i->src1_reg].i64; - int64_t b = ics.rf[i->src2_reg].i64; - uint8_t c = ics.rf[i->src3_reg].u8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = ADD_CARRY_DID_CARRY(a, b, c); - } - ics.rf[i->dest_reg].i64 = a + b + c; - return IA_NEXT; -} -uint32_t IntCode_ADD_CARRY_F32_F32(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 + ics.rf[i->src2_reg].f32 + - ics.rf[i->src3_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_ADD_CARRY_F64_F64(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 + ics.rf[i->src2_reg].f64 + - ics.rf[i->src3_reg].i8; - return IA_NEXT; -} -int Translate_ADD_CARRY(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ADD_CARRY_I8_I8, IntCode_ADD_CARRY_I16_I16, - IntCode_ADD_CARRY_I32_I32, IntCode_ADD_CARRY_I64_I64, - IntCode_ADD_CARRY_F32_F32, IntCode_ADD_CARRY_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t Translate_VECTOR_ADD_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - const uint32_t arithmetic_flags = i->flags >> 8; - if (arithmetic_flags & ARITHMETIC_SATURATE) { - if (arithmetic_flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 16; n++) { - uint16_t v = src1.u8[n] + src2.u8[n]; - if (v > 0xFF) { - dest.u8[n] = 0xFF; - ics.did_saturate = 1; - } else { - dest.u8[n] = (uint8_t)v; - } - } - } else { - for (int n = 0; n < 16; n++) { - int16_t v = (int8_t)src1.u8[n] + (int8_t)src2.u8[n]; - if (v > 0x7F) { - dest.u8[n] = 0x7F; - ics.did_saturate = 1; - } else if (v < -0x80) { - dest.u8[n] = -0x80; - ics.did_saturate = 1; - } else { - dest.u8[n] = (uint8_t)v; - } - } - } - } else { - for (int n = 0; n < 16; n++) { - dest.u8[n] = src1.u8[n] + src2.u8[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_ADD_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - const uint32_t arithmetic_flags = i->flags >> 8; - if (arithmetic_flags & ARITHMETIC_SATURATE) { - if (arithmetic_flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 8; n++) { - uint32_t v = src1.u16[n] + src2.u16[n]; - if (v > 0xFFFF) { - dest.u16[n] = 0xFFFF; - ics.did_saturate = 1; - } else { - dest.u16[n] = (uint16_t)v; - } - } - } else { - for (int n = 0; n < 8; n++) { - int32_t v = (int16_t)src1.u16[n] + (int16_t)src2.u16[n]; - if (v > 0x7FFF) { - dest.u16[n] = 0x7FFF; - ics.did_saturate = 1; - } else if (v < -0x8000) { - dest.u16[n] = -0x8000; - ics.did_saturate = 1; - } else { - dest.u16[n] = (uint16_t)v; - } - } - } - } else { - for (int n = 0; n < 8; n++) { - dest.u16[n] = src1.u16[n] + src2.u16[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_ADD_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - const uint32_t arithmetic_flags = i->flags >> 8; - if (arithmetic_flags & ARITHMETIC_SATURATE) { - if (arithmetic_flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 4; n++) { - uint64_t v = (uint64_t)src1.u32[n] + (uint64_t)src2.u32[n]; - if (v > 0xFFFFFFFF) { - dest.u32[n] = 0xFFFFFFFF; - ics.did_saturate = 1; - } else { - dest.u32[n] = (uint32_t)v; - } - } - } else { - for (int n = 0; n < 4; n++) { - int64_t v = - (int64_t)(int32_t)src1.u32[n] + (int64_t)(int32_t)src2.u32[n]; - if (v > 0x7FFFFFFF) { - dest.u32[n] = 0x7FFFFFFF; - ics.did_saturate = 1; - } else if (v < -0x80000000ll) { - dest.u32[n] = 0x80000000; - ics.did_saturate = 1; - } else { - dest.u32[n] = (uint32_t)v; - } - } - } - } else { - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] + src2.u32[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_ADD_F32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] + src2.f32[n]; - } - return IA_NEXT; -} -int Translate_VECTOR_ADD(TranslationContext& ctx, Instr* i) { - TypeName part_type = (TypeName)(i->flags & 0xFF); - static IntCodeFn fns[] = { - Translate_VECTOR_ADD_I8, Translate_VECTOR_ADD_I16, - Translate_VECTOR_ADD_I32, IntCode_INVALID_TYPE, - Translate_VECTOR_ADD_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[part_type]); -} - -#define SUB_DID_CARRY(a, b) ((b) == 0) || CHECK_DID_CARRY(a, 0 - b) -uint32_t IntCode_SUB_I8_I8(IntCodeState& ics, const IntCode* i) { - int8_t a = ics.rf[i->src1_reg].i8; - int8_t b = ics.rf[i->src2_reg].i8; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = SUB_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i8 = a - b; - return IA_NEXT; -} -uint32_t IntCode_SUB_I16_I16(IntCodeState& ics, const IntCode* i) { - int16_t a = ics.rf[i->src1_reg].i16; - int16_t b = ics.rf[i->src2_reg].i16; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = SUB_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i16 = a - b; - return IA_NEXT; -} -uint32_t IntCode_SUB_I32_I32(IntCodeState& ics, const IntCode* i) { - int32_t a = ics.rf[i->src1_reg].i32; - int32_t b = ics.rf[i->src2_reg].i32; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = SUB_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i32 = a - b; - return IA_NEXT; -} -uint32_t IntCode_SUB_I64_I64(IntCodeState& ics, const IntCode* i) { - int64_t a = ics.rf[i->src1_reg].i64; - int64_t b = ics.rf[i->src2_reg].i64; - if (i->flags == ARITHMETIC_SET_CARRY) { - ics.did_carry = SUB_DID_CARRY(a, b); - } - ics.rf[i->dest_reg].i64 = a - b; - return IA_NEXT; -} -uint32_t IntCode_SUB_F32_F32(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 - ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_SUB_F64_F64(IntCodeState& ics, const IntCode* i) { - assert_true(!i->flags); - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 - ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -int Translate_SUB(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_SUB_I8_I8, IntCode_SUB_I16_I16, IntCode_SUB_I32_I32, - IntCode_SUB_I64_I64, IntCode_SUB_F32_F32, IntCode_SUB_F64_F64, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t Translate_VECTOR_SUB_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - uint32_t flags = i->flags >> 8; - // assert_zero(flags & ARITHMETIC_SATURATE); - if (flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 16; n++) { - dest.u8[n] = src1.u8[n] - src2.u8[n]; - } - } else { - for (int n = 0; n < 16; n++) { - dest.i8[n] = src1.i8[n] - src2.i8[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_SUB_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - uint32_t flags = i->flags >> 8; - // assert_zero(flags & ARITHMETIC_SATURATE); - if (flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 8; n++) { - dest.u16[n] = src1.u16[n] - src2.u16[n]; - } - } else { - for (int n = 0; n < 8; n++) { - dest.i16[n] = src1.i16[n] - src2.i16[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_SUB_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - uint32_t flags = i->flags >> 8; - // assert_zero(flags & ARITHMETIC_SATURATE); - if (flags & ARITHMETIC_UNSIGNED) { - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] - src2.u32[n]; - } - } else { - for (int n = 0; n < 4; n++) { - dest.i32[n] = src1.i32[n] - src2.i32[n]; - } - } - return IA_NEXT; -} -uint32_t Translate_VECTOR_SUB_F32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - uint32_t flags = i->flags >> 8; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] - src2.f32[n]; - } - return IA_NEXT; -} -int Translate_VECTOR_SUB(TranslationContext& ctx, Instr* i) { - TypeName part_type = (TypeName)(i->flags & 0xFF); - static IntCodeFn fns[] = { - Translate_VECTOR_SUB_I8, Translate_VECTOR_SUB_I16, - Translate_VECTOR_SUB_I32, IntCode_INVALID_TYPE, - Translate_VECTOR_SUB_F32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[part_type]); -} - -uint32_t IntCode_MUL_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 * ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_MUL_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 * ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_MUL_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 * ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_MUL_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 * ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_MUL_F32_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 * ics.rf[i->src2_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_MUL_F64_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 * ics.rf[i->src2_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_MUL_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] * src2.f32[n]; - } - return IA_NEXT; -} -uint32_t IntCode_MUL_I8_I8_U(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].u8 = ics.rf[i->src1_reg].u8 * ics.rf[i->src2_reg].u8; - return IA_NEXT; -} -uint32_t IntCode_MUL_I16_I16_U(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].u16 = ics.rf[i->src1_reg].u16 * ics.rf[i->src2_reg].u16; - return IA_NEXT; -} -uint32_t IntCode_MUL_I32_I32_U(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].u32 = ics.rf[i->src1_reg].u32 * ics.rf[i->src2_reg].u32; - return IA_NEXT; -} -uint32_t IntCode_MUL_I64_I64_U(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].u64 = ics.rf[i->src1_reg].u64 * ics.rf[i->src2_reg].u64; - return IA_NEXT; -} -int Translate_MUL(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MUL_I8_I8, IntCode_MUL_I16_I16, IntCode_MUL_I32_I32, - IntCode_MUL_I64_I64, IntCode_MUL_F32_F32, IntCode_MUL_F64_F64, - IntCode_MUL_V128_V128, - }; - static IntCodeFn fns_unsigned[] = { - IntCode_MUL_I8_I8_U, IntCode_MUL_I16_I16_U, IntCode_MUL_I32_I32_U, - IntCode_MUL_I64_I64_U, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, fns_unsigned[i->dest->type]); - } else { - return DispatchToC(ctx, i, fns[i->dest->type]); - } -} - -#if XE_COMPILER_MSVC -uint64_t Mul128(uint64_t xi_low, uint64_t xi_high, uint64_t yi_low, - uint64_t yi_high) { -// 128bit multiply, simplified for two input 64bit integers. -// http://mrob.com/pub/math/int128.c.txt -#define HI_WORD 0xFFFFFFFF00000000LL -#define LO_WORD 0x00000000FFFFFFFFLL - uint64_t d = xi_low & LO_WORD; - uint64_t c = (xi_low & HI_WORD) >> 32LL; - uint64_t b = xi_high & LO_WORD; - uint64_t a = (xi_high & HI_WORD) >> 32LL; - uint64_t h = yi_low & LO_WORD; - uint64_t g = (yi_low & HI_WORD) >> 32LL; - uint64_t f = yi_high & LO_WORD; - uint64_t e = (yi_high & HI_WORD) >> 32LL; - uint64_t acc = d * h; - acc >>= 32LL; - uint64_t carry = 0; - - uint64_t ac2 = acc + c * h; - if (ac2 < acc) { - carry++; - } - acc = ac2 + d * g; - if (acc < ac2) { - carry++; - } - ac2 = (acc >> 32LL) | (carry << 32LL); - carry = 0; - - acc = ac2 + b * h; - if (acc < ac2) { - carry++; - } - ac2 = acc + c * g; - if (ac2 < acc) { - carry++; - } - acc = ac2 + d * f; - if (acc < ac2) { - carry++; - } - uint64_t o2 = acc & LO_WORD; - ac2 = (acc >> 32LL) | (carry << 32LL); - - acc = ac2 + a * h; - ac2 = acc + b * g; - acc = ac2 + c * f; - ac2 = acc + d * e; - uint64_t rv2_hi = (ac2 << 32LL) | o2; - - return rv2_hi; -} -#endif // !XE_COMPILER_MSVC - -uint32_t IntCode_MUL_HI_I8_I8(IntCodeState& ics, const IntCode* i) { - int16_t v = (int16_t)ics.rf[i->src1_reg].i8 * (int16_t)ics.rf[i->src2_reg].i8; - ics.rf[i->dest_reg].i8 = (v >> 8); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I16_I16(IntCodeState& ics, const IntCode* i) { - int32_t v = - (int32_t)ics.rf[i->src1_reg].i16 * (int32_t)ics.rf[i->src2_reg].i16; - ics.rf[i->dest_reg].i16 = (v >> 16); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I32_I32(IntCodeState& ics, const IntCode* i) { - int64_t v = - (int64_t)ics.rf[i->src1_reg].i32 * (int64_t)ics.rf[i->src2_reg].i32; - ics.rf[i->dest_reg].i32 = (v >> 32); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I64_I64(IntCodeState& ics, const IntCode* i) { -#if !XE_COMPILER_MSVC - // GCC can, in theory, do this: - __int128 v = - (__int128)ics.rf[i->src1_reg].i64 * (__int128)ics.rf[i->src2_reg].i64; - ics.rf[i->dest_reg].i64 = (v >> 64); -#else - // 128bit multiply, simplified for two input 64bit integers. - // http://mrob.com/pub/math/int128.c.txt - int64_t xi_low = ics.rf[i->src1_reg].i64; - int64_t xi_high = xi_low < 0 ? -1 : 0; - int64_t yi_low = ics.rf[i->src2_reg].i64; - int64_t yi_high = yi_low < 0 ? -1 : 0; - ics.rf[i->dest_reg].i64 = Mul128(xi_low, xi_high, yi_low, yi_high); -#endif // !MSVC - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I8_I8_U(IntCodeState& ics, const IntCode* i) { - uint16_t v = - (uint16_t)ics.rf[i->src1_reg].u8 * (uint16_t)ics.rf[i->src2_reg].u8; - ics.rf[i->dest_reg].u8 = (v >> 8); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I16_I16_U(IntCodeState& ics, const IntCode* i) { - uint32_t v = - (uint32_t)ics.rf[i->src1_reg].u16 * (uint32_t)ics.rf[i->src2_reg].u16; - ics.rf[i->dest_reg].u16 = (v >> 16); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I32_I32_U(IntCodeState& ics, const IntCode* i) { - uint64_t v = - (uint64_t)ics.rf[i->src1_reg].u32 * (uint64_t)ics.rf[i->src2_reg].u32; - ics.rf[i->dest_reg].u32 = (v >> 32); - return IA_NEXT; -} -uint32_t IntCode_MUL_HI_I64_I64_U(IntCodeState& ics, const IntCode* i) { -#if !XE_COMPILER_MSVC - // GCC can, in theory, do this: - __int128 v = - (__int128)ics.rf[i->src1_reg].i64 * (__int128)ics.rf[i->src2_reg].i64; - ics.rf[i->dest_reg].i64 = (v >> 64); -#else - // 128bit multiply, simplified for two input 64bit integers. - // http://mrob.com/pub/math/int128.c.txt - int64_t xi_low = ics.rf[i->src1_reg].i64; - int64_t xi_high = 0; - int64_t yi_low = ics.rf[i->src2_reg].i64; - int64_t yi_high = 0; - ics.rf[i->dest_reg].i64 = Mul128(xi_low, xi_high, yi_low, yi_high); -#endif // !MSVC - return IA_NEXT; -} -int Translate_MUL_HI(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MUL_HI_I8_I8, IntCode_MUL_HI_I16_I16, IntCode_MUL_HI_I32_I32, - IntCode_MUL_HI_I64_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - static IntCodeFn fns_unsigned[] = { - IntCode_MUL_HI_I8_I8_U, IntCode_MUL_HI_I16_I16_U, - IntCode_MUL_HI_I32_I32_U, IntCode_MUL_HI_I64_I64_U, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, fns_unsigned[i->dest->type]); - } else { - return DispatchToC(ctx, i, fns[i->dest->type]); - } -} - -uint32_t IntCode_DIV_I8_I8(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].i8; - ics.rf[i->dest_reg].i8 = divisor ? ics.rf[i->src1_reg].i8 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I16_I16(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].i16; - ics.rf[i->dest_reg].i16 = divisor ? ics.rf[i->src1_reg].i16 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I32_I32(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].i32; - ics.rf[i->dest_reg].i32 = divisor ? ics.rf[i->src1_reg].i32 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I64_I64(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].i64; - ics.rf[i->dest_reg].i64 = divisor ? ics.rf[i->src1_reg].i64 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_F32_F32(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].f32; - ics.rf[i->dest_reg].f32 = divisor ? ics.rf[i->src1_reg].f32 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_F64_F64(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].f64; - ics.rf[i->dest_reg].f64 = divisor ? ics.rf[i->src1_reg].f64 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] / src2.f32[n]; - } - return IA_NEXT; -} -uint32_t IntCode_DIV_I8_I8_U(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].u8; - ics.rf[i->dest_reg].u8 = divisor ? ics.rf[i->src1_reg].u8 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I16_I16_U(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].u16; - ics.rf[i->dest_reg].u16 = divisor ? ics.rf[i->src1_reg].u16 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I32_I32_U(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].u32; - ics.rf[i->dest_reg].u32 = divisor ? ics.rf[i->src1_reg].u32 / divisor : 0; - return IA_NEXT; -} -uint32_t IntCode_DIV_I64_I64_U(IntCodeState& ics, const IntCode* i) { - auto divisor = ics.rf[i->src2_reg].u64; - ics.rf[i->dest_reg].u64 = divisor ? ics.rf[i->src1_reg].u64 / divisor : 0; - return IA_NEXT; -} -int Translate_DIV(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_DIV_I8_I8, IntCode_DIV_I16_I16, IntCode_DIV_I32_I32, - IntCode_DIV_I64_I64, IntCode_DIV_F32_F32, IntCode_DIV_F64_F64, - IntCode_DIV_V128_V128, - }; - static IntCodeFn fns_unsigned[] = { - IntCode_DIV_I8_I8_U, IntCode_DIV_I16_I16_U, IntCode_DIV_I32_I32_U, - IntCode_DIV_I64_I64_U, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - if (i->flags & ARITHMETIC_UNSIGNED) { - return DispatchToC(ctx, i, fns_unsigned[i->dest->type]); - } else { - return DispatchToC(ctx, i, fns[i->dest->type]); - } -} - -// TODO(benvanik): use intrinsics or something -uint32_t IntCode_MUL_ADD_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = - ics.rf[i->src1_reg].i8 * ics.rf[i->src2_reg].i8 + ics.rf[i->src3_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 * ics.rf[i->src2_reg].i16 + - ics.rf[i->src3_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 * ics.rf[i->src2_reg].i32 + - ics.rf[i->src3_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 * ics.rf[i->src2_reg].i64 + - ics.rf[i->src3_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 * ics.rf[i->src2_reg].f32 + - ics.rf[i->src3_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 * ics.rf[i->src2_reg].f64 + - ics.rf[i->src3_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_MUL_ADD_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - const vec128_t& src3 = ics.rf[i->src3_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] * src2.f32[n] + src3.f32[n]; - } - return IA_NEXT; -} -int Translate_MUL_ADD(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MUL_ADD_I8, IntCode_MUL_ADD_I16, IntCode_MUL_ADD_I32, - IntCode_MUL_ADD_I64, IntCode_MUL_ADD_F32, IntCode_MUL_ADD_F64, - IntCode_MUL_ADD_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -// TODO(benvanik): use intrinsics or something -uint32_t IntCode_MUL_SUB_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = - ics.rf[i->src1_reg].i8 * ics.rf[i->src2_reg].i8 - ics.rf[i->src3_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 * ics.rf[i->src2_reg].i16 - - ics.rf[i->src3_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 * ics.rf[i->src2_reg].i32 - - ics.rf[i->src3_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 * ics.rf[i->src2_reg].i64 - - ics.rf[i->src3_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = ics.rf[i->src1_reg].f32 * ics.rf[i->src2_reg].f32 - - ics.rf[i->src3_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = ics.rf[i->src1_reg].f64 * ics.rf[i->src2_reg].f64 - - ics.rf[i->src3_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_MUL_SUB_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - const vec128_t& src3 = ics.rf[i->src3_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = src1.f32[n] * src2.f32[n] - src3.f32[n]; - } - return IA_NEXT; -} -int Translate_MUL_SUB(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_MUL_SUB_I8, IntCode_MUL_SUB_I16, IntCode_MUL_SUB_I32, - IntCode_MUL_SUB_I64, IntCode_MUL_SUB_F32, IntCode_MUL_SUB_F64, - IntCode_MUL_SUB_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_NEG_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = -ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_NEG_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = -ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_NEG_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = -ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_NEG_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = -ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_NEG_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = -ics.rf[i->src1_reg].f32; - return IA_NEXT; -} -uint32_t IntCode_NEG_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = -ics.rf[i->src1_reg].f64; - return IA_NEXT; -} -uint32_t IntCode_NEG_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = -src1.f32[j]; - } - return IA_NEXT; -} -int Translate_NEG(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_NEG_I8, IntCode_NEG_I16, IntCode_NEG_I32, IntCode_NEG_I64, - IntCode_NEG_F32, IntCode_NEG_F64, IntCode_NEG_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_ABS_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = abs(ics.rf[i->src1_reg].i8); - return IA_NEXT; -} -uint32_t IntCode_ABS_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = abs(ics.rf[i->src1_reg].i16); - return IA_NEXT; -} -uint32_t IntCode_ABS_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = abs(ics.rf[i->src1_reg].i32); - return IA_NEXT; -} -uint32_t IntCode_ABS_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = abs(ics.rf[i->src1_reg].i64); - return IA_NEXT; -} -uint32_t IntCode_ABS_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = abs(ics.rf[i->src1_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_ABS_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = abs(ics.rf[i->src1_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_ABS_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = abs(src1.f32[j]); - } - return IA_NEXT; -} -int Translate_ABS(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ABS_I8, IntCode_ABS_I16, IntCode_ABS_I32, IntCode_ABS_I64, - IntCode_ABS_F32, IntCode_ABS_F64, IntCode_ABS_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_DOT_PRODUCT_3_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - ics.rf[i->dest_reg].f32 = - (src1.x * src2.x) + (src1.y * src2.y) + (src1.z * src2.z); - return IA_NEXT; -} -int Translate_DOT_PRODUCT_3(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_DOT_PRODUCT_3_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_DOT_PRODUCT_4_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - ics.rf[i->dest_reg].f32 = (src1.x * src2.x) + (src1.y * src2.y) + - (src1.z * src2.z) + (src1.w * src2.w); - return IA_NEXT; -} -int Translate_DOT_PRODUCT_4(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_DOT_PRODUCT_4_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_SQRT_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = sqrt(ics.rf[i->src1_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_SQRT_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = sqrt(ics.rf[i->src1_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_SQRT_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = sqrt(src1.f32[j]); - } - return IA_NEXT; -} -int Translate_SQRT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_SQRT_F32, IntCode_SQRT_F64, - IntCode_SQRT_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_RSQRT_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.f32[n] = 1 / sqrtf(src1.f32[n]); - } - return IA_NEXT; -} -int Translate_RSQRT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_RSQRT_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_POW2_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = (float)pow(2, ics.rf[i->src1_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_POW2_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = pow(2, ics.rf[i->src1_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_POW2_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = (float)pow(2, src1.f32[j]); - } - return IA_NEXT; -} -int Translate_POW2(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_POW2_F32, IntCode_POW2_F64, - IntCode_POW2_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_LOG2_F32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f32 = log2(ics.rf[i->src1_reg].f32); - return IA_NEXT; -} -uint32_t IntCode_LOG2_F64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].f64 = log2(ics.rf[i->src1_reg].f64); - return IA_NEXT; -} -uint32_t IntCode_LOG2_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = log2(src1.f32[j]); - } - return IA_NEXT; -} -int Translate_LOG2(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_LOG2_F32, IntCode_LOG2_F64, - IntCode_LOG2_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_AND_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 & ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_AND_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 & ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_AND_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 & ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_AND_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 & ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_AND_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] & src2.u32[n]; - } - return IA_NEXT; -} -int Translate_AND(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_AND_I8_I8, IntCode_AND_I16_I16, IntCode_AND_I32_I32, - IntCode_AND_I64_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_AND_V128_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_OR_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 | ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_OR_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 | ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_OR_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 | ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_OR_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 | ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_OR_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] | src2.u32[n]; - } - return IA_NEXT; -} -int Translate_OR(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_OR_I8_I8, IntCode_OR_I16_I16, IntCode_OR_I32_I32, - IntCode_OR_I64_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_OR_V128_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_XOR_I8_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 ^ ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_XOR_I16_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 ^ ics.rf[i->src2_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_XOR_I32_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 ^ ics.rf[i->src2_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_XOR_I64_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 ^ ics.rf[i->src2_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_XOR_V128_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] ^ src2.u32[n]; - } - return IA_NEXT; -} -int Translate_XOR(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_XOR_I8_I8, IntCode_XOR_I16_I16, IntCode_XOR_I32_I32, - IntCode_XOR_I64_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_XOR_V128_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_NOT_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ~ics.rf[i->src1_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_NOT_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ~ics.rf[i->src1_reg].i16; - return IA_NEXT; -} -uint32_t IntCode_NOT_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ~ics.rf[i->src1_reg].i32; - return IA_NEXT; -} -uint32_t IntCode_NOT_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ~ics.rf[i->src1_reg].i64; - return IA_NEXT; -} -uint32_t IntCode_NOT_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = ~src1.u32[n]; - } - return IA_NEXT; -} -int Translate_NOT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_NOT_I8, IntCode_NOT_I16, IntCode_NOT_I32, - IntCode_NOT_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_NOT_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_SHL_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 << ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHL_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 << ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHL_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 << ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHL_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 << ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -int Translate_SHL(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_SHL_I8, IntCode_SHL_I16, IntCode_SHL_I32, - IntCode_SHL_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_SHL_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = src1.u8[n] << (src2.u8[n] & 0x7); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHL_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = src1.u16[n] << (src2.u16[n] & 0xF); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHL_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] << (src2.u32[n] & 0x1F); - } - return IA_NEXT; -} -int Translate_VECTOR_SHL(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_SHL_I8, IntCode_VECTOR_SHL_I16, IntCode_VECTOR_SHL_I32, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_SHR_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].u8 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHR_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].u16 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHR_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].u32 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHR_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].u64 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -int Translate_SHR(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_SHR_I8, IntCode_SHR_I16, IntCode_SHR_I32, - IntCode_SHR_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_SHR_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = src1.u8[n] >> (src2.u8[n] & 0x7); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHR_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = src1.u16[n] >> (src2.u16[n] & 0xF); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHR_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = src1.u32[n] >> (src2.u32[n] & 0x1F); - } - return IA_NEXT; -} -int Translate_VECTOR_SHR(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_SHR_I8, IntCode_VECTOR_SHR_I16, IntCode_VECTOR_SHR_I32, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_SHA_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHA_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = ics.rf[i->src1_reg].i16 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHA_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = ics.rf[i->src1_reg].i32 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -uint32_t IntCode_SHA_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = ics.rf[i->src1_reg].i64 >> ics.rf[i->src2_reg].i8; - return IA_NEXT; -} -int Translate_SHA(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_SHA_I8, IntCode_SHA_I16, IntCode_SHA_I32, - IntCode_SHA_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_SHA_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = int8_t(src1.u8[n]) >> (src2.u8[n] & 0x7); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHA_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = int16_t(src1.u16[n]) >> (src2.u16[n] & 0xF); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_SHA_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = int32_t(src1.u32[n]) >> (src2.u32[n] & 0x1F); - } - return IA_NEXT; -} -int Translate_VECTOR_SHA(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_SHA_I8, IntCode_VECTOR_SHA_I16, IntCode_VECTOR_SHA_I32, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_ROTATE_LEFT_I8(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = poly::rotate_left(ics.rf[i->src1_reg].i8, - ics.rf[i->src2_reg].i8); - return IA_NEXT; -} -uint32_t IntCode_ROTATE_LEFT_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = poly::rotate_left(ics.rf[i->src1_reg].i16, - ics.rf[i->src2_reg].i8); - return IA_NEXT; -} -uint32_t IntCode_ROTATE_LEFT_I32(IntCodeState& ics, const IntCode* i) { - // TODO(benvanik): use _rtol on vc++ - ics.rf[i->dest_reg].i32 = poly::rotate_left(ics.rf[i->src1_reg].i32, - ics.rf[i->src2_reg].i8); - return IA_NEXT; -} -uint32_t IntCode_ROTATE_LEFT_I64(IntCodeState& ics, const IntCode* i) { - // TODO(benvanik): use _rtol64 on vc++ - ics.rf[i->dest_reg].i64 = poly::rotate_left(ics.rf[i->src1_reg].i64, - ics.rf[i->src2_reg].i8); - return IA_NEXT; -} -int Translate_ROTATE_LEFT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_ROTATE_LEFT_I8, IntCode_ROTATE_LEFT_I16, IntCode_ROTATE_LEFT_I32, - IntCode_ROTATE_LEFT_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_VECTOR_ROTATE_LEFT_I8(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 16; n++) { - dest.u8[n] = poly::rotate_left(src1.u8[n], src2.u8[n] & 0x7); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_ROTATE_LEFT_I16(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 8; n++) { - dest.u16[n] = poly::rotate_left(src1.u16[n], src2.u16[n] & 0xF); - } - return IA_NEXT; -} -uint32_t IntCode_VECTOR_ROTATE_LEFT_I32(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = poly::rotate_left(src1.u32[n], src2.u32[n] & 0x1F); - } - return IA_NEXT; -} -int Translate_VECTOR_ROTATE_LEFT(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_VECTOR_ROTATE_LEFT_I8, IntCode_VECTOR_ROTATE_LEFT_I16, - IntCode_VECTOR_ROTATE_LEFT_I32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_BYTE_SWAP_I16(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i16 = poly::byte_swap(ics.rf[i->src1_reg].i16); - return IA_NEXT; -} -uint32_t IntCode_BYTE_SWAP_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i32 = poly::byte_swap(ics.rf[i->src1_reg].i32); - return IA_NEXT; -} -uint32_t IntCode_BYTE_SWAP_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i64 = poly::byte_swap(ics.rf[i->src1_reg].i64); - return IA_NEXT; -} -uint32_t IntCode_BYTE_SWAP_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (int n = 0; n < 4; n++) { - dest.u32[n] = poly::byte_swap(src1.u32[n]); - } - return IA_NEXT; -} -int Translate_BYTE_SWAP(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_BYTE_SWAP_I16, IntCode_BYTE_SWAP_I32, - IntCode_BYTE_SWAP_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_BYTE_SWAP_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); -} - -uint32_t IntCode_CNTLZ_I8(IntCodeState& ics, const IntCode* i) { - // CHECK - assert_always(); - ics.rf[i->dest_reg].i8 = poly::lzcnt(ics.rf[i->src1_reg].i8); - return IA_NEXT; -} -uint32_t IntCode_CNTLZ_I16(IntCodeState& ics, const IntCode* i) { - // CHECK - assert_always(); - ics.rf[i->dest_reg].i8 = poly::lzcnt(ics.rf[i->src1_reg].i16); - return IA_NEXT; -} -uint32_t IntCode_CNTLZ_I32(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = poly::lzcnt(ics.rf[i->src1_reg].i32); - return IA_NEXT; -} -uint32_t IntCode_CNTLZ_I64(IntCodeState& ics, const IntCode* i) { - ics.rf[i->dest_reg].i8 = poly::lzcnt(ics.rf[i->src1_reg].i64); - return IA_NEXT; -} -int Translate_CNTLZ(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_CNTLZ_I8, IntCode_CNTLZ_I16, IntCode_CNTLZ_I32, - IntCode_CNTLZ_I64, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_EXTRACT_INT8_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - ics.rf[i->dest_reg].i8 = src1.i8[ics.rf[i->src2_reg].i8 ^ 0x3]; - return IA_NEXT; -} -uint32_t IntCode_EXTRACT_INT16_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - ics.rf[i->dest_reg].i16 = src1.i16[ics.rf[i->src2_reg].i8 ^ 0x1]; - return IA_NEXT; -} -uint32_t IntCode_EXTRACT_INT32_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - ics.rf[i->dest_reg].i32 = src1.i32[ics.rf[i->src2_reg].i8]; - return IA_NEXT; -} -int Translate_EXTRACT(TranslationContext& ctx, Instr* i) { - // Can do more as needed. - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_EXTRACT_INT8_V128, IntCode_EXTRACT_INT16_V128, - IntCode_EXTRACT_INT32_V128, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_INSERT_INT8_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const size_t offset = ics.rf[i->src2_reg].i64; - const uint8_t part = ics.rf[i->src3_reg].i8; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest = src1; - dest.u8[offset ^ 0x3] = part; - return IA_NEXT; -} -uint32_t IntCode_INSERT_INT16_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const size_t offset = ics.rf[i->src2_reg].i64; - const uint16_t part = ics.rf[i->src3_reg].i16; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest = src1; - dest.u16[offset ^ 0x1] = part; - return IA_NEXT; -} -uint32_t IntCode_INSERT_INT32_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - const size_t offset = ics.rf[i->src2_reg].i64; - const uint32_t part = ics.rf[i->src3_reg].i32; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest = src1; - dest.u32[offset] = part; - return IA_NEXT; -} -int Translate_INSERT(TranslationContext& ctx, Instr* i) { - // Can do more as needed. - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INSERT_INT8_V128, IntCode_INSERT_INT16_V128, - IntCode_INSERT_INT32_V128, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->src3.value->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_SPLAT_V128_INT8(IntCodeState& ics, const IntCode* i) { - int8_t src1 = ics.rf[i->src1_reg].i8; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 16; j++) { - dest.u8[j] = src1; - } - return IA_NEXT; -} -uint32_t IntCode_SPLAT_V128_INT16(IntCodeState& ics, const IntCode* i) { - int16_t src1 = ics.rf[i->src1_reg].i16; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 8; j++) { - dest.u16[j] = src1; - } - return IA_NEXT; -} -uint32_t IntCode_SPLAT_V128_INT32(IntCodeState& ics, const IntCode* i) { - int32_t src1 = ics.rf[i->src1_reg].i32; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.u32[j] = src1; - } - return IA_NEXT; -} -uint32_t IntCode_SPLAT_V128_FLOAT32(IntCodeState& ics, const IntCode* i) { - float src1 = ics.rf[i->src1_reg].f32; - vec128_t& dest = ics.rf[i->dest_reg].v128; - for (size_t j = 0; j < 4; j++) { - dest.f32[j] = src1; - } - return IA_NEXT; -} -int Translate_SPLAT(TranslationContext& ctx, Instr* i) { - // Can do more as needed. - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_SPLAT_V128_INT8, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_SPLAT_V128_INT16, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_SPLAT_V128_INT32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_SPLAT_V128_FLOAT32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_PERMUTE_V128_BY_INT32(IntCodeState& ics, const IntCode* i) { - uint32_t table = ics.rf[i->src1_reg].i32; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - const vec128_t& src3 = ics.rf[i->src3_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i32[0] = - (table & 0x00000004) ? src3.i32[table & 0x3] : src2.i32[table & 0x3]; - dest.i32[1] = (table & 0x00000400) ? src3.i32[(table >> 8) & 0x3] - : src2.i32[(table >> 8) & 0x3]; - dest.i32[2] = (table & 0x00040000) ? src3.i32[(table >> 16) & 0x3] - : src2.i32[(table >> 16) & 0x3]; - dest.i32[3] = (table & 0x04000000) ? src3.i32[(table >> 24) & 0x3] - : src2.i32[(table >> 24) & 0x3]; - return IA_NEXT; -} -uint32_t IntCode_PERMUTE_V128_BY_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& table = ics.rf[i->src1_reg].v128; - const vec128_t& src2 = ics.rf[i->src2_reg].v128; - const vec128_t& src3 = ics.rf[i->src3_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.low = dest.high = 0; - for (size_t n = 0; n < 16; n++) { - uint8_t index = (table.u8[n] & 0x1F) ^ 0x3; - dest.u8[n] = index < 16 ? src2.u8[index] : src3.u8[index - 16]; - } - return IA_NEXT; -} -int Translate_PERMUTE(TranslationContext& ctx, Instr* i) { - // Can do more as needed. - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_PERMUTE_V128_BY_INT32, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_PERMUTE_V128_BY_V128, - }; - IntCodeFn fn = fns[i->src1.value->type * MAX_TYPENAME + i->dest->type]; - return DispatchToC(ctx, i, fn); -} - -uint32_t IntCode_SWIZZLE_V128(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - uint32_t swizzle_mask = ics.rf[i->src2_reg].u32; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i32[0] = src1.i32[(swizzle_mask >> 0) & 0x3]; - dest.i32[1] = src1.i32[(swizzle_mask >> 2) & 0x3]; - dest.i32[2] = src1.i32[(swizzle_mask >> 4) & 0x3]; - dest.i32[3] = src1.i32[(swizzle_mask >> 6) & 0x3]; - return IA_NEXT; -} -int Translate_SWIZZLE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_SWIZZLE_V128, - }; - return DispatchToC(ctx, i, fns[i->src1.value->type]); -} - -uint32_t IntCode_PACK_D3DCOLOR(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - // RGBA (XYZW) -> ARGB (WXYZ) - dest.ux = dest.uy = dest.uz = 0; - dest.uw = ((src1.uw & 0xFF) << 24) | ((src1.ux & 0xFF) << 16) | - ((src1.uy & 0xFF) << 8) | (src1.uz & 0xFF); - return IA_NEXT; -} -uint32_t IntCode_PACK_FLOAT16_2(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.ux = dest.uy = dest.uz = 0; - dest.uw = (uint32_t(poly::float_to_half(src1.x)) << 16) | - poly::float_to_half(src1.y); - return IA_NEXT; -} -uint32_t IntCode_PACK_FLOAT16_4(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.ux = dest.uy = 0; - dest.uz = (uint32_t(poly::float_to_half(src1.x)) << 16) | - poly::float_to_half(src1.y); - dest.uw = (uint32_t(poly::float_to_half(src1.z)) << 16) | - poly::float_to_half(src1.w); - return IA_NEXT; -} -uint32_t IntCode_PACK_SHORT_2(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - int16_t dx = int16_t(poly::saturate(src1.x) * 32767.0f); - int16_t dy = int16_t(poly::saturate(src1.y) * 32767.0f); - dest.ux = dest.uy = dest.uz = 0; - dest.uw = (uint32_t(uint16_t(dx)) << 16) | uint32_t(uint16_t(dy)); - return IA_NEXT; -} -int Translate_PACK(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_PACK_D3DCOLOR, IntCode_PACK_FLOAT16_2, IntCode_PACK_FLOAT16_4, - IntCode_PACK_SHORT_2, IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_UNPACK_D3DCOLOR(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - // ARGB (WXYZ) -> RGBA (XYZW) - // XMLoadColor - int32_t src = (int32_t)src1.uw; - dest.u32[0] = 0x3F800000 | ((src >> 16) & 0xFF); - dest.u32[1] = 0x3F800000 | ((src >> 8) & 0xFF); - dest.u32[2] = 0x3F800000 | (src & 0xFF); - dest.u32[3] = 0x3F800000 | ((src >> 24) & 0xFF); - return IA_NEXT; -} -uint32_t IntCode_UNPACK_FLOAT16_2(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.f32[0] = poly::half_to_float(uint16_t(src1.uw >> 16)); - dest.f32[1] = poly::half_to_float(uint16_t(src1.uw)); - dest.f32[2] = 0.0f; - dest.f32[3] = 1.0f; - return IA_NEXT; -} -uint32_t IntCode_UNPACK_FLOAT16_4(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.f32[0] = poly::half_to_float(src1.u16[5]); - dest.f32[1] = poly::half_to_float(src1.u16[4]); - dest.f32[2] = poly::half_to_float(src1.u16[7]); - dest.f32[3] = poly::half_to_float(src1.u16[6]); - return IA_NEXT; -} -uint32_t IntCode_UNPACK_SHORT_2(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - // XMLoadShortN2 - uint16_t sx = src1.uw >> 16; - uint16_t sy = src1.uw & 0xFFFF; - dest.u32[0] = sx & 0x8000 ? (0x403F0000 | sx) : (0x40400000 | sx); - dest.u32[1] = sy & 0x8000 ? (0x403F0000 | sy) : (0x40400000 | sy); - dest.u32[2] = 0; - dest.u32[3] = 0x3F800000; - return IA_NEXT; -} -uint32_t IntCode_UNPACK_S8_IN_16_LO(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i16[0] = (int16_t)src1.i8[8 + 0]; - dest.i16[1] = (int16_t)src1.i8[8 + 1]; - dest.i16[2] = (int16_t)src1.i8[8 + 2]; - dest.i16[3] = (int16_t)src1.i8[8 + 3]; - dest.i16[4] = (int16_t)src1.i8[8 + 4]; - dest.i16[5] = (int16_t)src1.i8[8 + 5]; - dest.i16[6] = (int16_t)src1.i8[8 + 6]; - dest.i16[7] = (int16_t)src1.i8[8 + 7]; - return IA_NEXT; -} -uint32_t IntCode_UNPACK_S8_IN_16_HI(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i16[0] = (int16_t)src1.i8[0]; - dest.i16[1] = (int16_t)src1.i8[1]; - dest.i16[2] = (int16_t)src1.i8[2]; - dest.i16[3] = (int16_t)src1.i8[3]; - dest.i16[4] = (int16_t)src1.i8[4]; - dest.i16[5] = (int16_t)src1.i8[5]; - dest.i16[6] = (int16_t)src1.i8[6]; - dest.i16[7] = (int16_t)src1.i8[7]; - return IA_NEXT; -} -uint32_t IntCode_UNPACK_S16_IN_32_LO(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i32[0] = (int32_t)src1.i16[4 + 0]; - dest.i32[1] = (int32_t)src1.i16[4 + 1]; - dest.i32[2] = (int32_t)src1.i16[4 + 2]; - dest.i32[3] = (int32_t)src1.i16[4 + 3]; - return IA_NEXT; -} -uint32_t IntCode_UNPACK_S16_IN_32_HI(IntCodeState& ics, const IntCode* i) { - const vec128_t& src1 = ics.rf[i->src1_reg].v128; - vec128_t& dest = ics.rf[i->dest_reg].v128; - dest.i32[0] = (int32_t)src1.i16[0]; - dest.i32[1] = (int32_t)src1.i16[1]; - dest.i32[2] = (int32_t)src1.i16[2]; - dest.i32[3] = (int32_t)src1.i16[3]; - return IA_NEXT; -} -int Translate_UNPACK(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_UNPACK_D3DCOLOR, IntCode_UNPACK_FLOAT16_2, - IntCode_UNPACK_FLOAT16_4, IntCode_UNPACK_SHORT_2, - IntCode_UNPACK_S8_IN_16_LO, IntCode_UNPACK_S8_IN_16_HI, - IntCode_UNPACK_S16_IN_32_LO, IntCode_UNPACK_S16_IN_32_HI, - }; - return DispatchToC(ctx, i, fns[i->flags]); -} - -uint32_t IntCode_ATOMIC_EXCHANGE_I32(IntCodeState& ics, const IntCode* i) { - auto address = (uint32_t*)ics.rf[i->src1_reg].u64; - auto new_value = ics.rf[i->src2_reg].u32; - auto old_value = poly::atomic_exchange(new_value, address); - ics.rf[i->dest_reg].u32 = old_value; - return IA_NEXT; -} -uint32_t IntCode_ATOMIC_EXCHANGE_I64(IntCodeState& ics, const IntCode* i) { - auto address = (uint64_t*)ics.rf[i->src1_reg].u64; - auto new_value = ics.rf[i->src2_reg].u64; - auto old_value = poly::atomic_exchange(new_value, address); - ics.rf[i->dest_reg].u64 = old_value; - return IA_NEXT; -} -int Translate_ATOMIC_EXCHANGE(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_ATOMIC_EXCHANGE_I32, IntCode_ATOMIC_EXCHANGE_I64, - IntCode_INVALID_TYPE, IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - }; - return DispatchToC(ctx, i, fns[i->src2.value->type]); -} - -typedef int (*TranslateFn)(TranslationContext& ctx, Instr* i); -static const TranslateFn dispatch_table[] = { - Translate_COMMENT, Translate_NOP, - Translate_SOURCE_OFFSET, Translate_TRACE_SOURCE, - Translate_DEBUG_BREAK, Translate_DEBUG_BREAK_TRUE, - Translate_TRAP, Translate_TRAP_TRUE, - Translate_CALL, Translate_CALL_TRUE, - Translate_CALL_INDIRECT, Translate_CALL_INDIRECT_TRUE, - Translate_CALL_EXTERN, Translate_RETURN, - Translate_RETURN_TRUE, Translate_SET_RETURN_ADDRESS, - Translate_BRANCH, Translate_BRANCH_TRUE, - Translate_BRANCH_FALSE, Translate_ASSIGN, - Translate_CAST, Translate_ZERO_EXTEND, - Translate_SIGN_EXTEND, Translate_TRUNCATE, - Translate_CONVERT, Translate_ROUND, - Translate_VECTOR_CONVERT_I2F, Translate_VECTOR_CONVERT_F2I, - Translate_LOAD_VECTOR_SHL, Translate_LOAD_VECTOR_SHR, - Translate_LOAD_CLOCK, Translate_LOAD_LOCAL, - Translate_STORE_LOCAL, Translate_LOAD_CONTEXT, - Translate_STORE_CONTEXT, Translate_LOAD, - Translate_STORE, Translate_PREFETCH, - Translate_MAX, Translate_VECTOR_MAX, - Translate_MIN, Translate_VECTOR_MIN, - Translate_SELECT, Translate_IS_TRUE, - Translate_IS_FALSE, Translate_COMPARE_EQ, - Translate_COMPARE_NE, Translate_COMPARE_SLT, - Translate_COMPARE_SLE, Translate_COMPARE_SGT, - Translate_COMPARE_SGE, Translate_COMPARE_ULT, - Translate_COMPARE_ULE, Translate_COMPARE_UGT, - Translate_COMPARE_UGE, Translate_DID_CARRY, - TranslateInvalid, // Translate_DID_OVERFLOW, - Translate_DID_SATURATE, Translate_VECTOR_COMPARE_EQ, - Translate_VECTOR_COMPARE_SGT, Translate_VECTOR_COMPARE_SGE, - Translate_VECTOR_COMPARE_UGT, Translate_VECTOR_COMPARE_UGE, - Translate_ADD, Translate_ADD_CARRY, - Translate_VECTOR_ADD, Translate_SUB, - Translate_VECTOR_SUB, Translate_MUL, - Translate_MUL_HI, Translate_DIV, - Translate_MUL_ADD, Translate_MUL_SUB, - Translate_NEG, Translate_ABS, - Translate_SQRT, Translate_RSQRT, - Translate_POW2, Translate_LOG2, - Translate_DOT_PRODUCT_3, Translate_DOT_PRODUCT_4, - Translate_AND, Translate_OR, - Translate_XOR, Translate_NOT, - Translate_SHL, Translate_VECTOR_SHL, - Translate_SHR, Translate_VECTOR_SHR, - Translate_SHA, Translate_VECTOR_SHA, - Translate_ROTATE_LEFT, Translate_VECTOR_ROTATE_LEFT, - Translate_BYTE_SWAP, Translate_CNTLZ, - Translate_INSERT, Translate_EXTRACT, - Translate_SPLAT, Translate_PERMUTE, - Translate_SWIZZLE, Translate_PACK, - Translate_UNPACK, - TranslateInvalid, // Translate_COMPARE_EXCHANGE, - Translate_ATOMIC_EXCHANGE, - TranslateInvalid, // Translate_ATOMIC_ADD, - TranslateInvalid, // Translate_ATOMIC_SUB, -}; - -int TranslateIntCodes(TranslationContext& ctx, Instr* i) { - TranslateFn fn = dispatch_table[i->opcode->num]; - return fn(ctx, i); -} - -} // namespace ivm -} // namespace backend -} // namespace alloy diff --git a/src/alloy/backend/ivm/ivm_intcode.h b/src/alloy/backend/ivm/ivm_intcode.h deleted file mode 100644 index 6a0a6f8f5..000000000 --- a/src/alloy/backend/ivm/ivm_intcode.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef ALLOY_BACKEND_IVM_INTCODE_H_ -#define ALLOY_BACKEND_IVM_INTCODE_H_ - -#include -#include - -namespace alloy { -namespace runtime { -class ThreadState; -} // namespace runtime -} // namespace alloy - -namespace alloy { -namespace backend { -namespace ivm { - -typedef union { - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - int64_t i64; - uint64_t u64; - float f32; - double f64; - vec128_t v128; -} Register; - -typedef struct { - Register* rf; - uint8_t* locals; - uint8_t* context; - uint8_t* membase; - int8_t did_carry; - int8_t did_saturate; - runtime::ThreadState* thread_state; - uint64_t return_address; - uint64_t call_return_address; -} IntCodeState; - -struct IntCode_s; -typedef uint32_t (*IntCodeFn)(IntCodeState& ics, const struct IntCode_s* i); - -#define IA_RETURN 0xA0000000 -#define IA_NEXT 0xB0000000 - -typedef struct IntCode_s { - IntCodeFn intcode_fn; - uint16_t flags; - uint16_t debug_flags; - - uint32_t dest_reg; - union { - struct { - uint32_t src1_reg; - uint32_t src2_reg; - uint32_t src3_reg; - // <4 bytes available> - }; - struct { - Register constant; - }; - }; - - // debugging info/etc -} IntCode; - -typedef struct LabelRef_s { - hir::Label* label; - IntCode* instr; - LabelRef_s* next; -} LabelRef; - -typedef struct SourceMapEntry_s { - uint64_t source_offset; - uint64_t intcode_index; -} SourceMapEntry; - -typedef struct { - uint32_t register_count; - size_t intcode_count; - Arena* intcode_arena; - size_t source_map_count; - Arena* source_map_arena; - Arena* scratch_arena; - LabelRef* label_ref_head; - size_t stack_size; -} TranslationContext; - -int TranslateIntCodes(TranslationContext& ctx, hir::Instr* i); - -} // namespace ivm -} // namespace backend -} // namespace alloy - -#endif // ALLOY_BACKEND_IVM_INTCODE_H_ diff --git a/src/alloy/backend/ivm/ivm_stack.cc b/src/alloy/backend/ivm/ivm_stack.cc deleted file mode 100644 index 1e80e4073..000000000 --- a/src/alloy/backend/ivm/ivm_stack.cc +++ /dev/null @@ -1,79 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -namespace alloy { -namespace backend { -namespace ivm { - -IVMStack::IVMStack() - : chunk_size_(2 * 1024 * 1024), head_chunk_(NULL), active_chunk_(NULL) {} - -IVMStack::~IVMStack() { - Chunk* chunk = head_chunk_; - while (chunk) { - Chunk* next = chunk->next; - delete chunk; - chunk = next; - } - head_chunk_ = NULL; -} - -Register* IVMStack::Alloc(size_t register_count) { - size_t size = register_count * sizeof(Register); - if (active_chunk_) { - if (active_chunk_->capacity - active_chunk_->offset < size) { - Chunk* next = active_chunk_->next; - if (!next) { - assert_true(size < chunk_size_, "need to support larger chunks"); - next = new Chunk(chunk_size_); - next->prev = active_chunk_; - active_chunk_->next = next; - } - next->offset = 0; - active_chunk_ = next; - } - } else { - head_chunk_ = active_chunk_ = new Chunk(chunk_size_); - } - - uint8_t* p = active_chunk_->buffer + active_chunk_->offset; - active_chunk_->offset += size; - return (Register*)p; -} - -void IVMStack::Free(size_t register_count) { - size_t size = register_count * sizeof(Register); - if (active_chunk_->offset == size) { - // Moving back a chunk. - active_chunk_->offset = 0; - if (active_chunk_->prev) { - active_chunk_ = active_chunk_->prev; - } - } else { - // Still in same chunk. - active_chunk_->offset -= size; - } -} - -IVMStack::Chunk::Chunk(size_t chunk_size) - : prev(NULL), next(NULL), capacity(chunk_size), buffer(0), offset(0) { - buffer = reinterpret_cast(malloc(capacity)); -} - -IVMStack::Chunk::~Chunk() { - if (buffer) { - free(buffer); - } -} - -} // namespace ivm -} // namespace backend -} // namespace alloy diff --git a/src/alloy/backend/ivm/ivm_stack.h b/src/alloy/backend/ivm/ivm_stack.h deleted file mode 100644 index f02a169f4..000000000 --- a/src/alloy/backend/ivm/ivm_stack.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef ALLOY_BACKEND_IVM_IVM_STACK_H_ -#define ALLOY_BACKEND_IVM_IVM_STACK_H_ - -#include - -namespace alloy { -namespace backend { -namespace ivm { - -class IVMStack { - public: - IVMStack(); - ~IVMStack(); - - Register* Alloc(size_t register_count); - void Free(size_t register_count); - - private: - class Chunk { - public: - Chunk(size_t chunk_size); - ~Chunk(); - - Chunk* prev; - Chunk* next; - - size_t capacity; - uint8_t* buffer; - size_t offset; - }; - - private: - size_t chunk_size_; - Chunk* head_chunk_; - Chunk* active_chunk_; -}; - -} // namespace ivm -} // namespace backend -} // namespace alloy - -#endif // ALLOY_BACKEND_IVM_IVM_STACK_H_ diff --git a/src/alloy/backend/ivm/sources.gypi b/src/alloy/backend/ivm/sources.gypi deleted file mode 100644 index 20306f9fb..000000000 --- a/src/alloy/backend/ivm/sources.gypi +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'ivm_intcode.cc', - 'ivm_intcode.h', - 'ivm_assembler.cc', - 'ivm_assembler.h', - 'ivm_backend.cc', - 'ivm_backend.h', - 'ivm_function.cc', - 'ivm_function.h', - 'ivm_stack.cc', - 'ivm_stack.h', - ], -} diff --git a/src/alloy/backend/sources.gypi b/src/alloy/backend/sources.gypi index ec3be77a4..3cf3b826b 100644 --- a/src/alloy/backend/sources.gypi +++ b/src/alloy/backend/sources.gypi @@ -9,7 +9,6 @@ ], 'includes': [ - 'ivm/sources.gypi', 'x64/sources.gypi', ], } diff --git a/src/alloy/frontend/ppc/test/alloy-ppc-test.cc b/src/alloy/frontend/ppc/test/alloy-ppc-test.cc index 4970325e8..9190eaccd 100644 --- a/src/alloy/frontend/ppc/test/alloy-ppc-test.cc +++ b/src/alloy/frontend/ppc/test/alloy-ppc-test.cc @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/src/alloy/memory.cc b/src/alloy/memory.cc index c699173e0..36d1ac05f 100644 --- a/src/alloy/memory.cc +++ b/src/alloy/memory.cc @@ -73,36 +73,4 @@ SimpleMemory::SimpleMemory(size_t capacity) : memory_(capacity) { SimpleMemory::~SimpleMemory() = default; -uint8_t SimpleMemory::LoadI8(uint64_t address) { - return poly::load(membase_ + address); -} - -uint16_t SimpleMemory::LoadI16(uint64_t address) { - return poly::load(membase_ + address); -} - -uint32_t SimpleMemory::LoadI32(uint64_t address) { - return poly::load(membase_ + address); -} - -uint64_t SimpleMemory::LoadI64(uint64_t address) { - return poly::load(membase_ + address); -} - -void SimpleMemory::StoreI8(uint64_t address, uint8_t value) { - poly::store(membase_ + address, value); -} - -void SimpleMemory::StoreI16(uint64_t address, uint16_t value) { - poly::store(membase_ + address, value); -} - -void SimpleMemory::StoreI32(uint64_t address, uint32_t value) { - poly::store(membase_ + address, value); -} - -void SimpleMemory::StoreI64(uint64_t address, uint64_t value) { - poly::store(membase_ + address, value); -} - } // namespace alloy diff --git a/src/alloy/memory.h b/src/alloy/memory.h index 3d858eab9..de094f6e3 100644 --- a/src/alloy/memory.h +++ b/src/alloy/memory.h @@ -40,16 +40,6 @@ class Memory { uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values, size_t value_count); - // TODO(benvanik): remove with IVM. - virtual uint8_t LoadI8(uint64_t address) = 0; - virtual uint16_t LoadI16(uint64_t address) = 0; - virtual uint32_t LoadI32(uint64_t address) = 0; - virtual uint64_t LoadI64(uint64_t address) = 0; - virtual void StoreI8(uint64_t address, uint8_t value) = 0; - virtual void StoreI16(uint64_t address, uint16_t value) = 0; - virtual void StoreI32(uint64_t address, uint32_t value) = 0; - virtual void StoreI64(uint64_t address, uint64_t value) = 0; - protected: size_t system_page_size_; uint8_t* membase_; @@ -63,16 +53,6 @@ class SimpleMemory : public Memory { SimpleMemory(size_t capacity); ~SimpleMemory() override; - // TODO(benvanik): remove with IVM. - uint8_t LoadI8(uint64_t address) override; - uint16_t LoadI16(uint64_t address) override; - uint32_t LoadI32(uint64_t address) override; - uint64_t LoadI64(uint64_t address) override; - void StoreI8(uint64_t address, uint8_t value) override; - void StoreI16(uint64_t address, uint16_t value) override; - void StoreI32(uint64_t address, uint32_t value) override; - void StoreI64(uint64_t address, uint64_t value) override; - private: std::vector memory_; }; diff --git a/src/alloy/runtime/instrument.cc b/src/alloy/runtime/instrument.cc index 3466d7cd5..8cb099fe6 100644 --- a/src/alloy/runtime/instrument.cc +++ b/src/alloy/runtime/instrument.cc @@ -53,7 +53,6 @@ bool FunctionInstrument::Attach() { // Function impl attach: // - add instrument to list - // IVM: handle in Call() // JIT: transition to instrumented state // - rewrite enter/exit to jump to instrumentation thunk // - some sort of locking required? diff --git a/src/alloy/runtime/runtime.cc b/src/alloy/runtime/runtime.cc index 5b8765bbe..5da4970da 100644 --- a/src/alloy/runtime/runtime.cc +++ b/src/alloy/runtime/runtime.cc @@ -17,10 +17,9 @@ #include // TODO(benvanik): based on compiler support -#include #include -DEFINE_string(runtime_backend, "any", "Runtime backend [any, ivm, x64]."); +DEFINE_string(runtime_backend, "any", "Runtime backend [any, x64]."); namespace alloy { namespace runtime { @@ -81,22 +80,12 @@ int Runtime::Initialize(std::unique_ptr frontend, backend.reset(new alloy::backend::x64::X64Backend(this)); } #endif // ALLOY_HAS_X64_BACKEND -#if defined(ALLOY_HAS_IVM_BACKEND) && ALLOY_HAS_IVM_BACKEND - if (FLAGS_runtime_backend == "ivm") { - backend.reset(new alloy::backend::ivm::IVMBackend(this)); - } -#endif // ALLOY_HAS_IVM_BACKEND if (FLAGS_runtime_backend == "any") { #if defined(ALLOY_HAS_X64_BACKEND) && ALLOY_HAS_X64_BACKEND if (!backend) { backend.reset(new alloy::backend::x64::X64Backend(this)); } #endif // ALLOY_HAS_X64_BACKEND -#if defined(ALLOY_HAS_IVM_BACKEND) && ALLOY_HAS_IVM_BACKEND - if (!backend) { - backend.reset(new alloy::backend::ivm::IVMBackend(this)); - } -#endif // ALLOY_HAS_IVM_BACKEND } } diff --git a/src/alloy/test/alloy-sandbox.cc b/src/alloy/test/alloy-sandbox.cc index 69ffa4d0a..8d519cf1b 100644 --- a/src/alloy/test/alloy-sandbox.cc +++ b/src/alloy/test/alloy-sandbox.cc @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/src/alloy/test/util.h b/src/alloy/test/util.h index 22734c0b2..a38692f0f 100644 --- a/src/alloy/test/util.h +++ b/src/alloy/test/util.h @@ -11,7 +11,6 @@ #define ALLOY_TEST_UTIL_H_ #include -#include #include #include #include @@ -22,7 +21,6 @@ #include -#define ALLOY_TEST_IVM 1 #define ALLOY_TEST_X64 1 namespace alloy { @@ -86,17 +84,6 @@ class TestFunction { memory_size = 16 * 1024 * 1024; memory.reset(new SimpleMemory(memory_size)); -#if ALLOY_TEST_IVM - { - auto runtime = std::make_unique(memory.get()); - auto frontend = - std::make_unique(runtime.get()); - auto backend = - std::make_unique(runtime.get()); - runtime->Initialize(std::move(frontend), std::move(backend)); - runtimes.emplace_back(std::move(runtime)); - } -#endif // ALLOY_TEST_IVM #if ALLOY_TEST_X64 { auto runtime = std::make_unique(memory.get()); diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 4c5f1b9ca..a0a3c60f5 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -90,7 +90,6 @@ int Processor::Setup() { } std::unique_ptr backend; - // backend.reset(new alloy::backend::ivm::IVMBackend(runtime)); // backend.reset(new alloy::backend::x64::X64Backend(runtime)); int result = runtime_->Initialize(std::move(backend)); if (result) { diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index ccbb8e85e..f1da724af 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -203,8 +203,8 @@ int Memory::Initialize() { // I have no idea what this is, but games try to read/write there. VirtualAlloc(Translate(0x40000000), 0x00010000, MEM_COMMIT, PAGE_READWRITE); - StoreI32(0x40000000, 0x00C40000); - StoreI32(0x40000004, 0x00010000); + poly::store_and_swap(Translate(0x40000000), 0x00C40000); + poly::store_and_swap(Translate(0x40000004), 0x00010000); return 0; } @@ -286,62 +286,6 @@ void Memory::CancelWriteWatch(uintptr_t watch_handle) { mmio_handler_->CancelWriteWatch(watch_handle); } -uint8_t Memory::LoadI8(uint64_t address) { - uint64_t value; - if (!mmio_handler_->CheckLoad(address, &value)) { - value = *reinterpret_cast(Translate(address)); - } - return static_cast(value); -} - -uint16_t Memory::LoadI16(uint64_t address) { - uint64_t value; - if (!mmio_handler_->CheckLoad(address, &value)) { - value = *reinterpret_cast(Translate(address)); - } - return static_cast(value); -} - -uint32_t Memory::LoadI32(uint64_t address) { - uint64_t value; - if (!mmio_handler_->CheckLoad(address, &value)) { - value = *reinterpret_cast(Translate(address)); - } - return static_cast(value); -} - -uint64_t Memory::LoadI64(uint64_t address) { - uint64_t value; - if (!mmio_handler_->CheckLoad(address, &value)) { - value = *reinterpret_cast(Translate(address)); - } - return static_cast(value); -} - -void Memory::StoreI8(uint64_t address, uint8_t value) { - if (!mmio_handler_->CheckStore(address, value)) { - *reinterpret_cast(Translate(address)) = value; - } -} - -void Memory::StoreI16(uint64_t address, uint16_t value) { - if (!mmio_handler_->CheckStore(address, value)) { - *reinterpret_cast(Translate(address)) = value; - } -} - -void Memory::StoreI32(uint64_t address, uint32_t value) { - if (!mmio_handler_->CheckStore(address, value)) { - *reinterpret_cast(Translate(address)) = value; - } -} - -void Memory::StoreI64(uint64_t address, uint64_t value) { - if (!mmio_handler_->CheckStore(address, value)) { - *reinterpret_cast(Translate(address)) = value; - } -} - uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags, uint32_t alignment) { // If we were given a base address we are outside of the normal heap and diff --git a/src/xenia/memory.h b/src/xenia/memory.h index 2258ee151..8bc741d77 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -58,15 +58,6 @@ class Memory : public alloy::Memory { void* callback_context, void* callback_data); void CancelWriteWatch(uintptr_t watch_handle); - uint8_t LoadI8(uint64_t address) override; - uint16_t LoadI16(uint64_t address) override; - uint32_t LoadI32(uint64_t address) override; - uint64_t LoadI64(uint64_t address) override; - void StoreI8(uint64_t address, uint8_t value) override; - void StoreI16(uint64_t address, uint16_t value) override; - void StoreI32(uint64_t address, uint32_t value) override; - void StoreI64(uint64_t address, uint64_t value) override; - uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags, uint32_t alignment = 0x20); int HeapFree(uint64_t address, size_t size);