Files
Tyler Wilding 64bcd8c030 goalc: Get CodeTester tests passing on Arm64 (only targetting macOS atm) (#3290)
This PR does the following:
- Designs a mechanism by which arm64 instructions can be encoded and
emitted
- Dispatch our higher-level instruction emitting calls to either x86 or
arm64 instructions depending on what the compiler is set to (defaults to
x86)
- Bare minimum scaffolding to get the arm64 instructions successfully
executing atleast on apple silicon
- Implement enough instructions to get the codetester test suite passing
on arm
2026-03-30 20:20:47 -04:00

1203 lines
40 KiB
C++

#include "IGenARM64.h"
#include "goalc/emitter/Instruction.h"
#include "goalc/emitter/InstructionSet.h"
#include "goalc/emitter/Register.h"
// https://armconverter.com/?code=ret
// https://developer.arm.com/documentation/ddi0487/latest
// TODO ARM64 - just silencing errors while things are not implemented obviously
#pragma GCC diagnostic ignored "-Wunused-parameter"
namespace emitter {
namespace IGen {
namespace ARM64 {
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// MOVES
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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);
}
InstructionARM64 mov_gpr64_u64(Register dst, uint64_t val) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mov_gpr64_u32(Register dst, uint64_t val) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mov_gpr64_s32(Register dst, int64_t val) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 movd_gpr32_xmm32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 movd_xmm32_gpr32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 movq_gpr64_xmm64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 movq_xmm64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mov_xmm32_xmm32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
// 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);
}
InstructionARM64 store8_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store8_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store8_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8u_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16s_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store16_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store16_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store16_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16u_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32s_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32s_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32s_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32u_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32u_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load64_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store64_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2, Register value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load64_gpr64_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store64_gpr64_gpr64_plus_gpr64_plus_s8(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load64_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store64_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
Register addr2,
Register value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store_goal_vf(Register addr, Register value, Register off, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store_goal_gpr(Register addr, Register value, Register off, int offset, int size) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load_goal_xmm128(Register dst, Register addr, Register off, int offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load_goal_gpr(Register dst,
Register addr,
Register off,
int offset,
int size,
bool sign_extend) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// LOADS n' STORES - XMM32
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 store32_xmm32_gpr64_plus_gpr64(Register addr1,
Register addr2,
Register xmm_value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32_xmm32_gpr64_plus_gpr64(Register simd_dest, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_xmm32_gpr64_plus_gpr64_plus_s8(Register addr1,
Register addr2,
Register xmm_value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32_xmm32_gpr64_plus_gpr64_plus_s8(Register simd_dest,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_xmm32_gpr64_plus_gpr64_plus_s32(Register addr1,
Register addr2,
Register xmm_value,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 lea_reg_plus_off32(Register dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 lea_reg_plus_off8(Register dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 lea_reg_plus_off(Register dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_xmm32_gpr64_plus_s32(Register base, Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_xmm32_gpr64_plus_s8(Register base, Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32_xmm32_gpr64_plus_gpr64_plus_s32(Register simd_dest,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32_xmm32_gpr64_plus_s32(Register simd_dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32_xmm32_gpr64_plus_s8(Register simd_dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load_goal_xmm32(Register simd_dest, Register addr, Register off, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store_goal_xmm32(Register addr, Register xmm_value, Register off, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store_reg_offset_xmm32(Register base, Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load_reg_offset_xmm32(Register simd_dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// LOADS n' STORES - SIMD (128-bit, QWORDS)
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 store128_gpr64_simd128(Register gpr_addr, Register simd_reg) {
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
// - STR Qn, [Xn] (unsigned offset)
ASSERT(gpr_addr.is_gpr(instr_set));
ASSERT(
simd_reg.is_128bit_simd(instr_set)); // TODO ARM64 - this assertion isn't as useful for ARM
// since Q registers are not unique in terms of their id
return InstructionARM64(Base(0b0011110110, 10), Rn(gpr_addr.id()), Rt(simd_reg.id()), Imm12(0));
}
InstructionARM64 store128_gpr64_simd128_s32(Register gpr_addr, Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store128_gpr64_simd128_s8(Register gpr_addr, Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load128_simd128_gpr64(Register simd_dest, Register gpr_addr) {
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
// - LDR <Qt>, [<Xn|SP>{, #<pimm>}]
ASSERT(gpr_addr.is_gpr(instr_set));
ASSERT(simd_dest.is_128bit_simd(
instr_set)); // TODO ARM64 - this assertion isn't as useful for ARM
// since Q registers are not unique in terms of their id
return InstructionARM64(Base(0b0011110111, 10), Rn(gpr_addr.id()), Rt(simd_dest.id()), Imm12(0));
}
InstructionARM64 load128_simd128_gpr64_s32(Register simd_dest, Register gpr_addr, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load128_simd128_gpr64_s8(Register simd_dest, Register gpr_addr, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load128_xmm128_reg_offset(Register simd_dest, Register base, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store128_xmm128_reg_offset(Register base, Register xmm_val, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// RIP loads and stores
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 load64_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32s_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load32u_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16u_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load16s_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8u_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 load8s_rip_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 static_load(Register dest, s64 offset, int size, bool sign_extend) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store64_rip_s32(Register src, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store32_rip_s32(Register src, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store16_rip_s32(Register src, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store8_rip_s32(Register src, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 static_store(Register value, s64 offset, int size) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 static_addr(Register dst, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 static_load_xmm32(Register simd_dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 static_store_xmm32(Register xmm_value, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
// TODO, special load/stores of 128 bit values.
// TODO, consider specialized stack loads and stores?
InstructionARM64 load64_gpr64_plus_s32(Register dst_reg, int32_t offset, Register src_reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 store64_gpr64_plus_s32(Register addr, int32_t offset, Register value) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// FUNCTION STUFF
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 ret() {
// https://www.scs.stanford.edu/~zyedidia/arm64/ret.html
// - defaults to using X30 if Rn is absent
return InstructionARM64(Base(0b1101011001011111000000, 22), Rn(30));
}
InstructionARM64 push_gpr64(Register reg) {
// ARM64 stack grows down, so we subtract 16 from SP and store the register
// Equivalent assembly: STR reg, [SP, #-16]!
// - https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_gen.html
// We use 16 because in ARM, the stack must be 16-byte aligned.
// This does mean we are inefficiently using the stack, there are a few better options:
// - Push in pairs, two registers at a time
// - Preallocate stack-space
// But we can't do either of these at this level, this is an optimization that has to come from
// higher in the stack. Here we are concerned with just satisfying the need to push a GPR
ASSERT(reg.is_gpr(instr_set));
return InstructionARM64(Base(0b1111100000000000000011, 22), Imm9(-16), Rn(ARM64_REG::SP),
Rt(reg.id()));
}
InstructionARM64 pop_gpr64(Register reg) {
// ldr reg, [sp], #16
// - https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_gen.html
ASSERT(reg.is_gpr(instr_set));
return InstructionARM64(Base(0b1111100001000000000001, 22), Imm9(16), Rn(ARM64_REG::SP),
Rt(reg.id()));
}
InstructionARM64 call_r64(Register reg_) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jmp_r64(Register reg_) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// INTEGER MATH
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// NOTE: ARM can actually handle 12-bit immediate values, so if it's actually worth it, we
// could leverage these instructions for more than just 8-bit values
InstructionARM64 sub_gpr64_imm8s(Register reg, int64_t imm) {
// You cannot subtract or add with a negative immediate in ARM
// therefore depending on the value of the immediate, we use a different instruction
ASSERT(reg.is_gpr(instr_set));
if (imm < 0) {
return add_gpr64_imm8s(reg, std::abs(imm));
}
// https://www.scs.stanford.edu/~zyedidia/arm64/sub_addsub_imm.html
// - SUB <Xd>, <Xn>, #imm12 {, LSL #12}
// - using a shift of 0 here (last bit in the base)
return InstructionARM64(Base(0b1101000100, 10), Imm12(imm), Rn(reg.id()), Rd(reg.id()));
}
// NOTE: ARM can actually handle 12-bit immediate values, so if it's actually worth it, we
// could leverage these instructions for more than just 8-bit values
InstructionARM64 add_gpr64_imm8s(Register reg, int64_t imm) {
// You cannot subtract or add with a negative immediate in ARM
// therefore depending on the value of the immediate, we use a different instruction
ASSERT(reg.is_gpr(instr_set));
if (imm < 0) {
return sub_gpr64_imm8s(reg, abs(imm));
}
// https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_imm.html
// ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}
return InstructionARM64(Base(0b1001000100, 10), Imm12(imm), Rn(reg.id()), Rd(reg.id()));
}
InstructionARM64 sub_gpr64_imm32s(Register reg, int64_t imm) {
// ARM64 does not support this kind of single-instruction
ASSERT_MSG(false, "sub_gpr64_imm32s not supported on ARM64");
return InstructionARM64(0b0);
}
InstructionARM64 add_gpr64_imm32s(Register reg, int64_t imm) {
// ARM64 does not support this kind of single-instruction
ASSERT_MSG(false, "sub_gpr64_imm32s not supported on ARM64");
return InstructionARM64(0b0);
}
InstructionARM64 add_gpr64_imm(Register reg, int64_t imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sub_gpr64_imm(Register reg, int64_t imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 add_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sub_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 imul_gpr32_gpr32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 imul_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 idiv_gpr32(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 unsigned_div_gpr32(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 cdq() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 movsx_r64_r32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 cmp_gpr64_gpr64(Register a, Register b) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// BIT STUFF
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 or_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 and_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 xor_gpr64_gpr64(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 not_gpr64(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// SHIFTS
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 shl_gpr64_cl(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 shr_gpr64_cl(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sar_gpr64_cl(Register reg) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 shl_gpr64_u8(Register reg, uint8_t sa) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 shr_gpr64_u8(Register reg, uint8_t sa) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sar_gpr64_u8(Register reg, uint8_t sa) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// CONTROL FLOW
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 jmp_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 je_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jne_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jle_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jge_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jl_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jg_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jbe_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jae_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 jb_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 ja_32() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// FLOAT MATH
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 cmp_flt_flt(Register a, Register b) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sqrts_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mulss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 divss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 subss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 addss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 minss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 maxss_xmm_xmm(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 int32_to_float(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 float_to_int32(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 nop() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
// TODO - rsqrt / abs / sqrt
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// UTILITIES
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstructionARM64 null() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
/////////////////////////////
// AVX (VF - Vector Float) //
/////////////////////////////
InstructionARM64 nop_vf() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 wait_vf() {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mov_vf_vf(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 loadvf_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 loadvf_gpr64_plus_gpr64_plus_s8(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 loadvf_gpr64_plus_gpr64_plus_s32(Register dst,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 storevf_gpr64_plus_gpr64(Register value, Register addr1, Register addr2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 storevf_gpr64_plus_gpr64_plus_s8(Register value,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 storevf_gpr64_plus_gpr64_plus_s32(Register value,
Register addr1,
Register addr2,
s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 loadvf_rip_plus_s32(Register dest, s64 offset) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
// TODO - rip relative loads and stores.
InstructionARM64 blend_vf(Register dst, Register src1, Register src2, u8 mask) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 shuffle_vf(Register dst, Register src, u8 dx, u8 dy, u8 dz, u8 dw) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 swizzle_vf(Register dst, Register src, u8 controlBytes) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 splat_vf(Register dst, Register src, Register::VF_ELEMENT element) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 xor_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sub_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 add_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 mul_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 max_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 min_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 div_vf(Register dst, Register src1, Register src2) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 sqrt_vf(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 itof_vf(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 ftoi_vf(Register dst, Register src) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pw_sra(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pw_srl(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 ph_srl(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pw_sll(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 ph_sll(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_add_byte(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_bitwise_or(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_bitwise_xor(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_bitwise_and(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextub_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextuh_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextuw_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextlb_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextlh_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pextlw_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_e_b(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_e_h(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_e_w(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_gt_b(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_gt_h(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 parallel_compare_gt_w(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpunpcklqdq(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pcpyld_swapped(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 pcpyud(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpsubd(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpsrldq(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpslldq(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpshuflw(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpshufhw(Register dst, Register src, u8 imm) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
InstructionARM64 vpackuswb(Register dst, Register src0, Register src1) {
ASSERT_MSG(false, "not yet implemented");
return InstructionARM64(0b0);
}
} // namespace ARM64
} // namespace IGen
} // namespace emitter