104 lines
3.0 KiB
C
104 lines
3.0 KiB
C
#include "assembler.h"
|
|
|
|
#include <blue/core/hash.h>
|
|
#include <blue/object/dict.h>
|
|
#include <blue/object/number.h>
|
|
#include <blue/object/string.h>
|
|
#include <ivy/asm/bin.h>
|
|
#include <ivy/asm/instr.h>
|
|
#include <ivy/ident.h>
|
|
#include <ivy/selector.h>
|
|
|
|
#define R_MASK_OP 0x01800C03u
|
|
#define R_MASK_R1 0x000003FCu
|
|
#define R_MASK_R2 0x000FF000u
|
|
#define R_MASK_R3 0x01800C03u
|
|
|
|
#define R_MASK_D1 0xFE700000u
|
|
#define R_MASK_D2 0xFE7FF000u
|
|
#define R_MASK_D3 0xFE7FF3FCu
|
|
|
|
#define R_SET_OPCODE(i, op) \
|
|
(((i) & ~R_MASK_OP) | (op & 0x03u) | ((op & 0x0Cu) << 8) \
|
|
| ((op & 0x30u) << 19))
|
|
|
|
#define R_SET_R1(i, r) (((i) & ~R_MASK_R1) | ((r & 0xFFu) << 2))
|
|
#define R_SET_R2(i, r) (((i) & ~R_MASK_R2) | ((r & 0xFFu) << 12))
|
|
#define R_SET_R3(i, r) \
|
|
(((i) & ~R_MASK_R3) | ((r & 0x01u) << 22) | ((r & 0xFEu) << 24))
|
|
|
|
#define R_SET_D1(i, r) \
|
|
(((i) & ~R_MASK_D1) | ((r & 0x07u) << 20) | ((r & 0x3F8u) << 22))
|
|
#define R_SET_D2(i, r) \
|
|
(((i) & ~R_MASK_D2) | ((r & 0x7FFu) << 12) | ((r & 0x3F800u) << 14))
|
|
#define R_SET_D3(i, r) \
|
|
(((i) & ~R_MASK_D3) | ((r & 0xFFu) << 2) | ((r & 0x7FF00u) << 4) \
|
|
| ((r & 0x3F80000u) << 6))
|
|
|
|
struct block_assembler_scope {
|
|
struct assembler_scope s_base;
|
|
};
|
|
|
|
static enum ivy_status init_scope(
|
|
struct ivy_assembler *as, struct assembler_scope *scope,
|
|
const ivy_assembler_attrib_table attrib)
|
|
{
|
|
struct ivy_bin_block header = {0};
|
|
|
|
header.b_index = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_INDEX]);
|
|
assembler_write_data(as, &header, sizeof header);
|
|
|
|
struct block_assembler_scope *c = (struct block_assembler_scope *)scope;
|
|
|
|
return IVY_OK;
|
|
}
|
|
|
|
static enum ivy_status put_instr(
|
|
struct ivy_assembler *as, struct assembler_scope *scope,
|
|
const struct ivy_instr *instr)
|
|
{
|
|
uint32_t v = 0;
|
|
v = R_SET_OPCODE(v, instr->i_op->i_opcode);
|
|
|
|
switch (instr->i_op->i_layout) {
|
|
case IVY_INSTR_X:
|
|
break;
|
|
case IVY_INSTR_D:
|
|
v = R_SET_D3(v, instr->i_arg[0]);
|
|
break;
|
|
case IVY_INSTR_R1:
|
|
v = R_SET_R1(v, instr->i_arg[0]);
|
|
break;
|
|
case IVY_INSTR_R1D:
|
|
v = R_SET_R1(v, instr->i_arg[0]);
|
|
v = R_SET_D2(v, instr->i_arg[1]);
|
|
break;
|
|
case IVY_INSTR_R2:
|
|
v = R_SET_R1(v, instr->i_arg[0]);
|
|
v = R_SET_R2(v, instr->i_arg[1]);
|
|
break;
|
|
case IVY_INSTR_R2D:
|
|
v = R_SET_R1(v, instr->i_arg[0]);
|
|
v = R_SET_R2(v, instr->i_arg[1]);
|
|
v = R_SET_D1(v, instr->i_arg[2]);
|
|
break;
|
|
case IVY_INSTR_R3:
|
|
v = R_SET_R1(v, instr->i_arg[0]);
|
|
v = R_SET_R2(v, instr->i_arg[1]);
|
|
v = R_SET_R3(v, instr->i_arg[2]);
|
|
break;
|
|
default:
|
|
return IVY_ERR_INTERNAL_FAILURE;
|
|
}
|
|
|
|
b_i32 x = b_i32_htob(v);
|
|
assembler_write_data(as, &x, sizeof x);
|
|
return IVY_OK;
|
|
}
|
|
|
|
const struct assembler_scope_type block_scope_type = {
|
|
.s_scope_size = sizeof(struct block_assembler_scope),
|
|
.s_init_scope = init_scope,
|
|
.s_put_instr = put_instr,
|
|
};
|