From 08f08df6e43e64fbd544e18abf767a6923c57044 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Dec 2024 22:35:54 +0000 Subject: [PATCH 1/5] common: replace reference to b_strv_builder with b_stringstream --- common/ident.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/common/ident.c b/common/ident.c index d63c5d0..776d4ba 100644 --- a/common/ident.c +++ b/common/ident.c @@ -1,6 +1,7 @@ -#include #include +#include #include +#include #include #include @@ -23,9 +24,10 @@ void ivy_ident_destroy(struct ivy_ident *ident) b_queue_iterator_begin(&ident->id_parts, &it); while (b_queue_iterator_is_valid(&it)) { - struct ivy_ident_part *part = b_unbox(struct ivy_ident_part, it.entry, p_entry); + struct ivy_ident_part *part + = b_unbox(struct ivy_ident_part, it.entry, p_entry); b_queue_iterator_erase(&it); - + free(part->p_str); free(part); } @@ -49,21 +51,22 @@ void ivy_ident_add_part(struct ivy_ident *ident, const char *s) size_t ivy_ident_to_string(const struct ivy_ident *ident, char *out, size_t max) { - b_strv_builder strv; - b_strv_builder_begin(&strv, out, max); + b_stringstream strv; + b_stringstream_begin(&strv, out, max); int i = 0; b_queue_iterator it = {0}; b_queue_foreach (&it, &ident->id_parts) { if (i > 0) { - b_strv_builder_add(&strv, "."); + b_stringstream_add(&strv, "."); } - struct ivy_ident_part *part = b_unbox(struct ivy_ident_part, it.entry, p_entry); - b_strv_builder_add(&strv, part->p_str); + struct ivy_ident_part *part + = b_unbox(struct ivy_ident_part, it.entry, p_entry); + b_stringstream_add(&strv, part->p_str); i++; } /* TODO return string length. */ return 0; -} \ No newline at end of file +} From 3ad355e58c330482542f3f7af35f0d5cd458676b Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Dec 2024 22:36:14 +0000 Subject: [PATCH 2/5] common: add additional opcodes --- common/include/ivy/opcode.h | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/common/include/ivy/opcode.h b/common/include/ivy/opcode.h index db7d94b..ff6c6c5 100644 --- a/common/include/ivy/opcode.h +++ b/common/include/ivy/opcode.h @@ -12,7 +12,6 @@ enum ivy_instr_id { IVY_INSTR_SUB, IVY_INSTR_MUL, IVY_INSTR_DIV, - IVY_INSTR_CMP, IVY_INSTR_C_EQ, IVY_INSTR_C_NE, IVY_INSTR_C_LT, @@ -20,14 +19,8 @@ enum ivy_instr_id { IVY_INSTR_C_GT, IVY_INSTR_C_GE, IVY_INSTR_BR, - IVY_INSTR_B_Z, - IVY_INSTR_B_NZ, - IVY_INSTR_B_EQ, - IVY_INSTR_B_NE, - IVY_INSTR_B_LT, - IVY_INSTR_B_LE, - IVY_INSTR_B_GT, - IVY_INSTR_B_GE, + IVY_INSTR_BR_T, + IVY_INSTR_BR_F, IVY_INSTR_OB_C, IVY_INSTR_OB_E, IVY_INSTR_LAM_C, @@ -49,7 +42,7 @@ enum ivy_opcode { IVY_OP_LDR_SELF_CONST, IVY_OP_LDR_POOL_REG, IVY_OP_LDR_POOL_CONST, - IVY_OP_LDR_IMM, + IVY_OP_LDR_CONST, IVY_OP_STR_SP_REG, IVY_OP_STR_SP_CONST, @@ -70,8 +63,6 @@ enum ivy_opcode { IVY_OP_MUL, IVY_OP_DIV, - IVY_OP_CMP, - IVY_OP_C_EQ, IVY_OP_C_NE, IVY_OP_C_LT, @@ -80,19 +71,15 @@ enum ivy_opcode { IVY_OP_C_GE, IVY_OP_BR, - IVY_OP_B_Z, - IVY_OP_B_NZ, - IVY_OP_B_EQ, - IVY_OP_B_NE, - IVY_OP_B_LT, - IVY_OP_B_LE, - IVY_OP_B_GT, - IVY_OP_B_GE, + IVY_OP_BR_T, + IVY_OP_BR_F, - IVY_OP_OB_C, + IVY_OP_OB_C_REG, + IVY_OP_OB_C_CONST, IVY_OP_OB_E, - IVY_OP_LAM_C, + IVY_OP_LAM_C_REG, + IVY_OP_LAM_C_CONST, IVY_OP_IT_G, IVY_OP_IT_N, From b67b861ecf306f3d12fbdd305639ba83a34be45b Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Dec 2024 22:36:50 +0000 Subject: [PATCH 3/5] asm: implement instruction assembly and emission --- asm/assembler/block.c | 69 +++++++++++-- asm/assembler/lambda.c | 21 ---- asm/include/ivy/asm/instr.h | 25 +++-- asm/instr.c | 149 +++++++++++++++++++++------ asm/parse/block.c | 198 +++++++++++++++++++++++++++++++++++- 5 files changed, 397 insertions(+), 65 deletions(-) delete mode 100644 asm/assembler/lambda.c diff --git a/asm/assembler/block.c b/asm/assembler/block.c index df96b86..e996dc9 100644 --- a/asm/assembler/block.c +++ b/asm/assembler/block.c @@ -5,10 +5,35 @@ #include #include #include +#include #include #include -#include -#include + +#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; @@ -23,8 +48,7 @@ static enum ivy_status init_scope( 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; + struct block_assembler_scope *c = (struct block_assembler_scope *)scope; return IVY_OK; } @@ -33,8 +57,41 @@ static enum ivy_status put_instr( struct ivy_assembler *as, struct assembler_scope *scope, const struct ivy_instr *instr) { - uint32_t op = 0xAABBCCDD; - b_i32 x = b_i32_htob(op); + 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; } diff --git a/asm/assembler/lambda.c b/asm/assembler/lambda.c deleted file mode 100644 index 43d75ea..0000000 --- a/asm/assembler/lambda.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "assembler.h" - -#include - -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); - - return IVY_OK; -} - -const struct assembler_scope_type block_scope_type = { - .s_scope_size = sizeof(struct assembler_scope), - .s_init_scope = init_scope, -}; diff --git a/asm/include/ivy/asm/instr.h b/asm/include/ivy/asm/instr.h index 8541ab2..98f13ef 100644 --- a/asm/include/ivy/asm/instr.h +++ b/asm/include/ivy/asm/instr.h @@ -1,10 +1,21 @@ #ifndef IVY_ASM_INSTR_H_ #define IVY_ASM_INSTR_H_ +#include #include +enum ivy_instr_layout { + IVY_INSTR_X = 0, + IVY_INSTR_D, + IVY_INSTR_R1, + IVY_INSTR_R1D, + IVY_INSTR_R2, + IVY_INSTR_R2D, + IVY_INSTR_R3, +}; + enum ivy_instr_operand_type { - IVY_OPERAND_NONE = 0, + IVY_INSTR_OPERAND_NONE = 0, IVY_INSTR_OPERAND_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SELF_INDEX_REG, @@ -19,15 +30,17 @@ enum ivy_instr_operand_type { struct ivy_instr_definition { enum ivy_instr_id i_id; - enum ivy_opcopde i_opcode; + enum ivy_instr_layout i_layout; + enum ivy_opcode i_opcode; enum ivy_instr_operand_type i_operand[3]; }; struct ivy_instr { - enum ivy_opcode i_op; - long i_a0; - long i_a1; - long i_a2; + const struct ivy_instr_definition *i_op; + long i_arg[3]; }; +IVY_API const struct ivy_instr_definition *ivy_instr_find( + enum ivy_instr_id id, const enum ivy_instr_operand_type operands[4]); + #endif diff --git a/asm/instr.c b/asm/instr.c index 3b2f511..e291cb0 100644 --- a/asm/instr.c +++ b/asm/instr.c @@ -1,37 +1,128 @@ #include +#include -#define INSTR(id, op, ...) \ - [op] = { .i_id = (id), .i_opcode = (op), .i_operand = { __VA_ARGS__ }} +#define INSTR0(id, l, op) \ + [IVY_OP_##op] = { \ + .i_id = IVY_INSTR_##id, \ + .i_layout = IVY_INSTR_##l, \ + .i_opcode = IVY_OP_##op, \ + .i_operand = {}, \ + } + +#define INSTR1(id, l, op, a0) \ + [IVY_OP_##op] = { \ + .i_id = IVY_INSTR_##id, \ + .i_layout = IVY_INSTR_##l, \ + .i_opcode = IVY_OP_##op, \ + .i_operand = {IVY_INSTR_OPERAND_##a0,}, \ + } + +#define INSTR2(id, l, op, a0, a1) \ + [IVY_OP_##op] = { \ + .i_id = IVY_INSTR_##id, \ + .i_layout = IVY_INSTR_##l, \ + .i_opcode = IVY_OP_ ##op, \ + .i_operand = {IVY_INSTR_OPERAND_##a0, IVY_INSTR_OPERAND_##a1,}, \ + } + +#define INSTR3(id, l, op, a0, a1, a2) \ + [IVY_OP_##op] = {.i_id = IVY_INSTR_##id, \ + .i_layout = IVY_INSTR_##l, \ + .i_opcode = IVY_OP_##op, \ + .i_operand = { \ + IVY_INSTR_OPERAND_##a0, \ + IVY_INSTR_OPERAND_##a1, \ + IVY_INSTR_OPERAND_##a2, \ + }, \ + } /* clang-format off */ static const struct ivy_instr_definition instructions[] = { - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_SP_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SP_INDEX_REG), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_SP_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SP_INDEX_CONST), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_BP_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_BP_INDEX_REG), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_BP_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_BP_INDEX_CONST), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_SELF_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SELF_INDEX_REG), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_SELF_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SELF_INDEX_CONST), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_POOL_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_POOL_INDEX_REG), - INSTR(IVY_INSTR_LDR, IVY_OP_LDR_POOL_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_POOL_INDEX_CONST), - - INSTR(IVY_INSTR_STR, IVY_OP_LDR_SP_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SP_INDEX_REG), - INSTR(IVY_INSTR_STR, IVY_OP_LDR_SP_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SP_INDEX_CONST), - INSTR(IVY_INSTR_STR, IVY_OP_LDR_BP_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_BP_INDEX_REG), - INSTR(IVY_INSTR_STR, IVY_OP_LDR_BP_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_BP_INDEX_CONST), - INSTR(IVY_INSTR_STR, IVY_OP_LDR_SELF_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SELF_INDEX_REG), - INSTR(IVY_INSTR_STR, IVY_OP_LDR_SELF_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_SELF_INDEX_CONST), - - INSTR(IVY_INSTR_PUSH, IVY_OP_PUSH_REG, IVY_INSTR_OPERAND_REGISTER), - INSTR(IVY_INSTR_PUSH, IVY_OP_PUSH_CONST, IVY_INSTR_OPERAND_CONST), - INSTR(IVY_INSTR_POP, IVY_OP_POP, IVY_INSTR_OPERAND_REGISTER), - - INSTR(IVY_INSTR_MSG, IVY_OP_MSG_REG, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER), - INSTR(IVY_INSTR_MSG, IVY_OP_MSG_CONST, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_CONST), + INSTR2(LDR, R1D, LDR_SP_REG, REGISTER, SP_INDEX_REG), + INSTR2(LDR, R1D, LDR_SP_CONST, REGISTER, SP_INDEX_CONST), + INSTR2(LDR, R1D, LDR_BP_REG, REGISTER, BP_INDEX_REG), + INSTR2(LDR, R1D, LDR_BP_CONST, REGISTER, BP_INDEX_CONST), + INSTR2(LDR, R1D, LDR_SELF_REG, REGISTER, SELF_INDEX_REG), + INSTR2(LDR, R1D, LDR_SELF_CONST, REGISTER, SELF_INDEX_CONST), + INSTR2(LDR, R1D, LDR_POOL_REG, REGISTER, POOL_INDEX_REG), + INSTR2(LDR, R1D, LDR_POOL_CONST, REGISTER, POOL_INDEX_CONST), + INSTR2(LDR, R1D, LDR_CONST, REGISTER, CONST), - INSTR(IVY_INSTR_ADD, IVY_OP_ADD, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER), - INSTR(IVY_INSTR_SUB, IVY_OP_SUB, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER), - INSTR(IVY_INSTR_MUL, IVY_OP_MUL, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER), - INSTR(IVY_INSTR_DIV, IVY_OP_DIV, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER, IVY_INSTR_OPERAND_REGISTER), + INSTR2(STR, R1D, STR_SP_REG, REGISTER, SP_INDEX_REG), + INSTR2(STR, R1D, STR_SP_CONST, REGISTER, SP_INDEX_CONST), + INSTR2(STR, R1D, STR_BP_REG, REGISTER, BP_INDEX_REG), + INSTR2(STR, R1D, STR_BP_CONST, REGISTER, BP_INDEX_CONST), + INSTR2(STR, R1D, STR_SELF_REG, REGISTER, SELF_INDEX_REG), + INSTR2(STR, R1D, STR_SELF_CONST, REGISTER, SELF_INDEX_CONST), + INSTR1(PUSH, R1, PUSH_REG, REGISTER), + INSTR1(PUSH, R1, PUSH_CONST, CONST), + INSTR1(POP, R1, POP, REGISTER), + + INSTR3(MSG, R3, MSG_REG, REGISTER, REGISTER, REGISTER), + INSTR3(MSG, R2D, MSG_CONST, REGISTER, REGISTER, CONST), + + INSTR3(ADD, R3, ADD, REGISTER, REGISTER, REGISTER), + INSTR3(SUB, R3, SUB, REGISTER, REGISTER, REGISTER), + INSTR3(MUL, R3, MUL, REGISTER, REGISTER, REGISTER), + INSTR3(DIV, R3, DIV, REGISTER, REGISTER, REGISTER), + + INSTR2(C_EQ, R2, C_EQ, REGISTER, REGISTER), + INSTR2(C_NE, R2, C_NE, REGISTER, REGISTER), + INSTR2(C_LT, R2, C_LT, REGISTER, REGISTER), + INSTR2(C_LE, R2, C_LE, REGISTER, REGISTER), + INSTR2(C_GT, R2, C_GT, REGISTER, REGISTER), + INSTR2(C_GE, R2, C_GE, REGISTER, REGISTER), + + INSTR1(BR, D, BR, CONST), + INSTR1(BR_T, D, BR_T, CONST), + INSTR1(BR_F, D, BR_F, CONST), + + INSTR2(OB_C, R2, OB_C_REG, REGISTER, POOL_INDEX_REG), + INSTR2(OB_C, R1D, OB_C_CONST, REGISTER, POOL_INDEX_CONST), + INSTR1(OB_E, R1, OB_E, REGISTER), + + INSTR2(LAM_C, R2, LAM_C_REG, REGISTER, POOL_INDEX_REG), + INSTR2(LAM_C, R1D, LAM_C_CONST, REGISTER, POOL_INDEX_CONST), + + INSTR2(IT_G, R2, IT_G, REGISTER, REGISTER), + INSTR1(IT_N, R1, IT_N, REGISTER), + INSTR1(IT_V, R1, IT_V, REGISTER), + + INSTR0(RET, X, RET), + INSTR0(RET_N, X, RET_N), }; -/* clang-format on */ \ No newline at end of file +static const size_t nr_instructions = sizeof instructions / sizeof instructions[0]; +/* clang-format on */ + +const struct ivy_instr_definition *ivy_instr_find( + enum ivy_instr_id id, const enum ivy_instr_operand_type operands[4]) +{ + if (operands[3] != IVY_INSTR_OPERAND_NONE) { + return NULL; + } + + for (size_t i = 0; i < nr_instructions; i++) { + const struct ivy_instr_definition *def = &instructions[i]; + + if (def->i_id != id) { + continue; + } + + if (def->i_operand[0] != operands[0]) { + continue; + } + + if (def->i_operand[1] != operands[1]) { + continue; + } + + if (def->i_operand[2] != operands[2]) { + continue; + } + + return def; + } + + return NULL; +} diff --git a/asm/parse/block.c b/asm/parse/block.c index 4e2589b..9a6e8cd 100644 --- a/asm/parse/block.c +++ b/asm/parse/block.c @@ -1,12 +1,13 @@ #include "parse.h" #include +#include #include #include #include +#include #include #include -#include #include #define HASH_SELF 0x2d19e518d40792b7 @@ -93,6 +94,47 @@ struct block_parser_state { struct arg *s_current_arg; }; +struct mnemonic { + const char *m_name; + uint64_t m_hash; + enum ivy_instr_id m_id; +}; + +#define MNEMONIC(id, name, hash) \ + { \ + .m_id = (id), .m_name = (name), .m_hash = (hash) \ + } + +static const struct mnemonic mnemonics[] = { + MNEMONIC(IVY_INSTR_LDR, "ldr", 0x127688191dd0471d), + MNEMONIC(IVY_INSTR_STR, "str", 0x826e83195d0d60f0), + MNEMONIC(IVY_INSTR_PUSH, "push", 0x6c80030e2762459d), + MNEMONIC(IVY_INSTR_POP, "pop", 0x779b5819564f2f50), + MNEMONIC(IVY_INSTR_MSG, "msg", 0x07e05a191745be82), + MNEMONIC(IVY_INSTR_ADD, "add", 0xe70bc3190530e654), + MNEMONIC(IVY_INSTR_SUB, "sub", 0x82719d195d0fc2f5), + MNEMONIC(IVY_INSTR_MUL, "mul", 0x07e66519174a3ce1), + MNEMONIC(IVY_INSTR_DIV, "div", 0xcaa83a18f46e5888), + MNEMONIC(IVY_INSTR_C_EQ, "c.eq", 0x2d6e0e924e665476), + MNEMONIC(IVY_INSTR_C_NE, "c.ne", 0x2d8d12924e810bd1), + MNEMONIC(IVY_INSTR_C_LT, "c.lt", 0x2d861d924e7affd4), + MNEMONIC(IVY_INSTR_C_LE, "c.le", 0x2d860e924e7ae657), + MNEMONIC(IVY_INSTR_C_GT, "c.gt", 0x2d751f924e6c9007), + MNEMONIC(IVY_INSTR_C_GE, "c.ge", 0x2d750e924e6c7324), + MNEMONIC(IVY_INSTR_BR, "br", 0x08a64607b54df055), + MNEMONIC(IVY_INSTR_BR_T, "br.t", 0x3e0bed9c06af59cf), + MNEMONIC(IVY_INSTR_BR_F, "br.f", 0x3e0bdf9c06af4205), + MNEMONIC(IVY_INSTR_OB_C, "ob.c", 0x70bdc0b4a72facf7), + MNEMONIC(IVY_INSTR_OB_E, "ob.e", 0x70bdbeb4a72fa991), + MNEMONIC(IVY_INSTR_LAM_C, "lam.c", 0xeb2c84ec62ed7472), + MNEMONIC(IVY_INSTR_IT_G, "it.g", 0x2939c6c597a9d607), + MNEMONIC(IVY_INSTR_IT_N, "it.n", 0x2939bdc597a9c6bc), + MNEMONIC(IVY_INSTR_IT_V, "it.v", 0x2939b5c597a9b924), + MNEMONIC(IVY_INSTR_RET, "ret", 0x89e9ae1960f4a6ec), + MNEMONIC(IVY_INSTR_RET_N, "ret.n", 0x16b792f2c490f4d8), +}; +static const size_t nr_mnemonics = sizeof mnemonics / sizeof mnemonics[0]; + static unsigned long long get_register_index(struct ivy_asm_token *tok) { if (tok->t_type != IVY_ASM_TOK_IDENT) { @@ -155,9 +197,159 @@ static enum index_base get_index_base(struct ivy_asm_token *tok) } } -static enum ivy_status write_instruction(struct ivy_asm_parser *p, struct block_parser_state *state) +static enum ivy_instr_id get_instruction_id(b_queue *mnemonic_tokens) { + char mnemonic[64]; + mnemonic[0] = 0; + + b_stringstream s; + b_stringstream_begin(&s, mnemonic, sizeof mnemonic); + + unsigned int i = 0; + + b_queue_iterator it = {0}; + b_queue_iterator_begin(mnemonic_tokens, &it); + while (b_queue_iterator_is_valid(&it)) { + struct ivy_asm_token *tok + = b_unbox(struct ivy_asm_token, it.entry, t_entry); + b_queue_iterator_erase(&it); + + if (i > 0) { + b_stringstream_add(&s, "."); + } + + b_stringstream_add(&s, tok->t_str); + i++; + + ivy_asm_token_destroy(tok); + } + + uint64_t hash = b_hash_string(mnemonic); + for (i = 0; i < nr_mnemonics; i++) { + if (hash == mnemonics[i].m_hash + && !strcmp(mnemonic, mnemonics[i].m_name)) { + return mnemonics[i].m_id; + } + } + + return IVY_INSTR_NONE; +} + +static enum ivy_status write_instruction( + struct ivy_asm_parser *p, struct block_parser_state *state) +{ + /* one more than the true maximum to catch if the input has specified + * too many operands */ +#define MAX_ARGS 4 + + unsigned int i = 0; + + enum ivy_instr_id id = get_instruction_id(&state->s_mnemonic); + if (id == IVY_INSTR_NONE) { + return IVY_ERR_BAD_SYNTAX; + } + + enum ivy_instr_operand_type operand_types[MAX_ARGS] = {0}; + + b_queue_iterator it = {0}; + b_queue_foreach (&it, &state->s_args) { + struct arg *arg = b_unbox(struct arg, it.entry, arg_entry); + + if (i >= MAX_ARGS) { + return IVY_ERR_BAD_SYNTAX; + } + + switch (arg->arg_type) { + case ARG_REG: + operand_types[i++] = IVY_INSTR_OPERAND_REGISTER; + break; + case ARG_CONST: + case ARG_LABEL: + operand_types[i++] = IVY_INSTR_OPERAND_CONST; + break; + case ARG_INDEX_REG: + switch (arg->arg_index_reg.index_base) { + case INDEX_SELF: + operand_types[i++] + = IVY_INSTR_OPERAND_SELF_INDEX_REG; + break; + case INDEX_POOL: + operand_types[i++] + = IVY_INSTR_OPERAND_POOL_INDEX_REG; + case INDEX_SP: + operand_types[i++] = IVY_INSTR_OPERAND_SP_INDEX_REG; + case INDEX_BP: + operand_types[i++] = IVY_INSTR_OPERAND_BP_INDEX_REG; + default: + return IVY_ERR_BAD_SYNTAX; + } + break; + case ARG_INDEX_CONST: + switch (arg->arg_index_reg.index_base) { + case INDEX_SELF: + operand_types[i++] + = IVY_INSTR_OPERAND_SELF_INDEX_CONST; + break; + case INDEX_POOL: + operand_types[i++] + = IVY_INSTR_OPERAND_POOL_INDEX_CONST; + break; + case INDEX_SP: + operand_types[i++] + = IVY_INSTR_OPERAND_SP_INDEX_CONST; + break; + case INDEX_BP: + operand_types[i++] + = IVY_INSTR_OPERAND_BP_INDEX_CONST; + break; + default: + return IVY_ERR_BAD_SYNTAX; + } + break; + default: + return IVY_ERR_BAD_SYNTAX; + } + } + + const struct ivy_instr_definition *instr_info + = ivy_instr_find(id, operand_types); + if (!instr_info) { + return IVY_ERR_BAD_SYNTAX; + } + struct ivy_instr instr = {0}; + instr.i_op = instr_info; + i = 0; + + b_queue_iterator_begin(&state->s_args, &it); + while (b_queue_iterator_is_valid(&it)) { + struct arg *arg = b_unbox(struct arg, it.entry, arg_entry); + b_queue_iterator_erase(&it); + + switch (arg->arg_type) { + case ARG_REG: + instr.i_arg[i++] = arg->arg_reg.reg_index; + break; + case ARG_CONST: + instr.i_arg[i++] = arg->arg_const->t_int.v; + break; + case ARG_LABEL: + instr.i_arg[i++] = 0; + break; + case ARG_INDEX_REG: + instr.i_arg[i++] = arg->arg_index_reg.index_offset_reg; + break; + case ARG_INDEX_CONST: + instr.i_arg[i++] + = arg->arg_index_const.index_offset->t_int.v; + break; + default: + return IVY_ERR_BAD_SYNTAX; + } + + free(arg); + } + ivy_assembler_put_instr(p->p_assembler, &instr); return IVY_OK; } @@ -237,7 +429,7 @@ static enum ivy_status push_reg_arg( static enum ivy_status parse_linefeed( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { - struct block_parser_state *state + struct block_parser_state *state = (struct block_parser_state *)asm_parser_get_state(ctx); switch (state->s_prev_component) { From 3c05b362d72b8ef7b3cf5124bab7bf017ca34afb Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Dec 2024 22:37:05 +0000 Subject: [PATCH 4/5] doc: update with new vm instructions --- doc/sample/Person.iasm | 24 ++++++++++++------------ doc/vm-instructions.txt | 12 ++---------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/doc/sample/Person.iasm b/doc/sample/Person.iasm index b55f3a6..9d10f67 100644 --- a/doc/sample/Person.iasm +++ b/doc/sample/Person.iasm @@ -155,16 +155,16 @@ ldr x1, [bp, #-2] ldr x2, [pool, #4] - cmp x1, x2 - b.eq L0001 + c.eq x1, x2 + br.t L0001 ldr x2, [pool, #5] - cmp x1, x2 - b.eq L0002 + c.eq x1, x2 + br.t L0002 ldr x2, [pool, #6] - cmp x1, x2 - b.eq L0003 + c.eq x1, x2 + br.t L0003 ldr x0, #0 str x0, [self, #1] @@ -191,16 +191,16 @@ L0004: ldr x1, [bp, #-1] ; x1 = units ldr x2, [pool, #4] ; x2 = #years - cmp x1, x2 - b.eq L0001 ; [jump] if units == #years + c.eq x1, x2 + br.t L0001 ; [jump] if units == #years ldr x2, [pool, #5] ; x2 = #months - cmp x1, x2 - b.eq L0002 ; [jump] if units == #years + c.eq x1, x2 + br.t L0002 ; [jump] if units == #years ldr x2, [pool, #6] ; x2 = #days - cmp x1, x2 - b.eq L0003 ; [jump] if units == #days + c.eq x1, x2 + br.t L0003 ; [jump] if units == #days ldr x0, #0 ; else ret ; return 0 diff --git a/doc/vm-instructions.txt b/doc/vm-instructions.txt index 6ea80ad..7d67f7a 100755 --- a/doc/vm-instructions.txt +++ b/doc/vm-instructions.txt @@ -19,8 +19,6 @@ sub mul div -cmp - c.eq c.ne c.lt @@ -29,14 +27,8 @@ c.gt c.ge br -b.z -b.nz -b.eq -b.ne -b.lt -b.le -b.gt -b.ge +br.t +br.f ob.c ob.e From b2047d9907304e41ba75497264088d03ea4cd079 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 15 Dec 2024 22:37:19 +0000 Subject: [PATCH 5/5] vim: add new vm instructions --- ivy.vim/syntax/ivyasm.vim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ivy.vim/syntax/ivyasm.vim b/ivy.vim/syntax/ivyasm.vim index b83c9b6..b5ee242 100755 --- a/ivy.vim/syntax/ivyasm.vim +++ b/ivy.vim/syntax/ivyasm.vim @@ -8,7 +8,11 @@ set cpoptions&vim setlocal iskeyword+=@-@ setlocal iskeyword+=. syn keyword ivyasmUnspecifiedStatement @end @class @block @import @constpool @selector @ident @atom @package @property @var @msgh @lambda -syn keyword ivyasmInstruction ldr str ret ret.n cmp b.eq br add sub div mul push pop msg +syn keyword ivyasmInstruction + \ ldr str ret ret.n + \ c.z c.nz c.eq c.ne c.lt c.le c.gt c.ge + \ br br.t br.f + \ add sub div mul push pop msg syn match ivyasmRegister "x[0-9]" syn match ivyasmRegister "x[1-9][0-9]" syn keyword ivyasmIndexBase self bp sp pool