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/compiler/IR.cpp b/goalc/compiler/IR.cpp index c0d9cf38ac..7de4139b93 100644 --- a/goalc/compiler/IR.cpp +++ b/goalc/compiler/IR.cpp @@ -418,6 +418,7 @@ void IR_GotoLabel::do_codegen_x86(emitter::ObjectGenerator* gen, emitter::IR_Record irec) { (void)allocs; auto instr = gen->add_instr(IGen::jmp_32(*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)); } diff --git a/goalc/emitter/IGenARM64.cpp b/goalc/emitter/IGenARM64.cpp index 089faeae28..f46fd4a353 100644 --- a/goalc/emitter/IGenARM64.cpp +++ b/goalc/emitter/IGenARM64.cpp @@ -22,25 +22,37 @@ 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 + // sf 0 1 0 1 0 1 0 0 0 0 Rm 0 + // 0 0 0 0 0 1 1 1 1 1 Rd 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) { + // TODO - cannot be done in a single arm64 instruction + // multiple https://www.scs.stanford.edu/~zyedidia/arm64/movk.html are needed ASSERT_MSG(false, "not yet implemented"); return InstructionARM64(0b0); } InstructionARM64 mov_gpr64_u32(Register dst, uint64_t val) { + // TODO - cannot be done in a single arm64 instruction + // multiple https://www.scs.stanford.edu/~zyedidia/arm64/movk.html are needed ASSERT_MSG(false, "not yet implemented"); return InstructionARM64(0b0); } InstructionARM64 mov_gpr64_s32(Register dst, int64_t val) { + // TODO - cannot be done in a single arm64 instruction + // multiple https://www.scs.stanford.edu/~zyedidia/arm64/movk.html are needed ASSERT_MSG(false, "not yet implemented"); return InstructionARM64(0b0); } +// TODO - should these be make generic to simdX? InstructionARM64 movd_gpr32_xmm32(Register dst, Register src) { ASSERT_MSG(false, "not yet implemented"); return InstructionARM64(0b0); @@ -74,11 +86,18 @@ InstructionARM64 mov_xmm32_xmm32(Register dst, Register src) { //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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); } @@ -615,14 +634,18 @@ InstructionARM64 pop_gpr64(Register reg) { Rt(reg.id())); } -InstructionARM64 call_r64(Register reg_) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 call_r64(Register reg) { + // https://www.scs.stanford.edu/~zyedidia/arm64/blr.html + // BLR + ASSERT(reg.is_gpr(instr_set)); + return InstructionARM64(Base(0b1101011000111111000000, 22), Rn(reg.id())); } -InstructionARM64 jmp_r64(Register reg_) { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); +InstructionARM64 jmp_r64(Register reg) { + // https://www.scs.stanford.edu/~zyedidia/arm64/br.html + // BR + ASSERT(reg.is_gpr(instr_set)); + return InstructionARM64(Base(0b1101011000011111000000, 22), Rn(reg.id())); } //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -711,8 +734,12 @@ InstructionARM64 unsigned_div_gpr32(Register reg) { } InstructionARM64 cdq() { + // https://www.scs.stanford.edu/~zyedidia/arm64/asr_asrv.html + // asr x3, x0, #63 + // (using X3 = edx and X0 = eax) ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + return InstructionARM64(Base(0b1001101011000000001010, 22), Rm(63), Rn(ARM64_REG::X0), + Rd(ARM64_REG::X3)); } InstructionARM64 movsx_r64_r32(Register dst, Register src) { @@ -897,8 +924,9 @@ InstructionARM64 float_to_int32(Register dst, Register src) { } InstructionARM64 nop() { - ASSERT_MSG(false, "not yet implemented"); - return InstructionARM64(0b0); + // https://www.scs.stanford.edu/~zyedidia/arm64/nop.html + // nop + return InstructionARM64(Base(0b11010101000000110010000000011111, 32)); } // TODO - rsqrt / abs / sqrt @@ -908,7 +936,8 @@ InstructionARM64 nop() { //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InstructionARM64 null() { - ASSERT_MSG(false, "not yet implemented"); + // https://www.scs.stanford.edu/~zyedidia/arm64/nop.html + // nop return InstructionARM64(0b0); } @@ -1200,4 +1229,4 @@ InstructionARM64 vpackuswb(Register dst, Register src0, Register src1) { } } // namespace ARM64 } // namespace IGen -} // namespace emitter \ No newline at end of file +} // namespace emitter diff --git a/goalc/emitter/Instruction.h b/goalc/emitter/Instruction.h index 8bda3f995b..ca79a81873 100644 --- a/goalc/emitter/Instruction.h +++ b/goalc/emitter/Instruction.h @@ -91,6 +91,9 @@ struct InstructionARM64 : InstructionImpl { } uint8_t emit(uint8_t* buffer) const { + if (encoding == 0) { + return 0; + } memcpy(buffer, &encoding, 4); return 4; }