diff --git a/common/cross_os_debug/xdbg.cpp b/common/cross_os_debug/xdbg.cpp index c70e6bbd68..6ceadce4ae 100644 --- a/common/cross_os_debug/xdbg.cpp +++ b/common/cross_os_debug/xdbg.cpp @@ -714,7 +714,9 @@ bool break_now(const ThreadID& tid) { bool cont_now(const ThreadID& tid) { return false; } -bool open_memory(const ThreadID& tid, MemoryHandle* out); +bool open_memory(const ThreadID& tid, MemoryHandle* out) { + return false; +} bool close_memory(const ThreadID& tid, MemoryHandle* handle) { return false; } diff --git a/goalc/build_level/common/FileInfo.cpp b/goalc/build_level/common/FileInfo.cpp index 2aa38da677..a499e005a4 100644 --- a/goalc/build_level/common/FileInfo.cpp +++ b/goalc/build_level/common/FileInfo.cpp @@ -5,7 +5,8 @@ #include "common/versions/versions.h" #include "goalc/data_compiler/DataObjectGenerator.h" -#include + +#include "fmt/chrono.h" std::string get_current_time_and_date() { auto const now = std::chrono::floor(std::chrono::system_clock::now()); diff --git a/goalc/build_level/jak2/build_level.cpp b/goalc/build_level/jak2/build_level.cpp index fd991b0c2d..fc41abc309 100644 --- a/goalc/build_level/jak2/build_level.cpp +++ b/goalc/build_level/jak2/build_level.cpp @@ -3,13 +3,13 @@ #include "common/util/gltf_util.h" #include "decompiler/extractor/extractor_util.h" +#include "decompiler/level_extractor/extract_collide_frags.h" #include "decompiler/level_extractor/extract_merc.h" #include "goalc/build_level/collide/jak2/collide.h" #include "goalc/build_level/common/Tfrag.h" #include "goalc/build_level/jak2/Entity.h" #include "goalc/build_level/jak2/FileInfo.h" #include "goalc/build_level/jak2/LevelFile.h" -#include namespace jak2 { bool run_build_level(const std::string& input_file, diff --git a/goalc/build_level/jak3/build_level.cpp b/goalc/build_level/jak3/build_level.cpp index 4501b910bb..3f2581e561 100644 --- a/goalc/build_level/jak3/build_level.cpp +++ b/goalc/build_level/jak3/build_level.cpp @@ -1,13 +1,13 @@ #include "build_level.h" #include "decompiler/extractor/extractor_util.h" +#include "decompiler/level_extractor/extract_collide_frags.h" #include "decompiler/level_extractor/extract_merc.h" #include "goalc/build_level/collide/jak3/collide.h" #include "goalc/build_level/common/Tfrag.h" #include "goalc/build_level/jak3/Entity.h" #include "goalc/build_level/jak3/FileInfo.h" #include "goalc/build_level/jak3/LevelFile.h" -#include namespace jak3 { bool run_build_level(const std::string& input_file, diff --git a/goalc/compiler/IR.cpp b/goalc/compiler/IR.cpp index c0d9cf38ac..ce4f98f91b 100644 --- a/goalc/compiler/IR.cpp +++ b/goalc/compiler/IR.cpp @@ -121,7 +121,7 @@ void regset_common(emitter::ObjectGenerator* gen, gen->count_eliminated_move(); gen->add_instr(IGen::null(*gen), irec); } else { - gen->add_instr(IGen::mov_xmm32_xmm32(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::mov_f32_f32(*gen, dst_reg, src_reg), irec); } } else if (src_is_xmm128 && dst_is_xmm128) { if (src_reg == dst_reg) { @@ -133,20 +133,20 @@ void regset_common(emitter::ObjectGenerator* gen, } } else if (src_class == RegClass::FLOAT && dst_class == RegClass::GPR_64) { // xmm 1x -> gpr - gen->add_instr(IGen::movd_gpr32_xmm32(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::movd_gpr32_f32(*gen, dst_reg, src_reg), irec); // don't forget to sign extend gen->add_instr(IGen::movsx_r64_r32(*gen, dst_reg, dst_reg), irec); } else if (src_class == RegClass::GPR_64 && dst_class == RegClass::FLOAT) { // gpr -> xmm 1x - gen->add_instr(IGen::movd_xmm32_gpr32(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::movd_f32_gpr32(*gen, dst_reg, src_reg), irec); } else if (src_is_xmm128 && dst_class == RegClass::FLOAT) { - gen->add_instr(IGen::mov_xmm32_xmm32(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::mov_f32_f32(*gen, dst_reg, src_reg), irec); } else if (src_class == RegClass::FLOAT && dst_is_xmm128) { - gen->add_instr(IGen::mov_xmm32_xmm32(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::mov_f32_f32(*gen, dst_reg, src_reg), irec); } else if (src_class == RegClass::GPR_64 && dst_is_xmm128) { - gen->add_instr(IGen::movq_xmm64_gpr64(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::movq_f64_gpr64(*gen, dst_reg, src_reg), irec); } else if (src_is_xmm128 && dst_class == RegClass::GPR_64) { - gen->add_instr(IGen::movq_gpr64_xmm64(*gen, dst_reg, src_reg), irec); + gen->add_instr(IGen::movq_gpr64_f64(*gen, dst_reg, src_reg), irec); } else { ASSERT(false); // unhandled move. } @@ -256,7 +256,7 @@ void IR_LoadSymbolPointer::do_codegen_x86(emitter::ObjectGenerator* gen, if (m_name == "#f") { static_assert(false_symbol_offset() == 0, "false symbol location"); if (dest_reg.is_xmm(gen->instr_set())) { - gen->add_instr(IGen::movq_xmm64_gpr64(*gen, dest_reg, gRegInfo.get_st_reg()), irec); + gen->add_instr(IGen::movq_f64_gpr64(*gen, dest_reg, gRegInfo.get_st_reg()), irec); } else { gen->add_instr(IGen::mov_gpr64_gpr64(*gen, dest_reg, gRegInfo.get_st_reg()), irec); } @@ -417,7 +417,8 @@ void IR_GotoLabel::do_codegen_x86(emitter::ObjectGenerator* gen, const AllocationResult& allocs, emitter::IR_Record irec) { (void)allocs; - auto instr = gen->add_instr(IGen::jmp_32(*gen), irec); + auto instr = gen->add_instr(IGen::jmp_imm(*gen), irec); + // TODO ARM - have to patch this differently, encoding for the immediate is different gen->link_instruction_jump(instr, gen->get_future_ir_record_in_same_func(irec, m_dest->idx)); } @@ -711,15 +712,21 @@ void IR_IntegerMath::do_codegen_x86(emitter::ObjectGenerator* gen, ASSERT(!m_arg); break; case IntegerMathKind::SHLV_64: - gen->add_instr(IGen::shl_gpr64_cl(*gen, get_reg(m_dest, allocs, irec)), irec); + // TODO ARM - register provided but unused on x86 + gen->add_instr(IGen::shl_gpr64_reg(*gen, get_reg(m_dest, allocs, irec), 0), irec); + // TODO ARM - x86 forces you to use CL, which is dumb, but the register allocator + // has that logic baked in somewhere + // ARM has no such constraint, so we should be able to use any register for the shift amount ASSERT(get_reg(m_arg, allocs, irec) == emitter::RCX); break; case IntegerMathKind::SHRV_64: - gen->add_instr(IGen::shr_gpr64_cl(*gen, get_reg(m_dest, allocs, irec)), irec); + // TODO ARM - register provided but unused on x86 + gen->add_instr(IGen::shr_gpr64_reg(*gen, get_reg(m_dest, allocs, irec), 0), irec); ASSERT(get_reg(m_arg, allocs, irec) == emitter::RCX); break; case IntegerMathKind::SARV_64: - gen->add_instr(IGen::sar_gpr64_cl(*gen, get_reg(m_dest, allocs, irec)), irec); + // TODO ARM - register provided but unused on x86 + gen->add_instr(IGen::sar_gpr64_reg(*gen, get_reg(m_dest, allocs, irec), 0), irec); ASSERT(get_reg(m_arg, allocs, irec) == emitter::RCX); break; case IntegerMathKind::SHL_64: @@ -823,37 +830,37 @@ void IR_FloatMath::do_codegen_x86(emitter::ObjectGenerator* gen, switch (m_kind) { case FloatMathKind::DIV_SS: gen->add_instr( - IGen::divss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::div_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::MUL_SS: gen->add_instr( - IGen::mulss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::mul_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::ADD_SS: gen->add_instr( - IGen::addss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::add_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::SUB_SS: gen->add_instr( - IGen::subss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::sub_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::MAX_SS: gen->add_instr( - IGen::maxss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::max_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::MIN_SS: gen->add_instr( - IGen::minss_xmm_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), + IGen::min_f32_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; case FloatMathKind::SQRT_SS: gen->add_instr( - IGen::sqrts_xmm(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); + IGen::sqrt_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); break; default: ASSERT(false); @@ -895,7 +902,7 @@ void IR_StaticVarLoad::do_codegen_x86(emitter::ObjectGenerator* gen, ASSERT(load_info.requires_load == true); auto instr = - gen->add_instr(IGen::static_load_xmm32(*gen, get_reg(m_dest, allocs, irec), 0), irec); + gen->add_instr(IGen::static_load_f32(*gen, get_reg(m_dest, allocs, irec), 0), irec); gen->link_instruction_static(instr, m_src->rec, 0); } else if (m_dest->ireg().reg_class == RegClass::VECTOR_FLOAT) { // we don't check the load info intentionally because we want to allow loading an entire @@ -966,38 +973,38 @@ void IR_ConditionalBranch::do_codegen_x86(emitter::ObjectGenerator* gen, ASSERT(m_resolved); switch (condition.kind) { case ConditionKind::EQUAL: - jump_instr = IGen::je_32(*gen); + jump_instr = IGen::je_imm(*gen); break; case ConditionKind::NOT_EQUAL: - jump_instr = IGen::jne_32(*gen); + jump_instr = IGen::jne_imm(*gen); break; case ConditionKind::LEQ: if (condition.is_signed) { - jump_instr = IGen::jle_32(*gen); + jump_instr = IGen::jle_imm(*gen); } else { - jump_instr = IGen::jbe_32(*gen); + jump_instr = IGen::jbe_imm(*gen); } break; case ConditionKind::GEQ: if (condition.is_signed) { - jump_instr = IGen::jge_32(*gen); + jump_instr = IGen::jge_imm(*gen); } else { - jump_instr = IGen::jae_32(*gen); + jump_instr = IGen::jae_imm(*gen); } break; case ConditionKind::LT: if (condition.is_signed) { - jump_instr = IGen::jl_32(*gen); + jump_instr = IGen::jl_imm(*gen); } else { - jump_instr = IGen::jb_32(*gen); + jump_instr = IGen::jb_imm(*gen); } break; case ConditionKind::GT: if (condition.is_signed) { - jump_instr = IGen::jg_32(*gen); + jump_instr = IGen::jg_imm(*gen); } else { - jump_instr = IGen::ja_32(*gen); + jump_instr = IGen::ja_imm(*gen); } break; default: @@ -1005,7 +1012,7 @@ void IR_ConditionalBranch::do_codegen_x86(emitter::ObjectGenerator* gen, } if (condition.is_float) { - gen->add_instr(IGen::cmp_flt_flt(*gen, get_reg(condition.a, allocs, irec), + gen->add_instr(IGen::cmp_f32_f32(*gen, get_reg(condition.a, allocs, irec), get_reg(condition.b, allocs, irec)), irec); } else { @@ -1210,8 +1217,7 @@ void IR_FloatToInt::do_codegen_x86(emitter::ObjectGenerator* gen, const AllocationResult& allocs, emitter::IR_Record irec) { gen->add_instr( - IGen::float_to_int32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_src, allocs, irec)), - irec); + IGen::f32_to_int32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_src, allocs, irec)), irec); gen->add_instr( IGen::movsx_r64_r32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_dest, allocs, irec)), irec); @@ -1244,8 +1250,7 @@ void IR_IntToFloat::do_codegen_x86(emitter::ObjectGenerator* gen, const AllocationResult& allocs, emitter::IR_Record irec) { gen->add_instr( - IGen::int32_to_float(*gen, get_reg(m_dest, allocs, irec), get_reg(m_src, allocs, irec)), - irec); + IGen::int32_to_f32(*gen, get_reg(m_dest, allocs, irec), get_reg(m_src, allocs, irec)), irec); } void IR_IntToFloat::do_codegen_arm64(emitter::ObjectGenerator* gen, diff --git a/goalc/emitter/CodeTester.cpp b/goalc/emitter/CodeTester.cpp index 1cefe8eb15..bfe3c8d79e 100644 --- a/goalc/emitter/CodeTester.cpp +++ b/goalc/emitter/CodeTester.cpp @@ -11,6 +11,7 @@ #include "common/common_types.h" #include "goalc/emitter/Instruction.h" +#include "goalc/emitter/InstructionSet.h" #include "goalc/emitter/Register.h" #ifdef OS_POSIX #include @@ -125,7 +126,7 @@ void CodeTester::emit_push_all_simd() { } else if (m_gen.instr_set() == InstructionSet::ARM64) { for (int i = 0; i < 16; i++) { emit(IGen::sub_gpr64_imm8s(m_gen, SP, 16)); - emit(IGen::store128_gpr64_simd128(m_gen, SP, Q0 + i)); + emit(IGen::store128_gpr64_simd128(m_gen, SP, V0 + i)); } } else { throw std::runtime_error("CodeTester::emit_push_all_simd unhandled instruction set"); @@ -144,7 +145,7 @@ void CodeTester::emit_pop_all_simd() { emit(IGen::add_gpr64_imm8s(m_gen, RSP, 8)); } else if (m_gen.instr_set() == InstructionSet::ARM64) { for (int i = 0; i < 16; i++) { - emit(IGen::load128_simd128_gpr64(m_gen, Q0 + i, SP)); + emit(IGen::load128_simd128_gpr64(m_gen, V0 + i, SP)); emit(IGen::add_gpr64_imm8s(m_gen, SP, 16)); } } else { diff --git a/goalc/emitter/IGen.cpp b/goalc/emitter/IGen.cpp index a621ce6b9c..61e0d92100 100644 --- a/goalc/emitter/IGen.cpp +++ b/goalc/emitter/IGen.cpp @@ -31,24 +31,24 @@ Instruction mov_gpr64_s32(const ObjectGenerator& gen, Register dst, int64_t val) IGEN_DISPATCH(mov_gpr64_s32, dst, val); } -Instruction movd_gpr32_xmm32(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(movd_gpr32_xmm32, dst, src); +Instruction movd_gpr32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(movd_gpr32_f32, dst, src); } -Instruction movd_xmm32_gpr32(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(movd_xmm32_gpr32, dst, src); +Instruction movd_f32_gpr32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(movd_f32_gpr32, dst, src); } -Instruction movq_gpr64_xmm64(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(movq_gpr64_xmm64, dst, src); +Instruction movq_gpr64_f64(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(movq_gpr64_f64, dst, src); } -Instruction movq_xmm64_gpr64(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(movq_xmm64_gpr64, dst, src); +Instruction movq_f64_gpr64(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(movq_f64_gpr64, dst, src); } -Instruction mov_xmm32_xmm32(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(mov_xmm32_xmm32, dst, src); +Instruction mov_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(mov_f32_f32, dst, src); } Instruction load8s_gpr64_gpr64_plus_gpr64(const ObjectGenerator& gen, @@ -516,31 +516,31 @@ Instruction store128_xmm128_reg_offset(const ObjectGenerator& gen, } Instruction load64_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load64_rip_s32, dest, offset); + IGEN_DISPATCH(load64_pcRel_s32, dest, offset); } Instruction load32s_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load32s_rip_s32, dest, offset); + IGEN_DISPATCH(load32s_pcRel_s32, dest, offset); } Instruction load32u_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load32u_rip_s32, dest, offset); + IGEN_DISPATCH(load32u_pcRel_s32, dest, offset); } Instruction load16u_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load16u_rip_s32, dest, offset); + IGEN_DISPATCH(load16u_pcRel_s32, dest, offset); } Instruction load16s_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load16s_rip_s32, dest, offset); + IGEN_DISPATCH(load16s_pcRel_s32, dest, offset); } Instruction load8u_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load8u_rip_s32, dest, offset); + IGEN_DISPATCH(load8u_pcRel_s32, dest, offset); } Instruction load8s_rip_s32(const ObjectGenerator& gen, Register dest, s64 offset) { - IGEN_DISPATCH(load8s_rip_s32, dest, offset); + IGEN_DISPATCH(load8s_pcRel_s32, dest, offset); } Instruction static_load(const ObjectGenerator& gen, @@ -552,19 +552,19 @@ Instruction static_load(const ObjectGenerator& gen, } Instruction store64_rip_s32(const ObjectGenerator& gen, Register src, s64 offset) { - IGEN_DISPATCH(store64_rip_s32, src, offset); + IGEN_DISPATCH(store64_pcRel_s32, src, offset); } Instruction store32_rip_s32(const ObjectGenerator& gen, Register src, s64 offset) { - IGEN_DISPATCH(store32_rip_s32, src, offset); + IGEN_DISPATCH(store32_pcRel_s32, src, offset); } Instruction store16_rip_s32(const ObjectGenerator& gen, Register src, s64 offset) { - IGEN_DISPATCH(store16_rip_s32, src, offset); + IGEN_DISPATCH(store16_pcRel_s32, src, offset); } Instruction store8_rip_s32(const ObjectGenerator& gen, Register src, s64 offset) { - IGEN_DISPATCH(store8_rip_s32, src, offset); + IGEN_DISPATCH(store8_pcRel_s32, src, offset); } Instruction static_store(const ObjectGenerator& gen, Register value, s64 offset, int size) { @@ -575,12 +575,12 @@ Instruction static_addr(const ObjectGenerator& gen, Register dst, s64 offset) { IGEN_DISPATCH(static_addr, dst, offset); } -Instruction static_load_xmm32(const ObjectGenerator& gen, Register simd_dest, s64 offset) { - IGEN_DISPATCH(static_load_xmm32, simd_dest, offset); +Instruction static_load_f32(const ObjectGenerator& gen, Register simd_dest, s64 offset) { + IGEN_DISPATCH(static_load_f32, simd_dest, offset); } -Instruction static_store_xmm32(const ObjectGenerator& gen, Register xmm_value, s64 offset) { - IGEN_DISPATCH(static_store_xmm32, xmm_value, offset); +Instruction static_store_f32(const ObjectGenerator& gen, Register xmm_value, s64 offset) { + IGEN_DISPATCH(static_store_f32, xmm_value, offset); } Instruction load64_gpr64_plus_s32(const ObjectGenerator& gen, @@ -693,16 +693,16 @@ Instruction not_gpr64(const ObjectGenerator& gen, Register reg) { IGEN_DISPATCH(not_gpr64, reg); } -Instruction shl_gpr64_cl(const ObjectGenerator& gen, Register reg) { - IGEN_DISPATCH(shl_gpr64_cl, reg); +Instruction shl_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg) { + IGEN_DISPATCH(shl_gpr64_reg, reg, shift_reg); } -Instruction shr_gpr64_cl(const ObjectGenerator& gen, Register reg) { - IGEN_DISPATCH(shr_gpr64_cl, reg); +Instruction shr_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg) { + IGEN_DISPATCH(shr_gpr64_reg, reg, shift_reg); } -Instruction sar_gpr64_cl(const ObjectGenerator& gen, Register reg) { - IGEN_DISPATCH(sar_gpr64_cl, reg); +Instruction sar_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg) { + IGEN_DISPATCH(sar_gpr64_reg, reg, shift_reg); } Instruction shl_gpr64_u8(const ObjectGenerator& gen, Register reg, uint8_t sa) { @@ -717,88 +717,88 @@ Instruction sar_gpr64_u8(const ObjectGenerator& gen, Register reg, uint8_t sa) { IGEN_DISPATCH(sar_gpr64_u8, reg, sa); } -Instruction jmp_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jmp_32); +Instruction jmp_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jmp_imm); } -Instruction je_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(je_32); +Instruction je_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(je_imm); } -Instruction jne_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jne_32); +Instruction jne_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jne_imm); } -Instruction jle_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jle_32); +Instruction jle_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jle_imm); } -Instruction jge_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jge_32); +Instruction jge_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jge_imm); } -Instruction jl_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jl_32); +Instruction jl_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jl_imm); } -Instruction jg_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jg_32); +Instruction jg_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jg_imm); } -Instruction jbe_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jbe_32); +Instruction jbe_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jbe_imm); } -Instruction jae_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jae_32); +Instruction jae_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jae_imm); } -Instruction jb_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(jb_32); +Instruction jb_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(jb_imm); } -Instruction ja_32(const ObjectGenerator& gen) { - IGEN_DISPATCH(ja_32); +Instruction ja_imm(const ObjectGenerator& gen) { + IGEN_DISPATCH(ja_imm); } -Instruction cmp_flt_flt(const ObjectGenerator& gen, Register a, Register b) { - IGEN_DISPATCH(cmp_flt_flt, a, b); +Instruction cmp_f32_f32(const ObjectGenerator& gen, Register a, Register b) { + IGEN_DISPATCH(cmp_f32_f32, a, b); } -Instruction sqrts_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(sqrts_xmm, dst, src); +Instruction sqrt_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(sqrt_f32, dst, src); } -Instruction mulss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(mulss_xmm_xmm, dst, src); +Instruction mul_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(mul_f32_f32, dst, src); } -Instruction divss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(divss_xmm_xmm, dst, src); +Instruction div_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(div_f32_f32, dst, src); } -Instruction subss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(subss_xmm_xmm, dst, src); +Instruction sub_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(sub_f32_f32, dst, src); } -Instruction addss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(addss_xmm_xmm, dst, src); +Instruction add_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(add_f32_f32, dst, src); } -Instruction minss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(minss_xmm_xmm, dst, src); +Instruction min_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(min_f32_f32, dst, src); } -Instruction maxss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(maxss_xmm_xmm, dst, src); +Instruction max_f32_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(max_f32_f32, dst, src); } -Instruction int32_to_float(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(int32_to_float, dst, src); +Instruction int32_to_f32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(int32_to_f32, dst, src); } -Instruction float_to_int32(const ObjectGenerator& gen, Register dst, Register src) { - IGEN_DISPATCH(float_to_int32, dst, src); +Instruction f32_to_int32(const ObjectGenerator& gen, Register dst, Register src) { + IGEN_DISPATCH(f32_to_int32, dst, src); } Instruction nop(const ObjectGenerator& gen) { diff --git a/goalc/emitter/IGen.h b/goalc/emitter/IGen.h index cfb985ea2e..27cbcc8c16 100644 --- a/goalc/emitter/IGen.h +++ b/goalc/emitter/IGen.h @@ -35,27 +35,27 @@ Instruction mov_gpr64_s32(const ObjectGenerator& gen, Register dst, int64_t val) /*! * Move 32-bits of xmm to 32 bits of gpr (no sign extension). */ -Instruction movd_gpr32_xmm32(const ObjectGenerator& gen, Register dst, Register src); +Instruction movd_gpr32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! * Move 32-bits of gpr to 32-bits of xmm (no sign extension) */ -Instruction movd_xmm32_gpr32(const ObjectGenerator& gen, Register dst, Register src); +Instruction movd_f32_gpr32(const ObjectGenerator& gen, Register dst, Register src); /*! * Move 64-bits of xmm to 64 bits of gpr (no sign extension). */ -Instruction movq_gpr64_xmm64(const ObjectGenerator& gen, Register dst, Register src); +Instruction movq_gpr64_f64(const ObjectGenerator& gen, Register dst, Register src); /*! * Move 64-bits of gpr to 64-bits of xmm (no sign extension) */ -Instruction movq_xmm64_gpr64(const ObjectGenerator& gen, Register dst, Register src); +Instruction movq_f64_gpr64(const ObjectGenerator& gen, Register dst, Register src); /*! * Move 32-bits between xmm's */ -Instruction mov_xmm32_xmm32(const ObjectGenerator& gen, Register dst, Register src); +Instruction mov_f32_f32(const ObjectGenerator& gen, Register dst, Register src); // todo - GPR64 -> XMM64 (zext) // todo - XMM -> GPR64 @@ -486,9 +486,9 @@ Instruction static_store(const ObjectGenerator& gen, Register value, s64 offset, Instruction static_addr(const ObjectGenerator& gen, Register dst, s64 offset); -Instruction static_load_xmm32(const ObjectGenerator& gen, Register simd_dest, s64 offset); +Instruction static_load_f32(const ObjectGenerator& gen, Register simd_dest, s64 offset); -Instruction static_store_xmm32(const ObjectGenerator& gen, Register xmm_value, s64 offset); +Instruction static_store_f32(const ObjectGenerator& gen, Register xmm_value, s64 offset); // TODO, special load/stores of 128 bit values. @@ -618,19 +618,21 @@ Instruction not_gpr64(const ObjectGenerator& gen, Register reg); //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; /*! - * Shift 64-bit gpr left by CL register + * Shift 64-bit gpr left by a shift amount in a register (ie. forced to be CL register on x86) */ -Instruction shl_gpr64_cl(const ObjectGenerator& gen, Register reg); +Instruction shl_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg); /*! - * Shift 64-bit gpr right (logical) by CL register + * Shift 64-bit gpr right (logical) by a shift amount in a register (ie. forced to be CL register on + * x86) */ -Instruction shr_gpr64_cl(const ObjectGenerator& gen, Register reg); +Instruction shr_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg); /*! - * Shift 64-bit gpr right (arithmetic) by CL register + * Shift 64-bit gpr right (arithmetic) a shift amount in a register (ie. forced to be CL register on + * x86) */ -Instruction sar_gpr64_cl(const ObjectGenerator& gen, Register reg); +Instruction sar_gpr64_reg(const ObjectGenerator& gen, Register reg, Register shift_reg); /*! * Shift 64-ptr left (logical) by the constant shift amount "sa". @@ -654,57 +656,57 @@ Instruction sar_gpr64_u8(const ObjectGenerator& gen, Register reg, uint8_t sa); /*! * Jump, 32-bit constant offset. The offset is by default 0 and must be patched later. */ -Instruction jmp_32(const ObjectGenerator& gen); +Instruction jmp_imm(const ObjectGenerator& gen); /*! * Jump if equal. */ -Instruction je_32(const ObjectGenerator& gen); +Instruction je_imm(const ObjectGenerator& gen); /*! * Jump not equal. */ -Instruction jne_32(const ObjectGenerator& gen); +Instruction jne_imm(const ObjectGenerator& gen); /*! * Jump less than or equal. */ -Instruction jle_32(const ObjectGenerator& gen); +Instruction jle_imm(const ObjectGenerator& gen); /*! * Jump greater than or equal. */ -Instruction jge_32(const ObjectGenerator& gen); +Instruction jge_imm(const ObjectGenerator& gen); /*! * Jump less than */ -Instruction jl_32(const ObjectGenerator& gen); +Instruction jl_imm(const ObjectGenerator& gen); /*! * Jump greater than */ -Instruction jg_32(const ObjectGenerator& gen); +Instruction jg_imm(const ObjectGenerator& gen); /*! * Jump below or equal */ -Instruction jbe_32(const ObjectGenerator& gen); +Instruction jbe_imm(const ObjectGenerator& gen); /*! * Jump above or equal */ -Instruction jae_32(const ObjectGenerator& gen); +Instruction jae_imm(const ObjectGenerator& gen); /*! * Jump below */ -Instruction jb_32(const ObjectGenerator& gen); +Instruction jb_imm(const ObjectGenerator& gen); /*! * Jump above */ -Instruction ja_32(const ObjectGenerator& gen); +Instruction ja_imm(const ObjectGenerator& gen); //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; // FLOAT MATH @@ -713,49 +715,49 @@ Instruction ja_32(const ObjectGenerator& gen); /*! * Compare two floats and set flag register for jump (ucomiss) */ -Instruction cmp_flt_flt(const ObjectGenerator& gen, Register a, Register b); +Instruction cmp_f32_f32(const ObjectGenerator& gen, Register a, Register b); -Instruction sqrts_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction sqrt_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Multiply two floats in xmm's + * Multiply two floats in f32's */ -Instruction mulss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction mul_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Divide two floats in xmm's + * Divide two floats in f32's */ -Instruction divss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction div_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Subtract two floats in xmm's + * Subtract two floats in f32's */ -Instruction subss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction sub_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Add two floats in xmm's + * Add two floats in f32's */ -Instruction addss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction add_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! * Floating point minimum. */ -Instruction minss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction min_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! * Floating point maximum. */ -Instruction maxss_xmm_xmm(const ObjectGenerator& gen, Register dst, Register src); +Instruction max_f32_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Convert GPR int32 to XMM float (single precision) + * Convert GPR int32 to float (single precision) */ -Instruction int32_to_float(const ObjectGenerator& gen, Register dst, Register src); +Instruction int32_to_f32(const ObjectGenerator& gen, Register dst, Register src); /*! - * Convert XMM float to GPR int32(single precision) (truncate) + * Convert float to GPR int32(single precision) (truncate) */ -Instruction float_to_int32(const ObjectGenerator& gen, Register dst, Register src); +Instruction f32_to_int32(const ObjectGenerator& gen, Register dst, Register src); Instruction nop(const ObjectGenerator& gen); diff --git a/goalc/emitter/IGenARM64.cpp b/goalc/emitter/IGenARM64.cpp index 089faeae28..e70d5eef54 100644 --- a/goalc/emitter/IGenARM64.cpp +++ b/goalc/emitter/IGenARM64.cpp @@ -1,6 +1,8 @@ #include "IGenARM64.h" +#include + #include "goalc/emitter/Instruction.h" #include "goalc/emitter/InstructionSet.h" #include "goalc/emitter/Register.h" @@ -22,63 +24,107 @@ const auto instr_set = emitter::InstructionSet::ARM64; using namespace emitter::ARM64; InstructionARM64 mov_gpr64_gpr64(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + // https://www.scs.stanford.edu/~zyedidia/arm64/mov_orr_log_shift.html + // MOV , + ASSERT(dst.is_gpr(instr_set)); + ASSERT(src.is_gpr(instr_set)); + return InstructionARM64(Base(0b10101010000, 11), Rm(src.id()), Rn(0b11111), Rd(dst.id()), + Imm6(0)); } InstructionARM64 mov_gpr64_u64(Register dst, uint64_t val) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + // Cannot be done in a single instruction, must combine multiple MOVZ/MOVKs + std::vector instrs; + bool emitted_movz = false; + for (int i = 0; i < 4; i++) { + u16 chunk = (val >> (i * 16)) & 0xFFFF; + if (!emitted_movz && chunk != 0) { + // https://www.scs.stanford.edu/~zyedidia/arm64/movz.html + // MOVZ , #{, LSL #/16} + instrs.emplace_back( + InstructionARM64(Base(0b110100101, 9), Hw(i), Imm16(chunk), Rd(dst.id()))); + emitted_movz = true; + } else if (emitted_movz && chunk != 0) { + // https://www.scs.stanford.edu/~zyedidia/arm64/movk.html + // MOVK , #{, LSL #/16} + instrs.emplace_back( + InstructionARM64(Base(0b111100101, 9), Hw(i), Imm16(chunk), Rd(dst.id()))); + } + } + if (!emitted_movz) { + // https://www.scs.stanford.edu/~zyedidia/arm64/movz.html + // MOVZ , #{, LSL #0} + instrs.emplace_back(InstructionARM64(Base(0b110100101, 9), Hw(0), Imm16(0), Rd(dst.id()))); + } + return InstructionARM64(instrs); } InstructionARM64 mov_gpr64_u32(Register dst, uint64_t val) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + return mov_gpr64_u64(dst, val); } InstructionARM64 mov_gpr64_s32(Register dst, int64_t val) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + // preserve sign -- but we are are simply moving the bits + u64 raw_val = static_cast(val); // via int64_t → sign already there + return mov_gpr64_u64(dst, raw_val); } -InstructionARM64 movd_gpr32_xmm32(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 movd_gpr32_f32(Register dst, Register src) { + // https://www.scs.stanford.edu/~zyedidia/arm64/fmov_float_gen.html + // Single-precision to 32-bit (sf == 0 && ftype == 00 && rmode == 00 && opcode == 110) + // FMOV , + ASSERT(dst.is_gpr(instr_set)); + return InstructionARM64(Base(0b0001111000100110000000, 22), Rn(src.id()), Rd(dst.id())); } -InstructionARM64 movd_xmm32_gpr32(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 movd_f32_gpr32(Register dst, Register src) { + // https://www.scs.stanford.edu/~zyedidia/arm64/fmov_float_gen.html + // 32-bit to single-precision (sf == 0 && ftype == 00 && rmode == 00 && opcode == 111) + // FMOV , + ASSERT(src.is_gpr(instr_set)); + return InstructionARM64(Base(0b0001111000100111000000, 22), Rn(src.id()), Rd(dst.id())); } -InstructionARM64 movq_gpr64_xmm64(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 movq_gpr64_f64(Register dst, Register src) { + // https://www.scs.stanford.edu/~zyedidia/arm64/fmov_float_gen.html + // Double-precision to 64-bit (sf == 1 && ftype == 01 && rmode == 00 && opcode == 110) + // FMOV , + ASSERT(dst.is_gpr(instr_set)); + return InstructionARM64(Base(0b1001111001100110000000, 22), Rn(src.id()), Rd(dst.id())); } -InstructionARM64 movq_xmm64_gpr64(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 movq_f64_gpr64(Register dst, Register src) { + // https://www.scs.stanford.edu/~zyedidia/arm64/fmov_float_gen.html + // 64-bit to double-precision (sf == 1 && ftype == 01 && rmode == 00 && opcode == 111) + // FMOV , + ASSERT(src.is_gpr(instr_set)); + return InstructionARM64(Base(0b1001111001100111000000, 22), Rn(src.id()), Rd(dst.id())); } -InstructionARM64 mov_xmm32_xmm32(Register dst, Register src) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 mov_f32_f32(Register dst, Register src) { + // https://www.scs.stanford.edu/~zyedidia/arm64/fmov_float.html + // Single-precision (ftype == 00) + // FMOV , + return InstructionARM64(Base(0b0001111000100000010000, 22), Rn(src.id()), Rd(dst.id())); } -// todo - GPR64 -> XMM64 (zext) -// todo - XMM -> GPR64 - //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; // GOAL Loads and Stores //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InstructionARM64 load8s_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + // https://www.scs.stanford.edu/~zyedidia/arm64/ldrsb_reg.html + // 64-bit with extended register offset (opc == 10 && option != 011) + // LDRSB , [, (|), {}] + ASSERT(dst.is_gpr(instr_set)); + ASSERT(addr1.is_gpr(instr_set)); + ASSERT(addr2.is_gpr(instr_set)); + return InstructionARM64(Base(0b0011100010100000111010, 22), Rt(dst.id()), Rn(addr1.id()), + Rm(addr2.id())); } InstructionARM64 store8_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) { + // https://www.scs.stanford.edu/~zyedidia/arm64/strb_reg.html ASSERT_MSG(false, "not yet implemented"); return InstructionARM64(0b0); } @@ -486,85 +532,181 @@ InstructionARM64 store128_xmm128_reg_offset(Register base, Register xmm_val, s64 } //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -// RIP loads and stores +// PC relative loads and stores //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -InstructionARM64 load64_rip_s32(Register dest, s64 offset) { +// Implement with LDR but that has a 1MB range limit on ARM (not 2GB like on x86) +// Hopefully this is fine, however it could potentially not be if this is loading static data, which +// may not within 1MB of the current instruction -- that all depends on the linker layout. +// +// TODO ARM - But keep it simple at first, add good assertions and we'll see what happens when we +// compile for real. + +const int ARM64_LDR_MIN = -(1 << 18) * 4; +const int ARM64_LDR_MAX = ((1 << 18) - 1) * 4; + +InstructionARM64 load64_pcRel_s32(Register dest, s64 offset) { + ASSERT(dest.is_gpr(instr_set)); + ASSERT_MSG(offset >= ARM64_LDR_MIN && offset <= ARM64_LDR_MAX, + "PC Relative offset is too large for ARM64, fix it."); + // https://www.scs.stanford.edu/~zyedidia/arm64/ldr_lit_gen.html + // LDR ,