Aarch64 jit compiler wip: implement integer & floating-point type conversions
This commit is contained in:
parent
12a4f64aed
commit
00d8f0fe52
5 changed files with 114 additions and 13 deletions
|
|
@ -169,9 +169,9 @@ int main(int argc, char ** argv)
|
|||
for (auto const & module : modules)
|
||||
{
|
||||
// TODO: remove, testing-only code; should execute entry point instead
|
||||
auto offset = module.code.symbol_table.at("pow");
|
||||
auto fptr = (float(*)(float, unsigned))(module.code.memory.data.get() + offset);
|
||||
auto x = fptr(1.5f, 12);
|
||||
auto offset = module.code.symbol_table.at("test");
|
||||
auto fptr = (int(*)())(module.code.memory.data.get() + offset);
|
||||
auto x = fptr();
|
||||
std::cout << "Result: " << std::boolalpha << x << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,2 @@
|
|||
func pow(x : f32, n : u32) -> f32:
|
||||
mut r = 1.0
|
||||
mut f = x // x^k
|
||||
mut k = 1u
|
||||
while k <= n:
|
||||
if (n & k) != 0u:
|
||||
r = r * f
|
||||
f = f * f
|
||||
k = k + k
|
||||
return r
|
||||
func test() -> i32:
|
||||
return 3.141592h as i32
|
||||
|
|
|
|||
|
|
@ -147,6 +147,25 @@ namespace pslang::jit::aarch64
|
|||
|
||||
void fcmp(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t mode);
|
||||
|
||||
// If @op is 0, move the value of a floating-point register @reg_src in format @mode into a general register @reg_dst
|
||||
// If @op is 1, move the value of a general register @reg_src into a floating-point register @reg_dst in format @mode
|
||||
// NB: mode = 2 (single precision) isn't supported
|
||||
void fmov(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode, std::uint8_t op);
|
||||
|
||||
// Convert signed integer in floating-point register @reg_src into floating-point format @mode and
|
||||
// store in floating-point register @reg_dst
|
||||
void scvtf(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode);
|
||||
|
||||
// Convert unsigned integer in floating-point register @reg_src into floating-point format @mode and
|
||||
// store in floating-point register @reg_dst
|
||||
void ucvtf(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode);
|
||||
|
||||
// Convert a value from floating-point register @reg_src in format @mode into a signed integer in @reg_dst
|
||||
void fcvtns(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode);
|
||||
|
||||
// Convert a value from floating-point register @reg_src in format @mode into a unsigned integer in @reg_dst
|
||||
void fcvtnu(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode);
|
||||
|
||||
// Return from a subroutine, taking the return address from register @reg
|
||||
void ret(std::uint8_t reg = 30);
|
||||
|
||||
|
|
|
|||
|
|
@ -528,6 +528,65 @@ namespace pslang::jit::aarch64
|
|||
}
|
||||
}
|
||||
|
||||
void apply(ast::cast_operation const & node)
|
||||
{
|
||||
auto src_type = ast::get_type(*node.expression);
|
||||
auto dst_type = node.inferred_type;
|
||||
|
||||
apply(*node.expression);
|
||||
|
||||
if (types::equal(*src_type, *dst_type))
|
||||
return;
|
||||
|
||||
if (types::is_integer_type(*src_type))
|
||||
{
|
||||
if (types::is_integer_type(*dst_type))
|
||||
{
|
||||
extend(0, dst_type);
|
||||
}
|
||||
else if (types::is_floating_point_type(*dst_type))
|
||||
{
|
||||
auto dst_mode = fp_mode_for(*dst_type);
|
||||
if (types::is_signed_integer_type(*src_type))
|
||||
{
|
||||
builder.fmov(0, 0, 3, 1);
|
||||
builder.scvtf(0, 0, 3);
|
||||
if (dst_mode != 3)
|
||||
builder.fcvt(0, 3, 0, dst_mode);
|
||||
}
|
||||
else if (types::is_unsigned_integer_type(*src_type))
|
||||
{
|
||||
builder.fmov(0, 0, 3, 1);
|
||||
builder.ucvtf(0, 0, 3);
|
||||
if (dst_mode != 3)
|
||||
builder.fcvt(0, 3, 0, dst_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (types::is_floating_point_type(*src_type))
|
||||
{
|
||||
auto src_mode = fp_mode_for(*src_type);
|
||||
if (types::is_integer_type(*dst_type))
|
||||
{
|
||||
if (types::is_signed_integer_type(*dst_type))
|
||||
{
|
||||
builder.fcvtns(0, 0, src_mode);
|
||||
extend(0, dst_type);
|
||||
}
|
||||
else if (types::is_unsigned_integer_type(*dst_type))
|
||||
{
|
||||
builder.fcvtnu(0, 0, src_mode);
|
||||
extend(0, dst_type);
|
||||
}
|
||||
}
|
||||
else if (types::is_floating_point_type(*dst_type))
|
||||
{
|
||||
auto dst_mode = fp_mode_for(*dst_type);
|
||||
builder.fcvt(0, src_mode, 0, dst_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply(ast::assignment const & node)
|
||||
{
|
||||
auto identifier = std::get_if<ast::identifier>(node.lhs.get());
|
||||
|
|
|
|||
|
|
@ -209,6 +209,37 @@ namespace pslang::jit::aarch64
|
|||
do_push(0x1e202000u | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16) | (((mode & 0x3u) ^ 0x2u) << 22));
|
||||
}
|
||||
|
||||
void instruction_builder::fmov(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode, std::uint8_t op)
|
||||
{
|
||||
do_push(0x9e260000u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5) | (((mode & 0x3u) ^ 0x2u) << 22) | ((op & 0x1u) << 16));
|
||||
}
|
||||
|
||||
void instruction_builder::scvtf(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode)
|
||||
{
|
||||
if (mode == 1)
|
||||
do_push(0x5e79d800u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5));
|
||||
else
|
||||
do_push(0x5e21d800u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5) | ((mode & 0x1u) << 22));
|
||||
}
|
||||
|
||||
void instruction_builder::ucvtf(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode)
|
||||
{
|
||||
if (mode == 1)
|
||||
do_push(0x7e79d800u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5));
|
||||
else
|
||||
do_push(0x7e21d800u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5) | ((mode & 0x1u) << 22));
|
||||
}
|
||||
|
||||
void instruction_builder::fcvtns(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode)
|
||||
{
|
||||
do_push(0x9e200000u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5) | (((mode & 0x3u) ^ 0x2u) << 22));
|
||||
}
|
||||
|
||||
void instruction_builder::fcvtnu(std::uint8_t reg_src, std::uint8_t reg_dst, std::uint8_t mode)
|
||||
{
|
||||
do_push(0x9e210000u | (reg_dst & REG_MASK) | ((reg_src & REG_MASK) << 5) | (((mode & 0x3u) ^ 0x2u) << 22));
|
||||
}
|
||||
|
||||
void instruction_builder::ret(std::uint8_t reg)
|
||||
{
|
||||
do_push(0xd65f0000u | ((reg & REG_MASK) << 5));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue