From b93c8ac9fac6002214aa5054a39ad7e014fd2da9 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Wed, 22 Mar 2023 21:16:50 +0800 Subject: [PATCH] make a framework for RISC instructions in native module --- core/scf_core_types.h | 3 + core/scf_function.h | 2 + elf/scf_elf_arm64_so.c | 3 +- native/arm64/scf_arm64.h | 184 - native/arm64/scf_arm64_inst.c | 4608 ------------- native/arm64/scf_arm64_opcode.c | 362 -- native/arm64/scf_arm64_opcode.h | 37 - native/arm64/scf_arm64_rcg.c | 1297 ---- native/arm64/scf_arm64_reg.c | 1492 ----- native/arm64/scf_arm64_reg.h | 226 - native/arm64/scf_arm64_util.c | 844 --- native/arm64/scf_arm64_util.h | 244 - native/risc/scf_arm64.c | 1609 +++++ native/{arm64/scf_arm64.c => risc/scf_risc.c} | 419 +- native/risc/scf_risc.h | 182 + .../scf_risc_bb_color.c} | 105 +- .../scf_risc_graph.c} | 106 +- native/risc/scf_risc_inst.c | 5789 +++++++++++++++++ native/risc/scf_risc_opcode.c | 362 ++ native/risc/scf_risc_opcode.h | 37 + native/risc/scf_risc_rcg.c | 1297 ++++ native/risc/scf_risc_reg.c | 1462 +++++ native/risc/scf_risc_reg.h | 203 + native/risc/scf_risc_util.h | 244 + native/scf_native.c | 28 +- native/scf_native.h | 119 +- native/x64/scf_x64.c | 2 +- native/x64/scf_x64.h | 4 +- parse/Makefile | 18 +- 29 files changed, 11631 insertions(+), 9657 deletions(-) delete mode 100644 native/arm64/scf_arm64.h delete mode 100644 native/arm64/scf_arm64_inst.c delete mode 100644 native/arm64/scf_arm64_opcode.c delete mode 100644 native/arm64/scf_arm64_opcode.h delete mode 100644 native/arm64/scf_arm64_rcg.c delete mode 100644 native/arm64/scf_arm64_reg.c delete mode 100644 native/arm64/scf_arm64_reg.h delete mode 100644 native/arm64/scf_arm64_util.c delete mode 100644 native/arm64/scf_arm64_util.h create mode 100644 native/risc/scf_arm64.c rename native/{arm64/scf_arm64.c => risc/scf_risc.c} (65%) create mode 100644 native/risc/scf_risc.h rename native/{arm64/scf_arm64_bb_color.c => risc/scf_risc_bb_color.c} (76%) rename native/{arm64/scf_arm64_graph.c => risc/scf_risc_graph.c} (74%) create mode 100644 native/risc/scf_risc_inst.c create mode 100644 native/risc/scf_risc_opcode.c create mode 100644 native/risc/scf_risc_opcode.h create mode 100644 native/risc/scf_risc_rcg.c create mode 100644 native/risc/scf_risc_reg.c create mode 100644 native/risc/scf_risc_reg.h create mode 100644 native/risc/scf_risc_util.h diff --git a/core/scf_core_types.h b/core/scf_core_types.h index db7d7c2..27cf38b 100644 --- a/core/scf_core_types.h +++ b/core/scf_core_types.h @@ -18,6 +18,9 @@ typedef struct scf_function_s scf_function_t; typedef struct scf_scope_s scf_scope_t; typedef struct scf_3ac_code_s scf_3ac_code_t; +typedef struct scf_inst_ops_s scf_inst_ops_t; +typedef struct scf_register_s scf_register_t; +typedef struct scf_OpCode_s scf_OpCode_t; enum scf_core_types { SCF_OP_ADD = 0, // + diff --git a/core/scf_function.h b/core/scf_function.h index 12b1cab..0158779 100644 --- a/core/scf_function.h +++ b/core/scf_function.h @@ -42,6 +42,8 @@ struct scf_function_s { scf_vector_t* text_relas; // re-localtions in .text segment scf_vector_t* data_relas; // re-localtions in .data segment + scf_inst_ops_t* iops; + scf_vector_t* init_insts; int init_code_bytes; diff --git a/elf/scf_elf_arm64_so.c b/elf/scf_elf_arm64_so.c index b516f66..ddca5fc 100644 --- a/elf/scf_elf_arm64_so.c +++ b/elf/scf_elf_arm64_so.c @@ -55,14 +55,13 @@ static int _arm64_elf_add_interp(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t size_t len = strlen(interp); size_t align = (len + 1 + 7) & ~0x7; - s->data = malloc(align); + s->data = calloc(1, align); if (!s->data) { scf_string_free(s->name); free(s); return -ENOMEM; } memcpy(s->data, interp, len); - s->data[len] = '\0'; s->data_len = align; s->index = 1; diff --git a/native/arm64/scf_arm64.h b/native/arm64/scf_arm64.h deleted file mode 100644 index 159baa0..0000000 --- a/native/arm64/scf_arm64.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef SCF_ARM64_H -#define SCF_ARM64_H - -#include"scf_native.h" -#include"scf_arm64_util.h" -#include"scf_arm64_reg.h" -#include"scf_arm64_opcode.h" -#include"scf_graph.h" -#include"scf_elf.h" - -#define ARM64_INST_ADD_CHECK(vec, inst) \ - do { \ - if (!(inst)) { \ - scf_loge("\n"); \ - return -ENOMEM; \ - } \ - int ret = scf_vector_add((vec), (inst)); \ - if (ret < 0) { \ - scf_loge("\n"); \ - free(inst); \ - return ret; \ - } \ - } while (0) - -#define ARM64_RELA_ADD_CHECK(vec, rela, c, v, f) \ - do { \ - rela = calloc(1, sizeof(scf_rela_t)); \ - if (!rela) \ - return -ENOMEM; \ - \ - (rela)->code = (c); \ - (rela)->var = (v); \ - (rela)->func = (f); \ - (rela)->inst = (c)->instructions->data[(c)->instructions->size - 1]; \ - (rela)->addend = 0; \ - \ - int ret = scf_vector_add((vec), (rela)); \ - if (ret < 0) { \ - free(rela); \ - rela = NULL; \ - return ret; \ - } \ - } while (0) - -#define ARM64_PEEPHOLE_DEL 1 -#define ARM64_PEEPHOLE_OK 0 - -typedef struct { - - scf_function_t* f; - -} scf_arm64_context_t; - -typedef struct { - scf_dag_node_t* dag_node; - - scf_register_arm64_t* reg; - - scf_arm64_OpCode_t* OpCode; - -} arm64_rcg_node_t; - -typedef struct { - int type; - int (*func)(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g); -} arm64_rcg_handler_t; - -typedef struct { - int type; - int (*func)(scf_native_t* ctx, scf_3ac_code_t* c); -} arm64_inst_handler_t; - -arm64_rcg_handler_t* scf_arm64_find_rcg_handler(const int op_type); -arm64_inst_handler_t* scf_arm64_find_inst_handler(const int op_type); - -int arm64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg); -int _arm64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg); - -int scf_arm64_open(scf_native_t* ctx); -int scf_arm64_close(scf_native_t* ctx); -int scf_arm64_select(scf_native_t* ctx); - -int arm64_optimize_peephole(scf_native_t* ctx, scf_function_t* f); - -int scf_arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors); - - -intptr_t arm64_bb_find_color (scf_vector_t* dn_colors, scf_dag_node_t* dn); -int arm64_save_bb_colors(scf_vector_t* dn_colors, scf_bb_group_t* bbg, scf_basic_block_t* bb); - -int arm64_bb_load_dn (intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f); -int arm64_bb_save_dn (intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f); -int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f); -int arm64_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f); - -int arm64_fix_bb_colors (scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); -int arm64_load_bb_colors (scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); -int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); -void arm64_init_bb_colors (scf_basic_block_t* bb); - - -scf_instruction_t* arm64_make_inst_G(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r); -scf_instruction_t* arm64_make_inst_E(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r); -scf_instruction_t* arm64_make_inst_I(scf_arm64_OpCode_t* OpCode, uint8_t* imm, int size); -void arm64_make_inst_I2(scf_instruction_t* inst, scf_arm64_OpCode_t* OpCode, uint8_t* imm, int size); - -scf_instruction_t* arm64_make_inst_I2E(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_dst, uint8_t* imm, int size); - -scf_instruction_t* arm64_make_inst_M ( scf_rela_t** prela, scf_arm64_OpCode_t* OpCode, scf_variable_t* v, scf_register_arm64_t* r_base); -scf_instruction_t* arm64_make_inst_I2M(scf_rela_t** prela, scf_arm64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_arm64_t* r_base, uint8_t* imm, int32_t size); - -scf_instruction_t* arm64_make_inst_G2E(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_dst, scf_register_arm64_t* r_src); -scf_instruction_t* arm64_make_inst_E2G(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_dst, scf_register_arm64_t* r_src); - -scf_instruction_t* arm64_make_inst_I2P(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_base, int32_t offset, uint8_t* imm, int size); - -scf_instruction_t* arm64_make_inst_I2SIB(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_base, scf_register_arm64_t* r_index, int32_t scale, int32_t disp, uint8_t* imm, int32_t size); - -scf_instruction_t* arm64_make_inst_SIB(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_base, scf_register_arm64_t* r_index, int32_t scale, int32_t disp, int size); -scf_instruction_t* arm64_make_inst_P( scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_base, int32_t offset, int size); - -int arm64_float_OpCode_type(int OpCode_type, int var_type); - - -int arm64_shift(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_shift_assign(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - - -int arm64_binary_assign(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_binary_assign_dereference(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_binary_assign_pointer(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_binary_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_unary_assign_dereference(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_unary_assign_pointer(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_unary_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - - -int arm64_inst_int_mul(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f); -int arm64_inst_int_div(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f, int mod_flag); - -int arm64_inst_pointer(scf_native_t* ctx, scf_3ac_code_t* c, int lea_flag); -int arm64_inst_dereference(scf_native_t* ctx, scf_3ac_code_t* c); - -int arm64_inst_float_cast(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_inst_movx(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_inst_op2(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_inst_jmp(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type); - -int arm64_inst_teq(scf_native_t* ctx, scf_3ac_code_t* c); -int arm64_inst_cmp(scf_native_t* ctx, scf_3ac_code_t* c); -int arm64_inst_set(scf_native_t* ctx, scf_3ac_code_t* c, int setcc_type); - -int arm64_inst_cmp_set(scf_native_t* ctx, scf_3ac_code_t* c, int setcc_type); - - -scf_instruction_t* arm64_make_inst(scf_3ac_code_t* c, uint32_t opcode); - -int arm64_make_inst_I2G (scf_3ac_code_t* c, scf_register_arm64_t* rd, uint64_t imm, int bytes); -int arm64_make_inst_M2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, scf_variable_t* vs); -int arm64_make_inst_M2GF (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, scf_variable_t* vs); -int arm64_make_inst_G2M (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rs, scf_register_arm64_t* rb, scf_variable_t* vs); -int arm64_make_inst_G2P (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rs, scf_register_arm64_t* rb, int32_t offset, int size); -int arm64_make_inst_P2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, int32_t offset, int size); -int arm64_make_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_variable_t* vs); -int arm64_make_inst_SIB2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, arm64_sib_t* sib); -int arm64_make_inst_G2SIB (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, arm64_sib_t* sib); -int arm64_make_inst_ADR2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_variable_t* vs); -int arm64_make_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, int32_t offset); -int arm64_make_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, arm64_sib_t* sib); - -int arm64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg); - -#endif - diff --git a/native/arm64/scf_arm64_inst.c b/native/arm64/scf_arm64_inst.c deleted file mode 100644 index bd94ad7..0000000 --- a/native/arm64/scf_arm64_inst.c +++ /dev/null @@ -1,4608 +0,0 @@ -#include"scf_arm64.h" - -#define ARM64_INST_OP3_CHECK() \ - if (!c->dsts || c->dsts->size != 1) \ - return -EINVAL; \ - \ - if (!c->srcs || c->srcs->size != 2) \ - return -EINVAL; \ - \ - scf_arm64_context_t* arm64 = ctx->priv; \ - scf_function_t* f = arm64->f; \ - \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - scf_3ac_operand_t* src0 = c->srcs->data[0]; \ - scf_3ac_operand_t* src1 = c->srcs->data[1]; \ - \ - if (!src0 || !src0->dag_node) \ - return -EINVAL; \ - \ - if (!src1 || !src1->dag_node) \ - return -EINVAL; \ - \ - if (!dst || !dst->dag_node) \ - return -EINVAL; \ - \ - if (src0->dag_node->var->size != src1->dag_node->var->size) {\ - scf_loge("size: %d, %d\n", src0->dag_node->var->size, src1->dag_node->var->size); \ - return -EINVAL; \ - } - - -static int _arm64_inst_call_stack_size(scf_3ac_code_t* c) -{ - int stack_size = 0; - - int i; - for (i = 1; i < c->srcs->size; i++) { - scf_3ac_operand_t* src = c->srcs->data[i]; - scf_variable_t* v = src->dag_node->var; - - if (src->dag_node->rabi2) - continue; - - int size = arm64_variable_size(v); - if (size & 0x7) - size = (size + 7) >> 3 << 3; - - v->sp_offset = stack_size; - stack_size += size; - } - assert(0 == (stack_size & 0x7)); - - if (stack_size & 0xf) - stack_size += 8; - - return stack_size; -} - -static int _arm64_load_const_arg(scf_register_arm64_t* rabi, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_instruction_t* inst; - scf_arm64_OpCode_t* lea; - scf_arm64_OpCode_t* mov; - scf_variable_t* v; - - v = dn->var; - - int size = arm64_variable_size(v); - int is_float = scf_variable_float(v); - - if (SCF_FUNCTION_PTR == v->type) { - - if (v->func_ptr) { - assert(v->const_literal_flag); - - v->global_flag = 1; - v->local_flag = 0; - v->tmp_flag = 0; - - return arm64_make_inst_M2G(c, f, rabi, NULL, v); - - } else { - uint32_t opcode; - - opcode = (0xcb << 24) | (rabi->id << 16) | (rabi->id << 5) | rabi->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - scf_loge("\n"); - return -EINVAL; - } - - } else if (scf_variable_const_string(v)) { - - return arm64_make_inst_ISTR2G(c, f, rabi, v); - - } else if (v->nb_dimentions > 0) { - assert(v->const_literal_flag); - - return arm64_make_inst_ADR2G(c, f, rabi, v); - } - - return arm64_make_inst_I2G(c, rabi, v->data.u64, size); -} - -static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) -{ - scf_register_arm64_t* sp = arm64_find_register("sp"); - - scf_arm64_OpCode_t* lea; - scf_arm64_OpCode_t* mov; - scf_arm64_OpCode_t* movx; - scf_instruction_t* inst; - - uint32_t opcode; - - int nb_floats = 0; - int ret; - int i; - for (i = c->srcs->size - 1; i >= 1; i--) { - scf_3ac_operand_t* src = c->srcs->data[i]; - scf_variable_t* v = src->dag_node->var; - scf_register_arm64_t* rd = src->rabi; - scf_register_arm64_t* rabi = src->dag_node->rabi2; - scf_register_arm64_t* rs = NULL; - - int size = arm64_variable_size(v); - int is_float = scf_variable_float(v); - - if (!rabi) { - rabi = arm64_find_register_type_id_bytes(is_float, SCF_ARM64_REG_X0, size); - - ret = arm64_overflow_reg(rabi, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - movx = NULL; - - if (!is_float) { - mov = arm64_find_OpCode(SCF_ARM64_MOV, 8, 8, SCF_ARM64_G2E); - - if (size < 8) { - if (scf_variable_signed(v)) - movx = arm64_find_OpCode(SCF_ARM64_MOVSX, size, 8, SCF_ARM64_E2G); - else if (size < 4) - movx = arm64_find_OpCode(SCF_ARM64_MOVZX, size, 8, SCF_ARM64_E2G); - } - - if (0 == src->dag_node->color) { - - ret = arm64_overflow_reg(rabi, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = _arm64_load_const_arg(rabi, src->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - rabi = arm64_find_register_color_bytes(rabi->color, 8); - rs = rabi; - } else { - if (src->dag_node->color < 0) - src->dag_node->color = rabi->color; - } - } else { - nb_floats++; - - if (0 == src->dag_node->color) { - src->dag_node->color = -1; - v->global_flag = 1; - } - - if (SCF_VAR_FLOAT == v->type) { - mov = arm64_find_OpCode(SCF_ARM64_MOVSS, 4, 4, SCF_ARM64_G2E); - movx = arm64_find_OpCode(SCF_ARM64_CVTSS2SD, 4, 8, SCF_ARM64_E2G); - } else - mov = arm64_find_OpCode(SCF_ARM64_MOVSD, size, size, SCF_ARM64_G2E); - - if (src->dag_node->color < 0) - src->dag_node->color = rabi->color; - } - - if (!rs) { - assert(src->dag_node->color > 0); - - if (rd && ARM64_COLOR_CONFLICT(rd->color, src->dag_node->color)) { - - ret = arm64_overflow_reg2(rd, src->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - rs = arm64_find_register_color_bytes(rs->color, 8); - } - - if (movx) { - if (SCF_ARM64_MOVSX == movx->type) { - if (1 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0x7 << 10) | (rs->id << 5) | rs->id; - else if (2 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0xf << 10) | (rs->id << 5) | rs->id; - else if (4 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0x1f << 10) | (rs->id << 5) | rs->id; - else - return -EINVAL; - - } else if (SCF_ARM64_MOVZX == movx->type) { - - if (1 == size) - opcode = (0x53 << 24) | (0x7 << 10) | (rs->id << 5) | rs->id; - else if (2 == size) - opcode = (0x53 << 24) | (0xf << 10) | (rs->id << 5) | rs->id; - else - return -EINVAL; - - } else { - assert(SCF_ARM64_CVTSS2SD == movx->type); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (0x3 << 14) | (rs->id << 5) | rs->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - if (!rd) { - ret = arm64_make_inst_G2P(c, f, rs, sp, v->sp_offset, size); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - continue; - } - - ret = arm64_overflow_reg2(rd, src->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (!ARM64_COLOR_CONFLICT(rd->color, rs->color)) { - rd = arm64_find_register_color_bytes(rd->color, rs->bytes); - - if (is_float) - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - else - opcode = (0x1e << 24) | (0x3 << 21) | (0x1 << 14) | (rs->id << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - ret = arm64_rcg_make(c, c->rcg, NULL, rd); - if (ret < 0) - return ret; - } - - return nb_floats; -} - -static int _arm64_call_save_ret_regs(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf) -{ - scf_register_arm64_t* r; - scf_variable_t* v; - - int i; - for (i = 0; i < pf->rets->size; i++) { - v = pf->rets->data[i]; - - int is_float = scf_variable_float(v); - - if (is_float) { - - if (i > 0) { - scf_loge("\n"); - return -1; - } - - r = arm64_find_register_type_id_bytes(is_float, 0, 8); - } else - r = arm64_find_register_type_id_bytes(is_float, arm64_abi_ret_regs[i], 8); - - int ret = arm64_overflow_reg(r, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - return 0; -} - -static int _arm64_dst_reg_valid(scf_register_arm64_t* rd, scf_register_arm64_t** updated_regs, int nb_updated, int abi_idx, int abi_total) -{ - scf_register_arm64_t* r; - - int i; - for (i = 0; i < nb_updated; i++) { - - r = updated_regs[i]; - - if (ARM64_COLOR_CONFLICT(r->color, rd->color)) - return 0; - } - - for (i = abi_idx; i < abi_total; i++) { - - r = arm64_find_register_type_id_bytes(ARM64_COLOR_TYPE(rd->color), arm64_abi_ret_regs[i], rd->bytes); - - if (ARM64_COLOR_CONFLICT(r->color, rd->color)) - return 0; - } - - return 1; -} - -static int _arm64_call_update_dsts(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t** updated_regs, int max_updated) -{ - scf_3ac_operand_t* dst; - scf_dag_node_t* dn; - scf_variable_t* v; - - scf_register_arm64_t* rd; - scf_register_arm64_t* rs; - scf_arm64_OpCode_t* mov; - - int nb_float = 0; - int nb_int = 0; - - int i; - for (i = 0; i < c->dsts->size; i++) { - dst = c->dsts->data[i]; - dn = dst->dag_node; - v = dn->var; - - if (SCF_VAR_VOID == v->type && 0 == v->nb_pointers) - continue; - - assert(0 != dn->color); - - int is_float = scf_variable_float(v); - - if (is_float) - nb_float++; - else - nb_int++; - } - - int nb_updated = 0; - int idx_float = 0; - int idx_int = 0; - - for (i = 0; i < c->dsts->size; i++) { - dst = c->dsts->data[i]; - dn = dst->dag_node; - v = dn->var; - - if (SCF_VAR_VOID == v->type && 0 == v->nb_pointers) - continue; - - int is_float = scf_variable_float(v); - int dst_size = arm64_variable_size (v); - - if (is_float) { - if (i > 0) { - scf_loge("\n"); - return -1; - } - - scf_loge("\n"); - return -EINVAL; - - rs = arm64_find_register_type_id_bytes(is_float, SCF_ARM64_REG_X0, dst_size); - - if (SCF_VAR_FLOAT == dn->var->type) - mov = arm64_find_OpCode(SCF_ARM64_MOVSS, dst_size, dst_size, SCF_ARM64_G2E); - else - mov = arm64_find_OpCode(SCF_ARM64_MOVSD, dst_size, dst_size, SCF_ARM64_G2E); - - idx_float++; - } else { - rs = arm64_find_register_type_id_bytes(is_float, arm64_abi_ret_regs[idx_int], dst_size); - - mov = arm64_find_OpCode(SCF_ARM64_MOV, dst_size, dst_size, SCF_ARM64_G2E); - - idx_int++; - } - - scf_instruction_t* inst; - - if (dn->color > 0) { - rd = arm64_find_register_color(dn->color); - - int rd_vars = arm64_reg_cached_vars(rd); - - if (rd_vars > 1) { - dn->color = -1; - dn->loaded = 0; - scf_vector_del(rd->dag_nodes, dn); - - } else if (rd_vars > 0 - && !scf_vector_find(rd->dag_nodes, dn)) { - dn->color = -1; - dn->loaded = 0; - - } else { - ARM64_SELECT_REG_CHECK(&rd, dn, c, f, 0); - - if (dn->color == rs->color) { - assert(nb_updated < max_updated); - - updated_regs[nb_updated++] = rs; - continue; - } - - int valid = _arm64_dst_reg_valid(rd, updated_regs, nb_updated, idx_int, nb_int); - if (valid) { - - uint32_t opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - assert(nb_updated < max_updated); - - updated_regs[nb_updated++] = rd; - continue; - } - - assert(0 == scf_vector_del(rd->dag_nodes, dn)); - dn->color = -1; - dn->loaded = 0; - } - } - - int rs_vars = arm64_reg_cached_vars(rs); - - if (0 == rs_vars) { - if (scf_vector_add(rs->dag_nodes, dn) < 0) - return -ENOMEM; - - assert(nb_updated < max_updated); - - updated_regs[nb_updated++] = rs; - - dn->color = rs->color; - dn->loaded = 1; - - } else { - int ret = arm64_make_inst_G2M(c, f, rs, NULL, dn->var); - if (ret < 0) - return ret; - } - } - return nb_updated; -} - -static int _arm64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (c->srcs->size < 1) { - scf_loge("\n"); - return -EINVAL; - } - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* src0 = c->srcs->data[0]; - scf_variable_t* var_pf = src0->dag_node->var; - scf_function_t* pf = var_pf->func_ptr; - - if (SCF_FUNCTION_PTR != var_pf->type || !pf) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* lr = arm64_find_register("lr"); - scf_register_arm64_t* sp = arm64_find_register("sp"); - scf_register_arm64_t* x0 = arm64_find_register("x0"); - scf_instruction_t* inst; - scf_instruction_t* inst_sp = NULL; - scf_instruction_t* inst_sp2 = NULL; - - lr->used = 1; - sp->used = 1; - - int data_rela_size = f->data_relas->size; - int text_rela_size = f->text_relas->size; - scf_loge("f->data_relas->size: %d, f->text_relas->size: %d\n", f->data_relas->size, f->text_relas->size); - - uint32_t opcode; - int ret; - int i; - - if (pf->rets) { - ret = _arm64_call_save_ret_regs(c, f, pf); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - ret = arm64_overflow_reg(x0, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - arm64_call_rabi(NULL, NULL, c); - - int32_t stack_size = _arm64_inst_call_stack_size(c); - if (stack_size > 0) { - inst_sp = arm64_make_inst(c, 0); - inst_sp2 = arm64_make_inst(c, 0); - ARM64_INST_ADD_CHECK(c->instructions, inst_sp); - ARM64_INST_ADD_CHECK(c->instructions, inst_sp2); - } - - ret = _arm64_inst_call_argv(c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - scf_register_arm64_t* saved_regs[ARM64_ABI_CALLER_SAVES_NB]; - - int save_size = arm64_caller_save_regs(c, f, arm64_abi_caller_saves, ARM64_ABI_CALLER_SAVES_NB, stack_size, saved_regs); - if (save_size < 0) { - scf_loge("\n"); - return save_size; - } - - if (stack_size > 0) { - assert(inst_sp); - assert(inst_sp2); - - if (stack_size <= 0xfff) - opcode = (0xd1 << 24) | (stack_size << 10) | (sp->id << 5) | sp->id; - else { - stack_size += 1 << 12; - stack_size &= ~0xfff; - - if (stack_size < 0 || (stack_size >> 12) > 0xfff) { - scf_loge("\n"); - return -EINVAL; - } - - opcode = (0xd1 << 24) | (0x1 << 22) | ((stack_size >> 12) << 10) | (sp->id << 5) | sp->id; - } - - memcpy(inst_sp->code, &opcode, 4); - - if (save_size > 0xfff) { - scf_loge("\n"); - return -EINVAL; - } - - if (save_size > 0) { - opcode = (0xd1 << 24) | (save_size << 10) | (sp->id << 5) | sp->id; - memcpy(inst_sp2->code, &opcode, 4); - } - } - - if (var_pf->const_literal_flag) { - assert(0 == src0->dag_node->color); - - opcode = 0x25 << 26; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - scf_rela_t* rela = NULL; - - ARM64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); - rela->type = R_AARCH64_CALL26; - - } else { - assert(0 != src0->dag_node->color); - - if (src0->dag_node->color > 0) { - - scf_register_arm64_t* r_pf = NULL; - - ret = arm64_select_reg(&r_pf, src0->dag_node, c, f, 1); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - opcode = (0xd63f << 16) | (r_pf->id << 5); - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - } else { - scf_loge("\n"); - return -EINVAL; - } - } - - if (stack_size > 0) { - - if (stack_size <= 0xfff) - opcode = (0x91 << 24) | (stack_size << 10) | (sp->id << 5) | sp->id; - else - opcode = (0x91 << 24) | (0x1 << 22) | ((stack_size >> 12) << 10) | (sp->id << 5) | sp->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - int nb_updated = 0; - scf_register_arm64_t* updated_regs[ARM64_ABI_RET_NB * 2]; - - if (pf->rets && pf->rets->size > 0 && c->dsts) { - - nb_updated = _arm64_call_update_dsts(c, f, updated_regs, ARM64_ABI_RET_NB * 2); - if (nb_updated < 0) { - scf_loge("\n"); - return nb_updated; - } - } - - if (save_size > 0) { - ret = arm64_pop_regs(c, saved_regs, save_size >> 3, updated_regs, nb_updated); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - return 0; -} - -static int _arm64_inst_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* s = src->dag_node; - scf_dag_node_t* d = dst->dag_node; - - uint32_t opcode; - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - uint64_t u = s->var->data.u64; - - int ret = arm64_make_inst_I2G(c, rd, u, 8); - if (ret < 0) - return ret; - - opcode = (0xaa << 24) | (0x1 << 21) | (rd->id << 16) | (0x1f << 10) | rd->id; - - } else { - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0xaa << 24) | (0x1 << 21) | (rs->id << 16) | (0x1f << 10) | rd->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_inc_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_instruction_t* inst = NULL; - scf_function_t* f = arm64->f; - - if (!src || !src->dag_node) - return -EINVAL; - - if (0 == src->dag_node->color) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - uint32_t opcode = (0x91 << 24) | (0x1 << 10) | (rs->id << 5) | rs->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -static int _arm64_inst_inc_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_instruction_t* inst = NULL; - scf_function_t* f = arm64->f; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (0 == src->dag_node->color) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - uint32_t opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = (0x91 << 24) | (0x1 << 10) | (rs->id << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_dec_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_instruction_t* inst = NULL; - scf_function_t* f = arm64->f; - - if (!src || !src->dag_node) - return -EINVAL; - - if (0 == src->dag_node->color) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - uint32_t opcode = (0xd1 << 24) | (0x1 << 10) | (rs->id << 5) | rs->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -static int _arm64_inst_dec_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_instruction_t* inst = NULL; - scf_function_t* f = arm64->f; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (0 == src->dag_node->color) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - uint32_t opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = (0xd1 << 24) | (0x1 << 10) | (rs->id << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - assert(0 != dst->dag_node->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* s = src->dag_node; - scf_dag_node_t* d = dst->dag_node; - scf_variable_t* v = d->var; - - uint32_t opcode; - - int is_float = scf_variable_float(v); - int size = arm64_variable_size(v); - - if (!is_float) { - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - uint64_t u = s->var->data.u64; - - int ret = arm64_make_inst_I2G(c, rd, u, 8); - if (ret < 0) - return ret; - - opcode = (0xcb << 24) | (rd->id << 16) | (0x1f << 10) | rd->id; - - } else { - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0xcb << 24) | (rs->id << 16) | (0x1f << 10) | rd->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - -#if 0 - scf_arm64_OpCode_t* pxor = arm64_find_OpCode(SCF_ARM64_PXOR, 8, 8, SCF_ARM64_E2G); - scf_arm64_OpCode_t* sub = arm64_find_OpCode(SCF_ARM64_SUBSS, 4, 4, SCF_ARM64_E2G); - - if (v->size > 4) - sub = arm64_find_OpCode(SCF_ARM64_SUBSD, 8, 8, SCF_ARM64_E2G); - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - inst = arm64_make_inst_E2G(pxor, rd, rd); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (src->dag_node->color > 0) { - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - inst = arm64_make_inst_E2G(sub, rd, rs); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - } else { - scf_rela_t* rela = NULL; - - v = src->dag_node->var; - - if (0 == src->dag_node->color) { - v->global_flag = 1; - v->local_flag = 0; - v->tmp_flag = 0; - } - - inst = arm64_make_inst_M2G(&rela, sub, rd, NULL, v); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); - } -#endif - return -1; -} - -static int _arm64_inst_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* member = c->srcs->data[1]; - scf_instruction_t* inst; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!member || !member->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vd = dst ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vm = member->dag_node->var; - - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - int ret = arm64_select_reg(&rd, dst->dag_node, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); - if (ret < 0) - return ret; - - if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) - - return arm64_make_inst_ADRP2G(c, f, rd, sib.base, sib.disp); - - if (sib.index) - return arm64_make_inst_SIB2G(c, f, rd, &sib); - - return arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); -} - -static int _arm64_inst_binary_assign_pointer(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) -{ - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* member = c->srcs->data[1]; - scf_3ac_operand_t* src = c->srcs->data[2]; - scf_instruction_t* inst; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!member || !member->dag_node) - return -EINVAL; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vs = src ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vm = member->dag_node->var; - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - arm64_sib_t sib = {0}; - - int ret = arm64_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); - if (ret < 0) - return ret; - - if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) - return -EINVAL; - - int is_float = scf_variable_float(vs); - - if (0 == src->dag_node->color) { - - if (is_float) { - - src->dag_node->color = -1; - vs->global_flag = 1; - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - } else { - ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, vs->data.u64, sib.size); - if (ret < 0) - return ret; - - rs = arm64_find_register_color_bytes(rs->color, sib.size); - } - } else - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - if (op) { - uint32_t opcode; - - ret = arm64_select_free_reg(&rd, c, f, is_float); - if (ret < 0) - return ret; - - ret = arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode = ((8 == sib.size) << 31)| op | (rs->id << 16) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - rs = rd; - } - - return arm64_make_inst_G2P(c, f, rs, sib.base, sib.disp, sib.size); -} - -static int _arm64_inst_inc_dec_pointer(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* member = c->srcs->data[1]; - scf_instruction_t* inst; - - uint32_t opcode; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!member || !member->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vm = member->dag_node->var; - scf_register_arm64_t* r = NULL; - arm64_sib_t sib = {0}; - - int size = arm64_variable_size(vm); - - int ret = arm64_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); - if (ret < 0) - return ret; - - if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) - return -EINVAL; - - int is_float = scf_variable_float(vm); - if (is_float) { - scf_loge("\n"); - return -EINVAL; - } - - ret = arm64_select_free_reg(&r, c, f, 0); - if (ret < 0) - return ret; - - if (sib.index) - ret = arm64_make_inst_SIB2G(c, f, r, &sib); - else - ret = arm64_make_inst_P2G(c, f, r, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode = ((8 == size) << 31) | (u24 << 24) | (0x1 << 10) | (r->id << 5) | r->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (sib.index) - ret = arm64_make_inst_G2SIB(c, f, r, &sib); - else - ret = arm64_make_inst_G2P(c, f, r, sib.base, sib.disp, sib.size); - return ret; -} - -static int _arm64_inst_inc_dec_post_pointer(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* member = c->srcs->data[1]; - scf_instruction_t* inst; - - uint32_t opcode; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!member || !member->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vd = dst ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vm = member->dag_node->var; - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - int size = arm64_variable_size(vm); - - int ret = arm64_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); - if (ret < 0) - return ret; - - if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) - return -EINVAL; - - int is_float = scf_variable_float(vm); - if (is_float) { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - if (sib.index) - ret = arm64_make_inst_SIB2G(c, f, rd, &sib); - else - ret = arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode = ((8 == size) << 31) | (u24 << 24) | (0x1 << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (sib.index) - ret = arm64_make_inst_G2SIB(c, f, rd, &sib); - else - ret = arm64_make_inst_G2P(c, f, rd, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode &= ~(1 << 30); - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_inc_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_pointer(ctx, c, 0x11); -} - -static int _arm64_inst_dec_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_pointer(ctx, c, 0x51); -} - -static int _arm64_inst_inc_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_post_pointer(ctx, c, 0x11); -} - -static int _arm64_inst_dec_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_post_pointer(ctx, c, 0x51); -} - -static int _arm64_inst_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* member = c->srcs->data[1]; - scf_instruction_t* inst; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!member || !member->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - scf_variable_t* vd = dst ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vm = member->dag_node->var; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - int ret = arm64_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); - if (ret < 0) - return ret; - - return arm64_make_inst_ADRP2G(c, f, rd, sib.base, sib.disp); -} - -static int _arm64_inst_binary_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) -{ - if (!c->srcs || c->srcs->size != 4) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* index = c->srcs->data[1]; - scf_3ac_operand_t* scale = c->srcs->data[2]; - scf_3ac_operand_t* src = c->srcs->data[3]; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!index || !index->dag_node) - return -EINVAL; - - if (!scale || !scale->dag_node) - return -EINVAL; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vscale = scale->dag_node->var; - scf_variable_t* vb = base->dag_node->var; - scf_variable_t* vs = src ->dag_node->var; - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - arm64_sib_t sib = {0}; - scf_instruction_t* inst; - - int is_float = scf_variable_float(vs); - int size = arm64_variable_size (vs); - - if (size > vscale->data.i) - size = vscale->data.i; - - int ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (0 == src->dag_node->color) { - - if (is_float) { - - src->dag_node->color = -1; - vs->global_flag = 1; - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - } else { - ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, vs->data.u64, size); - if (ret < 0) - return ret; - - rs = arm64_find_register_color_bytes(rs->color, size); - } - } else - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - if (op) { - uint32_t opcode; - - ret = arm64_select_free_reg(&rd, c, f, is_float); - if (ret < 0) - return ret; - - if (sib.index) - ret = arm64_make_inst_SIB2G(c, f, rd, &sib); - else - ret = arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode = ((8 == size) << 31) | op | (rs->id << 16) | (rd->id << 5) | rd->id | (is_float << 26); - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - rs = rd; - } - - if (sib.index) - ret = arm64_make_inst_G2SIB(c, f, rs, &sib); - else - ret = arm64_make_inst_G2P(c, f, rs, sib.base, sib.disp, size); - if (ret < 0) - return ret; - - return 0; -} - -static int _arm64_inst_inc_dec_array_index(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* index = c->srcs->data[1]; - scf_3ac_operand_t* scale = c->srcs->data[2]; - - uint32_t opcode; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!index || !index->dag_node) - return -EINVAL; - - if (!scale || !scale->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vscale = scale->dag_node->var; - scf_variable_t* vb = base->dag_node->var; - - scf_register_arm64_t* r = NULL; - arm64_sib_t sib = {0}; - scf_instruction_t* inst; - - int size = vb->data_size; - - int ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = arm64_select_free_reg(&r, c, f, 0); - if (ret < 0) - return ret; - - r = arm64_find_register_color_bytes(r->color, size); - - if (sib.index) - ret = arm64_make_inst_SIB2G(c, f, r, &sib); - else - ret = arm64_make_inst_P2G(c, f, r, sib.base, sib.disp, size); - if (ret < 0) - return ret; - - opcode = ((8 == size) << 31) | (u24 << 24) | (0x1 << 10) | (r->id << 5) | r->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (sib.index) - ret = arm64_make_inst_G2SIB(c, f, r, &sib); - else - ret = arm64_make_inst_G2P(c, f, r, sib.base, sib.disp, size); - return ret; -} - -static int _arm64_inst_inc_dec_post_array_index(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* index = c->srcs->data[1]; - scf_3ac_operand_t* scale = c->srcs->data[2]; - - uint32_t opcode; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!index || !index->dag_node) - return -EINVAL; - - if (!scale || !scale->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vscale = scale->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vd = dst ->dag_node->var; - - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - scf_instruction_t* inst; - - int size = vb->data_size; - - int ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - if (sib.index) - ret = arm64_make_inst_SIB2G(c, f, rd, &sib); - else - ret = arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, size); - if (ret < 0) - return ret; - - opcode = ((8 == size) << 31) | (u24 << 24) | (0x1 << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (sib.index) - ret = arm64_make_inst_G2SIB(c, f, rd, &sib); - else - ret = arm64_make_inst_G2P(c, f, rd, sib.base, sib.disp, size); - if (ret < 0) - return ret; - - opcode &= ~(0x1 << 30); - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_inc_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_array_index(ctx, c, 0x11); -} - -static int _arm64_inst_dec_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_array_index(ctx, c, 0x51); -} - -static int _arm64_inst_inc_post_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_post_array_index(ctx, c, 0x11); -} - -static int _arm64_inst_dec_post_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_inc_dec_post_array_index(ctx, c, 0x51); -} - -static int _arm64_inst_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* index = c->srcs->data[1]; - scf_3ac_operand_t* scale = c->srcs->data[2]; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!index || !index->dag_node) - return -EINVAL; - - if (!scale || !scale->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vd = dst ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vi = index->dag_node->var; - scf_variable_t* vs = scale->dag_node->var; - - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - scf_instruction_t* inst; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - int ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (vb->nb_dimentions > 1) { - - if (sib.index) - ret = arm64_make_inst_ADRSIB2G(c, f, rd, &sib); - else - ret = arm64_make_inst_ADRP2G(c, f, rd, sib.base, sib.disp); - return ret; - } - - if (sib.index) - return arm64_make_inst_SIB2G(c, f, rd, &sib); - - return arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); -} - -static int _arm64_inst_address_of_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* index = c->srcs->data[1]; - scf_3ac_operand_t* scale = c->srcs->data[2]; - scf_instruction_t* inst; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!index || !index->dag_node) - return -EINVAL; - - if (!scale || !scale->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vd = dst ->dag_node->var; - scf_variable_t* vb = base ->dag_node->var; - scf_variable_t* vi = index->dag_node->var; - scf_variable_t* vs = scale->dag_node->var; - - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - int ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (sib.index) - ret = arm64_make_inst_ADRSIB2G(c, f, rd, &sib); - else - ret = arm64_make_inst_ADRP2G(c, f, rd, sib.base, sib.disp); - - return ret; -} - -static int _arm64_inst_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* rd = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_instruction_t* inst; - scf_function_t* f = arm64->f; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - arm64_sib_t sib = {0}; - - int size = base->dag_node->var->data_size; - - int ret = arm64_dereference_reg(&sib, base->dag_node, NULL, c, f); - if (ret < 0) - return ret; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - return arm64_make_inst_P2G(c, f, rd, sib.base, 0, size); -} - -static int _arm64_inst_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rax = arm64_find_register("rax"); - scf_arm64_OpCode_t* push; - scf_instruction_t* inst; - -#if 0 - push = arm64_find_OpCode(SCF_ARM64_PUSH, 8,8, SCF_ARM64_G); - inst = arm64_make_inst_G(push, rax); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -#endif - return -1; -} - -static int _arm64_inst_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rax = arm64_find_register("rax"); - scf_arm64_OpCode_t* pop; - scf_instruction_t* inst; -#if 0 - pop = arm64_find_OpCode(SCF_ARM64_POP, 8,8, SCF_ARM64_G); - inst = arm64_make_inst_G(pop, rax); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -#endif - return -1; -} - -/* - -struct va_list -{ - uint8_t* iptr; - uint8_t* fptr; - uint8_t* optr; - - intptr_t ireg; - intptr_t freg; -}; -*/ - -static int _arm64_inst_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_loge("c->srcs->size: %d\n", c->srcs->size); - assert(3 == c->srcs->size); - - scf_register_arm64_t* rbp = arm64_find_register("rbp"); - scf_register_arm64_t* rptr = NULL; - scf_register_arm64_t* rap = NULL; - scf_instruction_t* inst = NULL; - scf_3ac_operand_t* ap = c->srcs->data[0]; - scf_3ac_operand_t* ptr = c->srcs->data[2]; - scf_arm64_OpCode_t* mov = arm64_find_OpCode(SCF_ARM64_MOV, 8, 8, SCF_ARM64_G2E); - scf_arm64_OpCode_t* lea = arm64_find_OpCode(SCF_ARM64_LEA, 8, 8, SCF_ARM64_E2G); - scf_variable_t* v = ap->dag_node->var; - - int offset_int = -f->args_int * 8 - 8; - int offset_float = -f->args_float * 8 - ARM64_ABI_NB * 8 - 8; - int offset_others = 16; - - if (v->bp_offset >= 0) { - scf_loge("\n"); - return -1; - } -#if 0 - ARM64_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); - ARM64_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); - - inst = arm64_make_inst_P2G(lea, rptr, rbp, offset_int); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 0, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - - inst = arm64_make_inst_P2G(lea, rptr, rbp, offset_float); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 8, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - - inst = arm64_make_inst_P2G(lea, rptr, rbp, offset_others); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 16, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - - mov = arm64_find_OpCode(SCF_ARM64_MOV, 4, 8, SCF_ARM64_I2E); - - inst = arm64_make_inst_I2P(mov, rap, 24, (uint8_t*)&f->args_int, 4); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_I2P(mov, rap, 32, (uint8_t*)&f->args_float, 4); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -#endif - return -1; -} - -static int _arm64_inst_va_end_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - assert(2 == c->srcs->size); - - scf_register_arm64_t* rbp = arm64_find_register("rbp"); - scf_register_arm64_t* rptr = NULL; - scf_register_arm64_t* rap = NULL; - scf_instruction_t* inst = NULL; - scf_3ac_operand_t* ap = c->srcs->data[0]; - scf_3ac_operand_t* ptr = c->srcs->data[1]; - scf_arm64_OpCode_t* mov = arm64_find_OpCode(SCF_ARM64_MOV, 8, 8, SCF_ARM64_G2E); - scf_arm64_OpCode_t* xor = arm64_find_OpCode(SCF_ARM64_XOR, 8, 8, SCF_ARM64_G2E); - scf_variable_t* v = ap->dag_node->var; - - if (v->bp_offset >= 0) { - scf_loge("\n"); - return -1; - } - - ptr->dag_node->var->tmp_flag = 1; - ptr->dag_node->color = -1; -#if 0 - ARM64_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); - ARM64_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); - - inst = arm64_make_inst_G2E(xor, rptr, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 0, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 8, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 16, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 24, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst_G2P(mov, rap, 32, rptr); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - ptr->dag_node->var->tmp_flag = 0; - ptr->dag_node->color = 0; - ptr->dag_node->loaded = 0; - - assert(0 == scf_vector_del(rptr->dag_nodes, ptr->dag_node)); - return 0; -#endif - return -1; -} - -static int _arm64_inst_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - assert(1 == c->dsts->size && 3 == c->srcs->size); - - scf_register_arm64_t* rbp = arm64_find_register("rbp"); - scf_register_arm64_t* rd = NULL; // result - scf_register_arm64_t* rap = NULL; // ap - scf_register_arm64_t* rptr = NULL; // ptr - scf_instruction_t* inst = NULL; - - scf_instruction_t* inst_jge = NULL; - scf_instruction_t* inst_jmp = NULL; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* ap = c->srcs->data[0]; - scf_3ac_operand_t* src = c->srcs->data[1]; - scf_3ac_operand_t* ptr = c->srcs->data[2]; - scf_variable_t* v = src->dag_node->var; - -#if 0 - scf_arm64_OpCode_t* inc = arm64_find_OpCode(SCF_ARM64_INC, 8, 8, SCF_ARM64_E); - scf_arm64_OpCode_t* add = arm64_find_OpCode(SCF_ARM64_ADD, 4, 8, SCF_ARM64_I2E); - scf_arm64_OpCode_t* sub = arm64_find_OpCode(SCF_ARM64_SUB, 4, 8, SCF_ARM64_I2E); - scf_arm64_OpCode_t* cmp = arm64_find_OpCode(SCF_ARM64_CMP, 4, 8, SCF_ARM64_I2E); - scf_arm64_OpCode_t* mov = arm64_find_OpCode(SCF_ARM64_MOV, 8, 8, SCF_ARM64_E2G); - scf_arm64_OpCode_t* jge = arm64_find_OpCode(SCF_ARM64_JGE, 4, 4, SCF_ARM64_I); - scf_arm64_OpCode_t* jmp = arm64_find_OpCode(SCF_ARM64_JMP, 4, 4, SCF_ARM64_I); - scf_arm64_OpCode_t* mov2 = NULL; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - ARM64_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); - ARM64_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); - - int is_float = scf_variable_float(v); - int size = arm64_variable_size(v); - - uint32_t nints = ARM64_ABI_NB; - uint32_t nfloats = ARM64_ABI_NB; - uint32_t offset = 0; - uint32_t incptr = 8; - - int idx_offset = 24; - int ptr_offset = 0; - - if (is_float) { - idx_offset = 32; - ptr_offset = 8; - } - - inst = arm64_make_inst_I2P(cmp, rap, idx_offset, (uint8_t*)&nints, 4); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst_jge = arm64_make_inst_I(jge, (uint8_t*)&offset, sizeof(offset)); - ARM64_INST_ADD_CHECK(c->instructions, inst_jge); - - - inst = arm64_make_inst_P2G(mov, rptr, rap, ptr_offset); - ARM64_INST_ADD_CHECK(c->instructions, inst); - offset += inst->len; - - inst = arm64_make_inst_I2P(sub, rap, ptr_offset, (uint8_t*)&incptr, 4); - ARM64_INST_ADD_CHECK(c->instructions, inst); - offset += inst->len; - - inst_jmp = arm64_make_inst_I(jmp, (uint8_t*)&offset, sizeof(offset)); - ARM64_INST_ADD_CHECK(c->instructions, inst_jmp); - offset += inst_jmp->len; - - uint8_t* p = (uint8_t*)&offset; - int i; - for (i = 0; i < 4; i++) - inst_jge->code[jge->nb_OpCodes + i] = p[i]; - - offset = 0; - inst = arm64_make_inst_P2G(mov, rptr, rap, 16); - ARM64_INST_ADD_CHECK(c->instructions, inst); - offset += inst->len; - - inst = arm64_make_inst_I2P(add, rap, 16, (uint8_t*)&incptr, 4); - ARM64_INST_ADD_CHECK(c->instructions, inst); - offset += inst->len; - - for (i = 0; i < 4; i++) - inst_jmp->code[jmp->nb_OpCodes + i] = p[i]; - - inst = arm64_make_inst_P(inc, rap, idx_offset, 8); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (is_float) { - if (4 == size) - mov2 = arm64_find_OpCode(SCF_ARM64_MOVSS, 4, 4, SCF_ARM64_E2G); - else if (8 == size) - mov2 = arm64_find_OpCode(SCF_ARM64_MOVSD, 8, 8, SCF_ARM64_E2G); - else - assert(0); - } else - mov2 = arm64_find_OpCode(SCF_ARM64_MOV, size, size, SCF_ARM64_E2G); - - inst = arm64_make_inst_P2G(mov2, rd, rptr, 0); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -#endif - return -1; -} - -static int _arm64_inst_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) { - scf_loge("\n"); - return -EINVAL; - } - - if (!c->srcs || c->srcs->size != 1) { - scf_loge("\n"); - return -EINVAL; - } - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst; - - if (!src || !src->dag_node) { - scf_loge("\n"); - return -EINVAL; - } - assert(dst->dag_node->var->nb_pointers > 0); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - int ret = arm64_select_reg(&rd, dst->dag_node, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - assert(dst->dag_node->color > 0); - - ret = arm64_overflow_reg2(rd, dst->dag_node, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - return arm64_make_inst_ADR2G(c, f, rd, src->dag_node->var); -} - -static int _arm64_inst_div_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rs0 = NULL; - scf_register_arm64_t* rs1 = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(s0->var)) { - - if (0 == s0->color) { - s0->color = -1; - s0->var->global_flag = 1; - - } else if (0 == s1->color) { - s1->color = -1; - s1->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x3 << 11); - opcode |= (rs1->id << 16) | (rs0->id << 5) | rd->id; - opcode |= ((8 == rd->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s1->color) { - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - - int ret = arm64_select_free_reg(&rs1, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs1, s1->var->data.u64, rs1->bytes); - if (ret < 0) - return ret; - - } else if (0 == s0->color) { - - if (!scf_variable_const_interger(s0->var)) { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - - int ret = arm64_select_free_reg(&rs0, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs0, s0->var->data.u64, rs0->bytes); - if (ret < 0) - return ret; - - } else { - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - } - - opcode = ((8 == rs0->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs1->id << 16) | (0x2 << 10) | (rs0->id << 5) | rd->id; - - if (scf_variable_signed(s0->var)) - opcode |= 0x3 << 10; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_mod_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rs0 = NULL; - scf_register_arm64_t* rs1 = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src0->dag_node->var)) { - - assert(scf_variable_float(src1->dag_node->var)); - assert(scf_variable_float(dst->dag_node->var)); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s1->color) { - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - - int ret = arm64_select_free_reg(&rs1, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs1, s1->var->data.u64, rs1->bytes); - if (ret < 0) - return ret; - - } else if (0 == s0->color) { - - if (!scf_variable_const_interger(s0->var)) { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - - int ret = arm64_select_free_reg(&rs0, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs0, s0->var->data.u64, rs0->bytes); - if (ret < 0) - return ret; - - } else { - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - } - - opcode = ((8 == rs0->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs1->id << 16) | (0x2 << 10) | (rs0->id << 5) | rd->id; - - if (scf_variable_signed(s0->var)) - opcode |= 0x3 << 10; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = ((8 == rs0->bytes) << 31) | (0x1b << 24) | (rs1->id << 16) | (0x1 << 15) | (rs0->id << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_mul_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rm = NULL; - scf_register_arm64_t* rn = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (0 == s0->color) - SCF_XCHG(s0, s1); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(s0->var)) { - - if (0 == s0->color) { - s0->color = -1; - s0->var->global_flag = 1; - - } else if (0 == s1->color) { - s1->color = -1; - s1->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 11); - opcode |= (rm->id << 16) | (rn->id << 5) | rd->id; - opcode |= ((8 == rd->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - - if (0 == s1->color) { - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - s1->color = -1; - s1->var->tmp_flag = 1; - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x9b << 24) | (rm->id << 16) | (0x1f << 10) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - s1->color = 0; - s1->loaded = 0; - s1->var->tmp_flag = 0; - assert(0 == scf_vector_del(rm->dag_nodes, s1)); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x9b << 24) | (rm->id << 16) | (0x1f << 10) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_mul_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (src->dag_node->var->size != dst->dag_node->var->size) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(s->var)) { - - if (0 == s->color) { - s->color = -1; - s->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 11); - opcode |= (rs->id << 16) | (rd->id << 5) | rd->id; - opcode |= ((8 == rd->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - - if (!scf_variable_const_interger(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - s->color = -1; - s->var->tmp_flag = 1; - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0x9b << 24) | (rs->id << 16) | (0x1f << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - s->color = 0; - s->loaded = 0; - s->var->tmp_flag = 0; - assert(0 == scf_vector_del(rs->dag_nodes, s)); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0x9b << 24) | (rs->id << 16) | (0x1f << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_add_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rm = NULL; - scf_register_arm64_t* rn = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (0 == s0->color) - SCF_XCHG(s0, s1); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src0->dag_node->var)) { - - if (0 == s1->color) { - s1->color = -1; - s1->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 13) | (0x1 << 11); - opcode |= (rm->id << 16) | (rn->id << 5) | rd->id; - opcode |= (8 == rd->bytes) << 22; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - if (0 == s1->color) { - - if (scf_variable_const_string(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - uint64_t u = s1->var->data.u64; - - uint32_t sh = 0; - uint32_t imm = 0; - - if (u <= 0xfff) - imm = u; - - else if (0 == (u & 0xfff) && (u >> 12) <= 0xfff) { - sh = 1; - imm = u >> 12; - - } else { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - - opcode = (0x91 << 24) | (sh << 22) | (imm << 10) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x8b << 24) | (rm->id << 16) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_add_sub_assign(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24i, uint32_t u24r) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (src->dag_node->var->size != dst->dag_node->var->size) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(s->var)) { - - if (0 == s->color) { - s->color = -1; - s->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - uint32_t op; - - if (0x11 == u24i) - op = 0x5; - - else if (0x51 == u24i) - op = 0x7; - else - return -EINVAL; - - opcode = (0x1e << 24) | (0x1 << 21) | (op << 11); - opcode |= (rs->id << 16) | (rd->id << 5) | rd->id; - opcode |= (8 == rd->bytes) << 22; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - if (0 == s->color) { - - if (scf_variable_const_string(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - if (!scf_variable_const_interger(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - uint64_t u = s->var->data.u64; - - uint32_t sh = 0; - uint32_t imm = 0; - - if (u <= 0xfff) - imm = u; - - else if (0 == (u & 0xfff) && (u >> 12) <= 0xfff) { - sh = 1; - imm = u >> 12; - - } else { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - opcode = ((8 == rd->bytes) << 31) | (u24i << 24) | (sh << 22) | (imm << 10) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = ((8 == rd->bytes) << 31) | (u24r << 24) | (rs->id << 16) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_add_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_add_sub_assign(ctx, c, 0x11, 0x0b); -} - -static int _arm64_inst_sub_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_add_sub_assign(ctx, c, 0x51, 0x4b); -} - -static int _arm64_inst_sub_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rm = NULL; - scf_register_arm64_t* rn = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src0->dag_node->var)) { - - if (0 == s0->color) { - s0->color = -1; - s0->var->global_flag = 1; - - } else if (0 == s1->color) { - s1->color = -1; - s1->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x7 << 11); - opcode |= (rm->id << 16) | (rn->id << 5) | rd->id; - opcode |= ((8 == rd->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - int neg = 0; - - if (0 == s0->color) { - neg = 1; - SCF_XCHG(s0, s1); - } - - if (0 == s1->color) { - - if (scf_variable_const_string(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - uint64_t u = s1->var->data.u64; - - uint32_t sh = 0; - uint32_t imm = 0; - - if (u <= 0xfff) - imm = u; - - else if (0 == (u & 0xfff) && (u >> 12) <= 0xfff) { - sh = 1; - imm = u >> 12; - - } else { - scf_loge("\n"); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - - opcode = ((8 == rn->bytes) << 31) | (0x51 << 24) | (sh << 22) | (imm << 10) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (neg) { - opcode = ((8 == rd->bytes) << 31) | (0x4b << 24) | (rd->id << 16) | (0x1f << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, s0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = ((8 == rn->bytes) << 31) | (0x4b << 24) | (rm->id << 16) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -int arm64_inst_bit_op(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) -{ - ARM64_INST_OP3_CHECK() - - scf_register_arm64_t* rm = NULL; - scf_register_arm64_t* rn = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - assert(0 != s0->color || 0 != s1->color); - - if (0 == s0->color) - SCF_XCHG(s0, s1); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src0->dag_node->var)) { - - assert(scf_variable_float(src1->dag_node->var)); - assert(scf_variable_float(dst->dag_node->var)); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rn, d, c, f, 1); - - if (0 == s1->color) { - - if (!scf_variable_const_interger(s1->var)) { - scf_loge("\n"); - return -EINVAL; - } - - s1->color = -1; - s1->var->tmp_flag = 1; - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (op << 24) | (rm->id << 16) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - s1->color = 0; - s1->loaded = 0; - s1->var->tmp_flag = 0; - assert(0 == scf_vector_del(rm->dag_nodes, s1)); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rm, s1, c, f, 1); - - opcode = (op << 24) | (rm->id << 16) | (rn->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -int arm64_inst_bit_op_assign(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (src->dag_node->var->size != dst->dag_node->var->size) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src->dag_node->var)) { - - assert(scf_variable_float(dst->dag_node->var)); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - - if (!scf_variable_const_interger(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - s->color = -1; - s->var->tmp_flag = 1; - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (op << 24) | (rs->id << 16) | (rd->id << 5) | rd->id; - ARM64_INST_ADD_CHECK(c->instructions, inst); - - s->color = 0; - s->loaded = 0; - s->var->tmp_flag = 0; - assert(0 == scf_vector_del(rs->dag_nodes, s)); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (op << 24) | (rs->id << 16) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_bit_and_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return arm64_inst_bit_op(ctx, c, 0x8a); -} - -static int _arm64_inst_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return arm64_inst_bit_op(ctx, c, 0xaa); -} - -static int _arm64_inst_and_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return arm64_inst_bit_op_assign(ctx, c, 0x8a); -} - -static int _arm64_inst_or_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return arm64_inst_bit_op_assign(ctx, c, 0xaa); -} - -static int _arm64_inst_teq_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rs; - scf_instruction_t* inst; - - uint32_t opcode; - - if (0 == src->dag_node->color) { - scf_loge("src->dag_node->var: %p\n", src->dag_node->var); - return -1; - } - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - opcode = ((8 == rs->bytes) << 1) | (0x6a << 24) | (rs->id << 16) | (rs->id << 5) | 0x1f; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_set(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t cc) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rd; - scf_instruction_t* inst; - - uint32_t opcode; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_logic_not_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - int ret = _arm64_inst_teq_handler(ctx, c); - if (ret < 0) - return ret; - - return _arm64_inst_set(ctx, c, 0x1); -} - -static int _arm64_inst_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* s0 = c->srcs->data[0]; - scf_3ac_operand_t* s1 = c->srcs->data[1]; - - if (!s0 || !s0->dag_node) - return -EINVAL; - - if (!s1 || !s1->dag_node) - return -EINVAL; - - scf_instruction_t* inst; - scf_register_arm64_t* rs1 = NULL; - scf_register_arm64_t* rs0 = NULL; - scf_dag_node_t* ds0 = s0->dag_node; - scf_dag_node_t* ds1 = s1->dag_node; - scf_rela_t* rela = NULL; - - uint32_t opcode; - - if (ds0->var->size != ds1->var->size) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (0 == ds0->color) { - scf_loge("src0 should be a var\n"); - if (ds0->var->w) - scf_loge("src0: '%s'\n", ds0->var->w->text->data); - else - scf_loge("src0: v_%#lx\n", 0xffff & (uintptr_t)ds0->var); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rs0, ds0, c, f, 1); - - if (scf_variable_float(ds0->var)) { - - if (0 == ds1->color) { - ds1->color = -1; - ds1->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rs0, ds0, c, f, 1); - ARM64_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 13); - opcode |= (rs1->id << 16) | (rs0->id << 5); - opcode |= ((8 == rs0->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - if (0 == ds1->color) { - - uint64_t u = ds1->var->data.u64; - - if (u <= 0xfff) - opcode = (0x71 << 24) | (u << 10) | (rs0->id << 5) | 0x1f; - - else if (0 == (u & 0xfff) && (u >> 12) <= 0xfff) - opcode = (0x71 << 24) | (1 << 22) | (u << 10) | (rs0->id << 5) | 0x1f; - - else { - ds1->loaded = 0; - ds1->color = -1; - ARM64_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); - - opcode = (0x6b << 24) | (rs1->id << 16) | (rs0->id << 5) | 0x1f; - - ds1->loaded = 0; - ds1->color = 0; - assert(0 == scf_vector_del(rs1->dag_nodes, ds1)); - } - - if (rs0->bytes > 4) - opcode |= (0x1 << 31); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); - - opcode = (0x6b << 24) | (rs1->id << 16) | (rs0->id << 5) | 0x1f; - - if (rs0->bytes > 4) - opcode |= (0x1 << 31); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -#define ARM64_INST_SET(name, cc) \ -static int _arm64_inst_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c) \ -{ \ - return _arm64_inst_set(ctx, c, cc); \ -} -ARM64_INST_SET(setz, 0x1) -ARM64_INST_SET(setnz, 0x0) -ARM64_INST_SET(setgt, 0xd) -ARM64_INST_SET(setge, 0xb) -ARM64_INST_SET(setlt, 0xa) -ARM64_INST_SET(setle, 0xc) - -#define ARM64_INST_CMP_SET(name, cc) \ -static int _arm64_inst_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c) \ -{ \ - int ret = _arm64_inst_cmp_handler(ctx, c); \ - if (ret < 0) \ - return ret; \ - return _arm64_inst_set(ctx, c, cc); \ -} -ARM64_INST_CMP_SET(eq, 0x1) -ARM64_INST_CMP_SET(ne, 0x0) -ARM64_INST_CMP_SET(gt, 0xd) -ARM64_INST_CMP_SET(ge, 0xb) -ARM64_INST_CMP_SET(lt, 0xa) -ARM64_INST_CMP_SET(le, 0xc) - -static int _arm64_inst_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_instruction_t* inst; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (0 == dst->dag_node->color) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - scf_variable_t* vs = s->var; - scf_variable_t* vd = d->var; - - int src_size = arm64_variable_size(vs); - int dst_size = arm64_variable_size(vd); - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - uint32_t opcode = 0; - - if (scf_variable_float(vs)) { - - if (0 == s->color) { - s->color = -1; - vs->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - if (scf_variable_float(vd)) { - - if (rd->bytes == rs->bytes) - opcode = (0x1e << 24) | ((8 == rd->bytes) << 22) | (0x1 << 21) | (0x1 << 14) | (rs->id << 5) | rd->id; - - else if (4 == rs->bytes) - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (0x1 << 15) | (0x1 << 14) | (rs->id << 5) | rd->id; - else - opcode = (0x1e << 24) | (0x1 << 22) | (0x1 << 21) | (0x1 << 17) | (0x1 << 14) | (rs->id << 5) | rd->id; - - } else { - opcode = ((8 == rd->bytes) << 31) | (0x1e << 24) | ((8 == rs->bytes) << 22) | (0x7 << 19) | (rs->id << 5) | rd->id; - - opcode |= (!scf_variable_signed(vd)) << 16; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - - } else if (scf_variable_float(vd)) { - - if (0 == s->color) { - - if (!scf_variable_const_interger(vs)) - return -EINVAL; - - if (src_size < dst_size) - scf_variable_extend_bytes(vs, 8); - - int ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, vs->data.u64, dst_size); - if (ret < 0) - return ret; - - } else - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (rs->id << 5) | rd->id; - - opcode |= ((8 == rs->bytes) << 31) | ((8 == rd->bytes) << 22); - - opcode |= (!scf_variable_signed(vd)) << 16; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - if (vs->nb_dimentions > 0) - return arm64_make_inst_ADR2G(c, f, rd, vs); - - scf_logw("src_size: %d, dst_size: %d\n", src_size, dst_size); - - if (0 == s->color) { - - if (!scf_variable_const_interger(vs)) - return -EINVAL; - - if (src_size < dst_size) - scf_variable_extend_bytes(vs, 8); - - return arm64_make_inst_I2G(c, rd, vs->data.u64, dst_size); - } - - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - if (src_size < dst_size) { - - if (scf_variable_signed(vs)) { - - opcode = (0x93 << 24) | (0x1 << 22) | (rs->id << 5) | rd->id; - - if (1 == src_size) - opcode |= 0x7 << 10; - - else if (2 == src_size) - opcode |= 0xf << 10; - - else if (4 == src_size) - opcode |= 0x1f << 10; - - } else { - opcode = (0x53 << 24) | (rs->id << 5) | rd->id; - - if (1 == src_size) - opcode |= 0x7 << 10; - - else if (2 == src_size) - opcode |= 0xf << 10; - } - } - - if (0 == opcode) - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_div_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (src->dag_node->var->size != dst->dag_node->var->size) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(s->var)) { - - if (0 == s->color) { - s->color = -1; - s->var->global_flag = 1; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0x1e << 24) | (0x1 << 21) | (0x3 << 11); - opcode |= (rs->id << 16) | (rd->id << 5) | rd->id; - opcode |= ((8 == rd->bytes) << 22); - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - - if (!scf_variable_const_interger(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - int ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, s->var->data.u64, rs->bytes); - if (ret < 0) - return ret; - - } else - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = ((8 == rd->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs->id << 16) | (0x2 << 10) | (rd->id << 5) | rd->id; - - if (scf_variable_signed(s->var)) - opcode |= 0x3 << 10; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (src->dag_node->var->size != dst->dag_node->var->size) - return -EINVAL; - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* r = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - assert(0 != d->color); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - if (scf_variable_float(src->dag_node->var)) { - - assert(scf_variable_float(dst->dag_node->var)); - return -EINVAL; - } - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - - if (!scf_variable_const_interger(s->var)) { - scf_loge("\n"); - return -EINVAL; - } - - int ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, s->var->data.u64, rs->bytes); - if (ret < 0) - return ret; - - } else - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - int ret = arm64_select_free_reg(&r, c, f, 0); - if (ret < 0) - return ret; - - opcode = ((8 == rd->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs->id << 16) | (0x2 << 10) | (rd->id << 5) | r->id; - - if (scf_variable_signed(s->var)) - opcode |= 0x3 << 10; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = ((8 == rd->bytes) << 31) | (0x1b << 24) | (rs->id << 16) | (0x1 << 15) | (rd->id << 10) | (r->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size < 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = NULL; - scf_variable_t* v = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - scf_register_arm64_t* rd = NULL; - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* sp = arm64_find_register("sp"); - scf_register_arm64_t* fp = arm64_find_register("fp"); - - scf_arm64_OpCode_t* pop; - scf_arm64_OpCode_t* mov; - scf_arm64_OpCode_t* ret; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - int i; - for (i = 0; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - - v = src->dag_node->var; - - int size = arm64_variable_size(v); - int is_float = scf_variable_float(v); - - if (i > 0 && is_float) { - scf_loge("\n"); - return -1; - } - - int retsize = size > 4 ? 8 : 4; - - if (is_float) { - rd = arm64_find_register_type_id_bytes(is_float, 0, retsize); - - if (0 == src->dag_node->color) { - src->dag_node->color = -1; - v->global_flag = 1; - } - - scf_loge("\n"); - return -1; - - } else { - rd = arm64_find_register_type_id_bytes(is_float, arm64_abi_ret_regs[i], retsize); - - if (0 == src->dag_node->color) { - if (rd->bytes > size) - scf_variable_extend_bytes(v, rd->bytes); - - int ret = arm64_make_inst_I2G(c, rd, v->data.u64, rd->bytes); - if (ret < 0) - return ret; - continue; - } - } - - scf_logd("rd: %s, rd->dag_nodes->size: %d\n", rd->name, rd->dag_nodes->size); - - if (src->dag_node->color > 0) { - - int start = c->instructions->size; - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - if (!ARM64_COLOR_CONFLICT(rd->color, rs->color)) { - - int ret = arm64_save_reg(rd, c, f); - if (ret < 0) - return ret; - - uint32_t opcode; - - if (rd->bytes > size) { - - if (scf_variable_signed(v)) { - - if (1 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0x7 << 10) | (rs->id << 5) | rd->id; - - else if (2 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0xf << 10) | (rs->id << 5) | rd->id; - - else if (4 == size) - opcode = (0x93 << 24) | (0x1 << 22) | (0x1f << 10) | (rs->id << 5) | rd->id; - - else { - scf_loge("\n"); - return -EINVAL; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - } else { - if (1 == size) - opcode = (0x53 << 24) | (0x7 << 10) | (rs->id << 5) | rd->id; - - else if (2 == size) - opcode = (0x53 << 24) | (0xf << 10) | (rs->id << 5) | rd->id; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - } else { - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - scf_instruction_t* tmp; - int j; - int k; - for (j = start; j < c->instructions->size; j++) { - tmp = c->instructions->data[j]; - - for (k = j - 1; k >= j - start; k--) - c->instructions->data[k + 1] = c->instructions->data[k]; - - c->instructions->data[j - start] = tmp; - } - } - } else { - int ret = arm64_save_reg(rd, c, f); - if (ret < 0) - return ret; - - ret = arm64_make_inst_M2G(c, f, rd, NULL, v); - if (ret < 0) - return ret; - } - } - return 0; -} - -static int _arm64_inst_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* dst = c->srcs->data[0]; - scf_3ac_operand_t* data = c->srcs->data[1]; - scf_3ac_operand_t* count = c->srcs->data[2]; - scf_instruction_t* inst = NULL; - - scf_register_arm64_t* rax = arm64_find_register("rax"); - scf_register_arm64_t* rcx = arm64_find_register("rcx"); - scf_register_arm64_t* rdi = arm64_find_register("rdi"); - scf_register_arm64_t* rd; - scf_arm64_OpCode_t* mov; - scf_arm64_OpCode_t* stos; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - int ret = arm64_overflow_reg2(rdi, dst->dag_node, c, f); - if (ret < 0) - return ret; - - ret = arm64_overflow_reg2(rax, data->dag_node, c, f); - if (ret < 0) - return ret; - - ret = arm64_overflow_reg2(rcx, count->dag_node, c, f); - if (ret < 0) - return ret; - -#if 0 -#define ARM64_MEMSET_LOAD_REG(r, dn) \ - do { \ - int size = arm64_variable_size(dn->var); \ - assert(8 == size); \ - \ - if (0 == dn->color) { \ - mov = arm64_find_OpCode(SCF_ARM64_MOV, size, size, SCF_ARM64_I2G); \ - inst = arm64_make_inst_I2G(mov, r, (uint8_t*)&dn->var->data, size); \ - ARM64_INST_ADD_CHECK(c->instructions, inst); \ - \ - } else { \ - if (dn->color < 0) \ - dn->color = r->color; \ - ARM64_SELECT_REG_CHECK(&rd, dn, c, f, 1); \ - \ - if (!ARM64_COLOR_CONFLICT(rd->color, r->color)) { \ - mov = arm64_find_OpCode(SCF_ARM64_MOV, size, size, SCF_ARM64_G2E); \ - inst = arm64_make_inst_G2E(mov, r, rd); \ - ARM64_INST_ADD_CHECK(c->instructions, inst); \ - } \ - } \ - } while (0) - ARM64_MEMSET_LOAD_REG(rdi, dst ->dag_node); - ARM64_MEMSET_LOAD_REG(rax, data ->dag_node); - ARM64_MEMSET_LOAD_REG(rcx, count->dag_node); - - stos = arm64_find_OpCode(SCF_ARM64_STOS, 1, 8, SCF_ARM64_G); - inst = arm64_make_inst(stos, 1); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -#endif - return -1; -} - -static int _arm64_inst_nop_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return 0; -} - -static int _arm64_inst_end_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* sp = arm64_find_register("sp"); - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_register_arm64_t* r; - - uint32_t sp_fp = 0x910003bf; - uint32_t ret = 0xd65f03c0; - - scf_instruction_t* inst = NULL; - - int i; - for (i = ARM64_ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) { - - r = arm64_find_register_type_id_bytes(0, arm64_abi_callee_saves[i], 8); - - if (!r->used) { - r = arm64_find_register_type_id_bytes(0, arm64_abi_callee_saves[i], 4); - - if (!r->used) - continue; - } - - uint32_t pop = (0xf8 << 24) | (0x1 << 22) | (0x8 << 12) | (0x1 << 10) | (0x1f << 5) | r->id; - - inst = arm64_make_inst(c, pop); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - inst = arm64_make_inst(c, sp_fp); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - uint32_t pop = (0xf8 << 24) | (0x1 << 22) | (0x8 << 12) | (0x1 << 10) | (0x1f << 5) | fp->id; - inst = arm64_make_inst(c, pop); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - inst = arm64_make_inst(c, ret); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -#define ARM64_INST_JMP(name, opcode) \ -static int _arm64_inst_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c) \ -{ \ - if (!c->dsts || c->dsts->size != 1) \ - return -EINVAL; \ - \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - scf_instruction_t* inst = NULL; \ - \ - if (!dst->bb) \ - return -EINVAL; \ - \ - if (0 == opcode) \ - return -EINVAL; \ - \ - if (!c->instructions) { \ - c->instructions = scf_vector_alloc(); \ - if (!c->instructions) \ - return -ENOMEM; \ - } \ - \ - inst = arm64_make_inst(c, opcode); \ - ARM64_INST_ADD_CHECK(c->instructions, inst); \ - return 0;\ -} - -ARM64_INST_JMP(goto, 0x14000000) -ARM64_INST_JMP(jz, 0x54000000) -ARM64_INST_JMP(jnz, 0x54000001) -ARM64_INST_JMP(jgt, 0x5400000c) -ARM64_INST_JMP(jge, 0x5400000a) -ARM64_INST_JMP(jlt, 0x5400000b) -ARM64_INST_JMP(jle, 0x5400000d) - -ARM64_INST_JMP(ja, 0) -ARM64_INST_JMP(jb, 0) -ARM64_INST_JMP(jae, 0) -ARM64_INST_JMP(jbe, 0) - -static int _arm64_inst_load_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* r = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_dag_node_t* dn = dst->dag_node; - - int ret; - int i; - - if (dn->color < 0) - return 0; - - scf_variable_t* v = dn->var; - - assert(dn->color > 0); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - r = arm64_find_register_color(dn->color); - - if (arm64_reg_used(r, dn)) { - dn->color = -1; - dn->loaded = 0; - scf_vector_del(r->dag_nodes, dn); - return 0; - } - - ret = arm64_load_reg(r, dn, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = scf_vector_add_unique(r->dag_nodes, dn); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - return 0; -} - -static int _arm64_inst_reload_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* r = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_dag_node_t* dn = dst->dag_node; - scf_dag_node_t* dn2 = NULL; - - int ret; - int i; - - if (dn->color < 0) - return 0; - assert(dn->color > 0); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - r = arm64_find_register_color(dn->color); - - ret = arm64_overflow_reg2(r, dn, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - dn->loaded = 0; - ret = arm64_load_reg(r, dn, c, f); - if (ret < 0) - return ret; - - ret = scf_vector_add_unique(r->dag_nodes, dn); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - return 0; -} - -static int _arm64_inst_save_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_dag_node_t* dn = src->dag_node; - - if (dn->color < 0) - return 0; - - if (!dn->loaded) - return 0; - - scf_variable_t* v = dn->var; - assert(dn->color > 0); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - return arm64_save_var(dn, c, f); -} - -static int _arm64_inst_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - scf_variable_t* v = s->var; - - uint32_t opcode; - - assert(0 != d->color); - - int size = arm64_variable_size(v); - int is_float = scf_variable_float(v); - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (is_float) { - assert(scf_variable_float(v)); - - if (0 == s->color) { - s->color = -1; - v->global_flag = 1; - return arm64_make_inst_M2GF(c, f, rd, NULL, v); - } - - ARM64_SELECT_REG_CHECK(&rs, d, c, f, 1); - - opcode = (0x1e << 24) | ((8 == rd->bytes) << 22) | (0x1 << 21) | (rs->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } - - if (0 == s->color) { - - if (scf_variable_const_string(v)) - return arm64_make_inst_ISTR2G(c, f, rd, v); - - if (!scf_variable_const_interger(v)) { - scf_loge("\n"); - return -EINVAL; - } - - if (rd->bytes > size) - scf_variable_extend_bytes(v, rd->bytes); - - return arm64_make_inst_I2G(c, rd, v->data.u64, rd->bytes); - } - - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_shift(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src0 = c->srcs->data[0]; - scf_3ac_operand_t* src1 = c->srcs->data[1]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src0 || !src0->dag_node) - return -EINVAL; - - if (!src1 || !src1->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rs0 = NULL; - scf_register_arm64_t* rs1 = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst ->dag_node; - scf_dag_node_t* s0 = src0->dag_node; - scf_dag_node_t* s1 = src1->dag_node; - - uint32_t opcode; - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s0->color) { - - if (scf_variable_signed(s0->var)) - scf_variable_sign_extend(s0->var, 8); - else - scf_variable_zero_extend(s0->var, 8); - - int ret = arm64_make_inst_I2G(c, rd, s0->var->data.u64, rd->bytes); - if (ret < 0) - return ret; - - rs0 = rd; - } else - ARM64_SELECT_REG_CHECK(&rs0, s0, c, f, 1); - - if (0 == s1->color) { - - int ret = arm64_select_free_reg(&rs1, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs1, s1->var->data.u64, 1); - if (ret < 0) - return ret; - } else - ARM64_SELECT_REG_CHECK(&rs1, s1, c, f, 1); - - uint32_t op = (0x9a << 24) | (0x3 << 22) | (0x1 << 13); - - if (SCF_OP_SHR == c->op->type) { - if (scf_variable_signed(s0->var)) - op |= 0x1 << 11; - else - op |= 0x1 << 10; - } - - opcode = op | (rs1->id << 16) | (rs0->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_shift_assign(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_dag_node_t* d = dst->dag_node; - scf_dag_node_t* s = src->dag_node; - - uint32_t opcode; - - ARM64_SELECT_REG_CHECK(&rd, d, c, f, 0); - - if (0 == s->color) { - - int ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, s->var->data.u64, 1); - if (ret < 0) - return ret; - } else - ARM64_SELECT_REG_CHECK(&rs, s, c, f, 1); - - uint32_t op = (0x9a << 24) | (0x3 << 22) | (0x1 << 13); - - if (SCF_OP_SHR == c->op->type) { - if (scf_variable_signed(s->var)) - op |= 0x1 << 11; - else - op |= 0x1 << 10; - } - - opcode = op | (rs->id << 16) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_shl_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_shift(ctx, c); -} - -static int _arm64_inst_shr_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_shift(ctx, c); -} - -static int _arm64_inst_shl_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_shift_assign(ctx, c); -} - -static int _arm64_inst_shr_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_shift_assign(ctx, c); -} - -static int _arm64_inst_binary_assign_dereference(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) -{ - if (!c->srcs || c->srcs->size != 2) - return -EINVAL; - - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* src = c->srcs->data[1]; - scf_instruction_t* inst; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_variable_t* vs = src ->dag_node->var; - scf_variable_t* vb = base->dag_node->var; - - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - arm64_sib_t sib = {0}; - - int ret = arm64_dereference_reg(&sib, base->dag_node, NULL, c, f); - if (ret < 0) - return ret; - - int is_float = scf_variable_float(vs); - - if (0 == src->dag_node->color) { - - if (is_float) { - - src->dag_node->color = -1; - vs->global_flag = 1; - - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - } else { - ret = arm64_select_free_reg(&rs, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rs, vs->data.u64, sib.size); - if (ret < 0) - return ret; - - rs = arm64_find_register_color_bytes(rs->color, sib.size); - } - } else - ARM64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - - if (op) { - uint32_t opcode; - - ret = arm64_select_free_reg(&rd, c, f, is_float); - if (ret < 0) - return ret; - - ret = arm64_make_inst_P2G(c, f, rd, sib.base, sib.disp, sib.size); - if (ret < 0) - return ret; - - opcode = ((8 == sib.size) << 31)| op | (rs->id << 16) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - rs = rd; - } - - return arm64_make_inst_G2P(c, f, rs, sib.base, sib.disp, sib.size); -} - -static int _arm64_inst_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_dereference(ctx, c, 0); -} - -static int _arm64_inst_add_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_dereference(ctx, c, 0x0b << 24); -} - -static int _arm64_inst_sub_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_dereference(ctx, c, 0x4b << 24); -} - -static int _arm64_inst_and_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_dereference(ctx, c, 0x0a << 24); -} - -static int _arm64_inst_or_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_dereference(ctx, c, 0x2a << 24); -} - -static int _arm64_inst_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_pointer(ctx, c, 0); -} - -static int _arm64_inst_add_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_pointer(ctx, c, 0x0b << 24); -} - -static int _arm64_inst_sub_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_pointer(ctx, c, 0x4b << 24); -} - -static int _arm64_inst_and_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_pointer(ctx, c, 0x0a << 24); -} - -static int _arm64_inst_or_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_pointer(ctx, c, 0x2a << 24); -} - -static int _arm64_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_array_index(ctx, c, 0); -} - -static int _arm64_inst_add_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_array_index(ctx, c, 0x0b << 24); -} - -static int _arm64_inst_sub_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_array_index(ctx, c, 0x4b << 24); -} - -static int _arm64_inst_and_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_array_index(ctx, c, 0x0a << 24); -} - -static int _arm64_inst_or_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inst_binary_assign_array_index(ctx, c, 0x2a << 24); -} - -static int _arm64_inc_dec_dereference(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->srcs || c->srcs->size != 1) { - scf_loge("\n"); - return -EINVAL; - } - - scf_register_arm64_t* r = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_instruction_t* inst; - scf_function_t* f = arm64->f; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - arm64_sib_t sib = {0}; - - int size = base->dag_node->var->data_size; - - int ret = arm64_dereference_reg(&sib, base->dag_node, NULL, c, f); - if (ret < 0) - return ret; - - ret = arm64_select_free_reg(&r, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_P2G(c, f, r, sib.base, 0, size); - if (ret < 0) - return ret; - - uint32_t opcode = (u24 << 24) | (0x1 << 10) | (r->id << 5) | r->id; - - if (size > 4) - opcode |= 0x1 << 31; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return arm64_make_inst_G2P(c, f, r, sib.base, 0, size); -} - -static int _arm64_inc_dec_post_dereference(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_register_arm64_t* rd = NULL; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* base = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_instruction_t* inst; - scf_function_t* f = arm64->f; - - if (!base || !base->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - arm64_sib_t sib = {0}; - - int size = base->dag_node->var->data_size; - - int ret = arm64_dereference_reg(&sib, base->dag_node, NULL, c, f); - if (ret < 0) - return ret; - - ARM64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - ret = arm64_make_inst_P2G(c, f, rd, sib.base, 0, size); - if (ret < 0) - return ret; - - uint32_t opcode = (u24 << 24) | (0x1 << 10) | (rd->id << 5) | rd->id; - - if (size > 4) - opcode |= 0x1 << 31; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - ret = arm64_make_inst_G2P(c, f, rd, sib.base, 0, size); - if (ret < 0) - return ret; - - opcode &= ~(0x1 << 30); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -static int _arm64_inst_dec_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inc_dec_dereference(ctx, c, 0x51); -} - -static int _arm64_inst_inc_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inc_dec_dereference(ctx, c, 0x11); -} - -static int _arm64_inst_dec_post_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inc_dec_post_dereference(ctx, c, 0x51); -} - -static int _arm64_inst_inc_post_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _arm64_inc_dec_post_dereference(ctx, c, 0x11); -} - -static arm64_inst_handler_t arm64_inst_handlers[] = { - - {SCF_OP_CALL, _arm64_inst_call_handler}, - {SCF_OP_ARRAY_INDEX, _arm64_inst_array_index_handler}, - {SCF_OP_POINTER, _arm64_inst_pointer_handler}, - - {SCF_OP_TYPE_CAST, _arm64_inst_cast_handler}, - {SCF_OP_LOGIC_NOT, _arm64_inst_logic_not_handler}, - {SCF_OP_BIT_NOT, _arm64_inst_bit_not_handler}, - {SCF_OP_NEG, _arm64_inst_neg_handler}, - - {SCF_OP_VA_START, _arm64_inst_va_start_handler}, - {SCF_OP_VA_ARG, _arm64_inst_va_arg_handler}, - {SCF_OP_VA_END, _arm64_inst_va_end_handler}, - - {SCF_OP_INC, _arm64_inst_inc_handler}, - {SCF_OP_DEC, _arm64_inst_dec_handler}, - - {SCF_OP_INC_POST, _arm64_inst_inc_post_handler}, - {SCF_OP_DEC_POST, _arm64_inst_dec_post_handler}, - - {SCF_OP_DEREFERENCE, _arm64_inst_dereference_handler}, - {SCF_OP_ADDRESS_OF, _arm64_inst_address_of_handler}, - - {SCF_OP_MUL, _arm64_inst_mul_handler}, - {SCF_OP_DIV, _arm64_inst_div_handler}, - {SCF_OP_MOD, _arm64_inst_mod_handler}, - - {SCF_OP_ADD, _arm64_inst_add_handler}, - {SCF_OP_SUB, _arm64_inst_sub_handler}, - - {SCF_OP_SHL, _arm64_inst_shl_handler}, - {SCF_OP_SHR, _arm64_inst_shr_handler}, - - {SCF_OP_BIT_AND, _arm64_inst_bit_and_handler}, - {SCF_OP_BIT_OR, _arm64_inst_bit_or_handler}, - - {SCF_OP_3AC_TEQ, _arm64_inst_teq_handler}, - {SCF_OP_3AC_CMP, _arm64_inst_cmp_handler}, - - {SCF_OP_3AC_SETZ, _arm64_inst_setz_handler}, - {SCF_OP_3AC_SETNZ, _arm64_inst_setnz_handler}, - {SCF_OP_3AC_SETGT, _arm64_inst_setgt_handler}, - {SCF_OP_3AC_SETGE, _arm64_inst_setge_handler}, - {SCF_OP_3AC_SETLT, _arm64_inst_setlt_handler}, - {SCF_OP_3AC_SETLE, _arm64_inst_setle_handler}, - - {SCF_OP_EQ, _arm64_inst_eq_handler}, - {SCF_OP_NE, _arm64_inst_ne_handler}, - {SCF_OP_GT, _arm64_inst_gt_handler}, - {SCF_OP_GE, _arm64_inst_ge_handler}, - {SCF_OP_LT, _arm64_inst_lt_handler}, - {SCF_OP_LE, _arm64_inst_le_handler}, - - {SCF_OP_ASSIGN, _arm64_inst_assign_handler}, - - {SCF_OP_ADD_ASSIGN, _arm64_inst_add_assign_handler}, - {SCF_OP_SUB_ASSIGN, _arm64_inst_sub_assign_handler}, - - {SCF_OP_MUL_ASSIGN, _arm64_inst_mul_assign_handler}, - {SCF_OP_DIV_ASSIGN, _arm64_inst_div_assign_handler}, - {SCF_OP_MOD_ASSIGN, _arm64_inst_mod_assign_handler}, - - {SCF_OP_SHL_ASSIGN, _arm64_inst_shl_assign_handler}, - {SCF_OP_SHR_ASSIGN, _arm64_inst_shr_assign_handler}, - - {SCF_OP_AND_ASSIGN, _arm64_inst_and_assign_handler}, - {SCF_OP_OR_ASSIGN, _arm64_inst_or_assign_handler}, - - {SCF_OP_RETURN, _arm64_inst_return_handler}, - {SCF_OP_GOTO, _arm64_inst_goto_handler}, - - {SCF_OP_3AC_JZ, _arm64_inst_jz_handler}, - {SCF_OP_3AC_JNZ, _arm64_inst_jnz_handler}, - {SCF_OP_3AC_JGT, _arm64_inst_jgt_handler}, - {SCF_OP_3AC_JGE, _arm64_inst_jge_handler}, - {SCF_OP_3AC_JLT, _arm64_inst_jlt_handler}, - {SCF_OP_3AC_JLE, _arm64_inst_jle_handler}, - - {SCF_OP_3AC_JA, _arm64_inst_ja_handler}, - {SCF_OP_3AC_JB, _arm64_inst_jb_handler}, - {SCF_OP_3AC_JAE, _arm64_inst_jae_handler}, - {SCF_OP_3AC_JBE, _arm64_inst_jbe_handler}, - - {SCF_OP_3AC_NOP, _arm64_inst_nop_handler}, - {SCF_OP_3AC_END, _arm64_inst_end_handler}, - - {SCF_OP_3AC_SAVE, _arm64_inst_save_handler}, - {SCF_OP_3AC_LOAD, _arm64_inst_load_handler}, - - {SCF_OP_3AC_RESAVE, _arm64_inst_save_handler}, - {SCF_OP_3AC_RELOAD, _arm64_inst_reload_handler}, - - {SCF_OP_3AC_INC, _arm64_inst_inc_handler}, - {SCF_OP_3AC_DEC, _arm64_inst_dec_handler}, - - {SCF_OP_3AC_PUSH_RAX, _arm64_inst_push_rax_handler}, - {SCF_OP_3AC_POP_RAX, _arm64_inst_pop_rax_handler}, - - {SCF_OP_3AC_MEMSET, _arm64_inst_memset_handler}, - - {SCF_OP_3AC_ASSIGN_DEREFERENCE, _arm64_inst_assign_dereference_handler}, - {SCF_OP_3AC_ASSIGN_ARRAY_INDEX, _arm64_inst_assign_array_index_handler}, - {SCF_OP_3AC_ASSIGN_POINTER, _arm64_inst_assign_pointer_handler}, - - {SCF_OP_3AC_ADD_ASSIGN_DEREFERENCE, _arm64_inst_add_assign_dereference_handler}, - {SCF_OP_3AC_ADD_ASSIGN_ARRAY_INDEX, _arm64_inst_add_assign_array_index_handler}, - {SCF_OP_3AC_ADD_ASSIGN_POINTER, _arm64_inst_add_assign_pointer_handler}, - - {SCF_OP_3AC_SUB_ASSIGN_DEREFERENCE, _arm64_inst_sub_assign_dereference_handler}, - {SCF_OP_3AC_SUB_ASSIGN_ARRAY_INDEX, _arm64_inst_sub_assign_array_index_handler}, - {SCF_OP_3AC_SUB_ASSIGN_POINTER, _arm64_inst_sub_assign_pointer_handler}, - - {SCF_OP_3AC_AND_ASSIGN_DEREFERENCE, _arm64_inst_and_assign_dereference_handler}, - {SCF_OP_3AC_AND_ASSIGN_ARRAY_INDEX, _arm64_inst_and_assign_array_index_handler}, - {SCF_OP_3AC_AND_ASSIGN_POINTER, _arm64_inst_and_assign_pointer_handler}, - - {SCF_OP_3AC_OR_ASSIGN_DEREFERENCE, _arm64_inst_or_assign_dereference_handler}, - {SCF_OP_3AC_OR_ASSIGN_ARRAY_INDEX, _arm64_inst_or_assign_array_index_handler}, - {SCF_OP_3AC_OR_ASSIGN_POINTER, _arm64_inst_or_assign_pointer_handler}, - - {SCF_OP_3AC_INC_DEREFERENCE, _arm64_inst_inc_dereference_handler}, - {SCF_OP_3AC_INC_ARRAY_INDEX, _arm64_inst_inc_array_index_handler}, - {SCF_OP_3AC_INC_POINTER, _arm64_inst_inc_pointer_handler}, - - {SCF_OP_3AC_INC_POST_DEREFERENCE, _arm64_inst_inc_post_dereference_handler}, - {SCF_OP_3AC_INC_POST_ARRAY_INDEX, _arm64_inst_inc_post_array_index_handler}, - {SCF_OP_3AC_INC_POST_POINTER, _arm64_inst_inc_post_pointer_handler}, - - {SCF_OP_3AC_DEC_DEREFERENCE, _arm64_inst_dec_dereference_handler}, - {SCF_OP_3AC_DEC_ARRAY_INDEX, _arm64_inst_dec_array_index_handler}, - {SCF_OP_3AC_DEC_POINTER, _arm64_inst_dec_pointer_handler}, - - {SCF_OP_3AC_DEC_POST_DEREFERENCE, _arm64_inst_dec_post_dereference_handler}, - {SCF_OP_3AC_DEC_POST_ARRAY_INDEX, _arm64_inst_dec_post_array_index_handler}, - {SCF_OP_3AC_DEC_POST_POINTER, _arm64_inst_dec_post_pointer_handler}, - - {SCF_OP_3AC_ADDRESS_OF_ARRAY_INDEX, _arm64_inst_address_of_array_index_handler}, - {SCF_OP_3AC_ADDRESS_OF_POINTER, _arm64_inst_address_of_pointer_handler}, -}; - -arm64_inst_handler_t* scf_arm64_find_inst_handler(const int op_type) -{ - int i; - for (i = 0; i < sizeof(arm64_inst_handlers) / sizeof(arm64_inst_handlers[0]); i++) { - - arm64_inst_handler_t* h = &(arm64_inst_handlers[i]); - - if (op_type == h->type) - return h; - } - return NULL; -} diff --git a/native/arm64/scf_arm64_opcode.c b/native/arm64/scf_arm64_opcode.c deleted file mode 100644 index ab041fb..0000000 --- a/native/arm64/scf_arm64_opcode.c +++ /dev/null @@ -1,362 +0,0 @@ -#include"scf_arm64.h" - -scf_arm64_OpCode_t arm64_OpCodes[] = { - {SCF_ARM64_PUSH, "push", 1, {0x50, 0x0, 0x0},1, 8,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_POP, "pop", 1, {0x58, 0x0, 0x0},1, 8,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - - {SCF_ARM64_INC, "inc", 2, {0xfe, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 0,1, 0,{0,0}}, - {SCF_ARM64_INC, "inc", 2, {0xff, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 0,1, 0,{0,0}}, - {SCF_ARM64_INC, "inc", 2, {0xff, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 0,1, 0,{0,0}}, - {SCF_ARM64_INC, "inc", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 0,1, 0,{0,0}}, - - {SCF_ARM64_DEC, "dec", 2, {0xfe, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 1,1, 0,{0,0}}, - {SCF_ARM64_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 1,1, 0,{0,0}}, - {SCF_ARM64_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 1,1, 0,{0,0}}, - {SCF_ARM64_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 1,1, 0,{0,0}}, - - {SCF_ARM64_XOR, "xor", 2, {0x30, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x32, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, -#if 0 - {SCF_ARM64_XOR, "xor", 2, {0x34, 0x0, 0x0},1, 1,1, SCF_ARM64_I2G, 0,0, 1,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 2,2, SCF_ARM64_I2G, 0,0, 1,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 4,4, SCF_ARM64_I2G, 0,0, 1,{0,0}}, - {SCF_ARM64_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 4,8, SCF_ARM64_I2G, 0,0, 1,{0,0}}, -#endif - {SCF_ARM64_AND, "and", 2, {0x20, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x21, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x21, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x21, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x22, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x23, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x23, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x23, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_AND, "and", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - - {SCF_ARM64_OR, "or", 2, {0x08, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x09, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x09, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x09, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x0a, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x0b, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x0b, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x0b, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 1,1, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 1,1, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 1,1, 0,{0,0}}, - {SCF_ARM64_OR, "or", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 1,1, 0,{0,0}}, - - {SCF_ARM64_CALL, "call", 5, {0xe8, 0x0, 0x0},1, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_CALL, "call", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 2,1, 0,{0,0}}, - - {SCF_ARM64_RET, "ret", 1, {0xc3, 0x0, 0x0},1, 8,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - - {SCF_ARM64_ADD, "add", 2, {0x00, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x01, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x01, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x01, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x02, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x03, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x03, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x03, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - // add r/m, imm - {SCF_ARM64_ADD, "add", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - - // add r/m, imm8 - {SCF_ARM64_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - - - {SCF_ARM64_SUB, "sub", 2, {0x28, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - - {SCF_ARM64_SUB, "sub", 2, {0x2a, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_SUB, "sub", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - - {SCF_ARM64_MUL, "mul", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 4,1, 2,{0,2}}, - {SCF_ARM64_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 4,1, 2,{0,2}}, - {SCF_ARM64_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 4,1, 2,{0,2}}, - {SCF_ARM64_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 4,1, 2,{0,2}}, - - {SCF_ARM64_IMUL, "imul", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 5,1, 2,{0,2}}, - {SCF_ARM64_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 5,1, 2,{0,2}}, - {SCF_ARM64_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 5,1, 2,{0,2}}, - {SCF_ARM64_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 5,1, 2,{0,2}}, - - {SCF_ARM64_DIV, "div", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 6,1, 2,{0,2}}, - {SCF_ARM64_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 6,1, 2,{0,2}}, - {SCF_ARM64_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 6,1, 2,{0,2}}, - {SCF_ARM64_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 6,1, 2,{0,2}}, - - {SCF_ARM64_IDIV, "idiv", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 7,1, 2,{0,2}}, - {SCF_ARM64_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 7,1, 2,{0,2}}, - {SCF_ARM64_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 7,1, 2,{0,2}}, - {SCF_ARM64_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 7,1, 2,{0,2}}, - - {SCF_ARM64_CBW, "cwd", 1, {0x98, 0x0, 0x0},1, 1,2, SCF_ARM64_G, 0,0, 2,{0,2}}, - {SCF_ARM64_CWD, "cwd", 1, {0x98, 0x0, 0x0},1, 2,4, SCF_ARM64_G, 0,0, 2,{0,2}}, - {SCF_ARM64_CDQ, "cdq", 1, {0x98, 0x0, 0x0},1, 4,8, SCF_ARM64_G, 0,0, 2,{0,2}}, - {SCF_ARM64_CQO, "cqo", 1, {0x98, 0x0, 0x0},1, 8,16, SCF_ARM64_G, 0,0, 2,{0,2}}, - - {SCF_ARM64_SAR, "sar", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 7,1, 1,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_ARM64_G2E, 7,1, 1,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_ARM64_G2E, 7,1, 1,{0,0}}, - {SCF_ARM64_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_ARM64_G2E, 7,1, 1,{0,0}}, - - {SCF_ARM64_SHR, "shr", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 5,1, 0,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 5,1, 1,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_ARM64_G2E, 5,1, 1,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_ARM64_G2E, 5,1, 1,{0,0}}, - {SCF_ARM64_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_ARM64_G2E, 5,1, 1,{0,0}}, - - {SCF_ARM64_SHL, "shl", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 4,1, 0,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 4,1, 1,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_ARM64_G2E, 4,1, 1,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_ARM64_G2E, 4,1, 1,{0,0}}, - {SCF_ARM64_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_ARM64_G2E, 4,1, 1,{0,0}}, - - {SCF_ARM64_NEG, "neg", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 3,1, 0,{0,0}}, - {SCF_ARM64_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 3,1, 0,{0,0}}, - {SCF_ARM64_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 3,1, 0,{0,0}}, - {SCF_ARM64_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 3,1, 0,{0,0}}, - - {SCF_ARM64_NOT, "not", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_E, 2,1, 0,{0,0}}, - {SCF_ARM64_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_E, 2,1, 0,{0,0}}, - {SCF_ARM64_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_E, 2,1, 0,{0,0}}, - {SCF_ARM64_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 2,1, 0,{0,0}}, - - {SCF_ARM64_LEA, "lea", 1, {0x8d, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MOV, "mov", 2, {0x88, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x8a, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MOV, "mov", 2, {0xb0, 0x0, 0x0},1, 1,1, SCF_ARM64_I2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 2,2, SCF_ARM64_I2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 4,4, SCF_ARM64_I2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 8,8, SCF_ARM64_I2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xc6, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - - {SCF_ARM64_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSX, "movsx", 2, {0x0f, 0xbf, 0x0},2, 2,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSX, "movsx", 2, {0x0f, 0xbf, 0x0},2, 2,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSX, "movsx", 2, {0x63, 0x0, 0x0}, 1, 4,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVZX, "movzx", 2, {0x0f, 0xb7, 0x0},2, 2,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVZX, "movzx", 2, {0x0f, 0xb7, 0x0},2, 2,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MOVS, "movs", 2, {0xf3, 0xa4, 0x0},2, 1,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVS, "movs", 2, {0xf3, 0xa4, 0x0},2, 1,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 2,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 4,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 8,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - - {SCF_ARM64_STOS, "stos", 2, {0xf3, 0xaa, 0x0},2, 1,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_STOS, "stos", 2, {0xf3, 0xaa, 0x0},2, 1,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 2,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 4,4, SCF_ARM64_G, 0,0, 0,{0,0}}, - {SCF_ARM64_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 8,8, SCF_ARM64_G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CMP, "cmp", 2, {0x38, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x3a, 0x0, 0x0},1, 1,1, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 2,2, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CMP, "cmp", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - {SCF_ARM64_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_ARM64_I2E, 7,1, 0,{0,0}}, - - {SCF_ARM64_TEST, "test", 2, {0x84, 0x0, 0x0},1, 1,1, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0x85, 0x0, 0x0},1, 2,2, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0x85, 0x0, 0x0},1, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0x85, 0x0, 0x0},1, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - - {SCF_ARM64_TEST, "test", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - {SCF_ARM64_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 4,8, SCF_ARM64_I2E, 0,1, 0,{0,0}}, - - {SCF_ARM64_SETZ, "setz", 3, {0x0f, 0x94, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - {SCF_ARM64_SETNZ, "setnz", 3, {0x0f, 0x95, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - - {SCF_ARM64_SETG, "setg", 3, {0x0f, 0x9f, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - {SCF_ARM64_SETGE, "setge", 3, {0x0f, 0x9d, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - - {SCF_ARM64_SETL, "setl", 3, {0x0f, 0x9c, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - {SCF_ARM64_SETLE, "setle", 3, {0x0f, 0x9e, 0x0},2, 1,1, SCF_ARM64_E, 0,0, 0,{0,0}}, - - {SCF_ARM64_ADDSS, "addss", 4, {0xf3, 0x0f, 0x58},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_ADDSD, "addsd", 8, {0xf2, 0x0f, 0x58},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_SUBSS, "subss", 4, {0xf3, 0x0f, 0x5c},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_SUBSD, "subsd", 8, {0xf2, 0x0f, 0x5c},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MULSS, "mulss", 4, {0xf3, 0x0f, 0x59},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MULSD, "mulsd", 8, {0xf2, 0x0f, 0x59},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_DIVSS, "divss", 4, {0xf3, 0x0f, 0x5e},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_DIVSD, "divsd", 8, {0xf2, 0x0f, 0x5e},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_MOVSS, "movss", 4, {0xf3, 0x0f, 0x10},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSS, "movss", 4, {0xf3, 0x0f, 0x11},3, 4,4, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSD, "movsd", 8, {0xf2, 0x0f, 0x10},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_MOVSD, "movsd", 8, {0xf2, 0x0f, 0x11},3, 8,8, SCF_ARM64_G2E, 0,0, 0,{0,0}}, - - {SCF_ARM64_PXOR, "pxor", 8, {0x0f, 0xef, 0 },2, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_PXOR, "pxor", 8, {0x66, 0x0f, 0xef},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_UCOMISS, "ucomiss", 3, {0x0f, 0x2e, 0}, 2, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_UCOMISD, "ucomisd", 4, {0x66, 0x0f, 0x2e},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CVTSS2SD, "cvtss2sd", 4, {0xf3, 0x0f, 0x5a},3, 4,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CVTSD2SS, "cvtsd2ss", 4, {0xf2, 0x0f, 0x5a},3, 8,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CVTSI2SS, "cvtsi2ss", 4, {0xf3, 0x0f, 0x2a},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CVTSI2SD, "cvtsi2sd", 4, {0xf2, 0x0f, 0x2a},3, 4,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CVTSI2SD, "cvtsi2sd", 4, {0xf2, 0x0f, 0x2a},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CVTTSS2SI, "cvttss2si", 4, {0xf3, 0x0f, 0x2c},3, 4,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_CVTTSD2SI, "cvttsd2si", 8, {0xf2, 0x0f, 0x2c},3, 8,4, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - {SCF_ARM64_CVTTSD2SI, "cvttsd2si", 8, {0xf2, 0x0f, 0x2c},3, 8,8, SCF_ARM64_E2G, 0,0, 0,{0,0}}, - - {SCF_ARM64_JZ, "jz", 2, {0x74, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JZ, "jz", 6, {0x0f, 0x84, 0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JNZ, "jnz", 2, {0x75, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JNZ, "jnz", 6, {0x0f, 0x85, 0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JG, "jg", 2, {0x7f, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JG, "jg", 6, {0x0f, 0x8f,0x0},1, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JGE, "jge", 2, {0x7d, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JGE, "jge", 6, {0x0f, 0x8d,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JL, "jl", 2, {0x7c, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JL, "jl", 6, {0x0f, 0x8c,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JLE, "jle", 2, {0x7e, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JLE, "jle", 6, {0x0f, 0x8e,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JA, "ja", 2, {0x77, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JA, "ja", 6, {0x0f, 0x87,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JAE, "jae", 2, {0x73, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JAE, "jae", 6, {0x0f, 0x83,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JB, "jb", 2, {0x72, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JB, "jb", 6, {0x0f, 0x82,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JBE, "jbe", 2, {0x76, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JBE, "jbe", 6, {0x0f, 0x86,0x0},2, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - - {SCF_ARM64_JMP, "jmp", 2, {0xeb, 0x0, 0x0},1, 1,1, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JMP, "jmp", 5, {0xe9, 0x0, 0x0},1, 4,4, SCF_ARM64_I, 0,0, 0,{0,0}}, - {SCF_ARM64_JMP, "jmp", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_ARM64_E, 4,1, 0,{0,0}}, -}; - -scf_arm64_OpCode_t* arm64_find_OpCode_by_type(const int type) -{ - int i; - for (i = 0; i < sizeof(arm64_OpCodes) / sizeof(arm64_OpCodes[0]); i++) { - - scf_arm64_OpCode_t* OpCode = &(arm64_OpCodes[i]); - if (OpCode->type == type) - return OpCode; - } - return NULL; -} - -scf_arm64_OpCode_t* arm64_find_OpCode(const int type, const int OpBytes, const int RegBytes, const int EG) -{ - int i; - for (i = 0; i < sizeof(arm64_OpCodes) / sizeof(arm64_OpCodes[0]); i++) { - - scf_arm64_OpCode_t* OpCode = &(arm64_OpCodes[i]); - - if (type == OpCode->type - && OpBytes == OpCode->OpBytes - && RegBytes == OpCode->RegBytes - && EG == OpCode->EG) - return OpCode; - } - return NULL; -} - -int arm64_find_OpCodes(scf_vector_t* results, const int type, const int OpBytes, const int RegBytes, const int EG) -{ - int i; - for (i = 0; i < sizeof(arm64_OpCodes) / sizeof(arm64_OpCodes[0]); i++) { - - scf_arm64_OpCode_t* OpCode = &(arm64_OpCodes[i]); - - if (type == OpCode->type - && OpBytes == OpCode->OpBytes - && RegBytes == OpCode->RegBytes - && EG == OpCode->EG) { - - int ret = scf_vector_add(results, OpCode); - if (ret < 0) - return ret; - } - } - return 0; -} - diff --git a/native/arm64/scf_arm64_opcode.h b/native/arm64/scf_arm64_opcode.h deleted file mode 100644 index 2abb36e..0000000 --- a/native/arm64/scf_arm64_opcode.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SCF_ARM64_OPCODE_H -#define SCF_ARM64_OPCODE_H - -#include"scf_native.h" -#include"scf_arm64_util.h" - -typedef struct { - int type; - - char* name; - - int len; - - uint8_t OpCodes[3]; - int nb_OpCodes; - - // RegBytes only valid for immediate - // same to OpBytes for E2G or G2E - int OpBytes; - int RegBytes; - int EG; - - uint8_t ModRM_OpCode; - int ModRM_OpCode_used; - - int nb_regs; - uint32_t regs[2]; -} scf_arm64_OpCode_t; - -scf_arm64_OpCode_t* arm64_find_OpCode_by_type(const int type); - -scf_arm64_OpCode_t* arm64_find_OpCode(const int type, const int OpBytes, const int RegBytes, const int EG); - -int arm64_find_OpCodes(scf_vector_t* results, const int type, const int OpBytes, const int RegBytes, const int EG); - -#endif - diff --git a/native/arm64/scf_arm64_rcg.c b/native/arm64/scf_arm64_rcg.c deleted file mode 100644 index bb92b25..0000000 --- a/native/arm64/scf_arm64_rcg.c +++ /dev/null @@ -1,1297 +0,0 @@ -#include"scf_arm64.h" - -static int _arm64_rcg_node_cmp(const void* v0, const void* v1) -{ - const scf_graph_node_t* gn1 = v1; - const arm64_rcg_node_t* rn1 = gn1->data; - const arm64_rcg_node_t* rn0 = v0; - - if (rn0->dag_node || rn1->dag_node) - return rn0->dag_node != rn1->dag_node; - - return rn0->reg != rn1->reg; -} - -int arm64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg) -{ - arm64_rcg_node_t* rn = calloc(1, sizeof(arm64_rcg_node_t)); - if (!rn) - return -ENOMEM; - - rn->dag_node = dn; - rn->reg = reg; - - scf_graph_node_t* gn = scf_vector_find_cmp(g->nodes, rn, _arm64_rcg_node_cmp); - free(rn); - rn = NULL; - - if (!gn) - return -1; - - *pp = gn; - return 0; -} - -int _arm64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg) -{ - arm64_rcg_node_t* rn = calloc(1, sizeof(arm64_rcg_node_t)); - if (!rn) - return -ENOMEM; - - rn->dag_node = dn; - rn->reg = reg; - rn->OpCode = NULL; - - scf_graph_node_t* gn = scf_vector_find_cmp(g->nodes, rn, _arm64_rcg_node_cmp); - if (!gn) { - - gn = scf_graph_node_alloc(); - if (!gn) { - free(rn); - return -ENOMEM; - } - - gn->data = rn; - - if (reg) - gn->color = reg->color; - - int ret = scf_graph_add_node(g, gn); - if (ret < 0) { - free(rn); - scf_graph_node_free(gn); - return ret; - } - } else { - if (reg) - gn->color = reg->color; - - free(rn); - rn = NULL; - } - - *pp = gn; - return 0; -} - -static int _arm64_rcg_make_edge(scf_graph_node_t* gn0, scf_graph_node_t* gn1) -{ - if (gn0 == gn1) - return 0; - - if (!scf_vector_find(gn0->neighbors, gn1)) { - - assert(!scf_vector_find(gn1->neighbors, gn0)); - - int ret = scf_graph_make_edge(gn0, gn1); - if (ret < 0) - return ret; - - ret = scf_graph_make_edge(gn1, gn0); - if (ret < 0) - return ret; - } else - assert(scf_vector_find(gn1->neighbors, gn0)); - - return 0; -} - -static int _arm64_rcg_active_vars(scf_graph_t* g, scf_vector_t* active_vars) -{ - scf_graph_node_t* gn0; - scf_graph_node_t* gn1; - - scf_dn_status_t* ds0; - scf_dn_status_t* ds1; - - scf_dag_node_t* dn0; - scf_dag_node_t* dn1; - - int ret; - int i; - int j; - - for (i = 0; i < active_vars->size; i++) { - - ds0 = active_vars->data[i]; - dn0 = ds0->dag_node; - - if (!ds0->active) - continue; - - ret = _arm64_rcg_make_node(&gn0, g, dn0, NULL); - if (ret < 0) - return ret; - - for (j = 0; j < i; j++) { - - ds1 = active_vars->data[j]; - dn1 = ds1->dag_node; - - if (!ds1->active) - continue; - - ret = _arm64_rcg_make_node(&gn1, g, dn1, NULL); - if (ret < 0) - return ret; - - assert(gn0 != gn1); - - ret = _arm64_rcg_make_edge(gn0, gn1); - if (ret < 0) - return ret; - } - } - - return 0; -} - -static int _arm64_rcg_operands(scf_graph_t* g, scf_vector_t* operands) -{ - scf_3ac_operand_t* operand0; - scf_3ac_operand_t* operand1; - - scf_graph_node_t* gn0; - scf_graph_node_t* gn1; - - scf_dag_node_t* dn0; - scf_dag_node_t* dn1; - - int i; - int j; - - for (i = 0; i < operands->size; i++) { - - operand0 = operands->data[i]; - dn0 = operand0->dag_node; - - if (scf_variable_const(dn0->var)) - continue; - - int ret = _arm64_rcg_make_node(&gn0, g, dn0, NULL); - if (ret < 0) - return ret; - - for (j = 0; j < i; j++) { - - operand1 = operands->data[j]; - dn1 = operand1->dag_node; - - if (scf_variable_const(dn1->var)) - continue; - - ret = _arm64_rcg_make_node(&gn1, g, dn1, NULL); - if (ret < 0) - return ret; - - if (gn1 == gn0) - continue; - - ret = _arm64_rcg_make_edge(gn0, gn1); - if (ret < 0) - return ret; - } - } - - return 0; -} - -static int _arm64_rcg_to_active_vars(scf_graph_t* g, scf_graph_node_t* gn0, scf_vector_t* active_vars) -{ - scf_graph_node_t* gn1; - scf_dn_status_t* ds1; - scf_dag_node_t* dn1; - - int ret; - int i; - - for (i = 0; i < active_vars->size; i++) { - - ds1 = active_vars->data[i]; - dn1 = ds1->dag_node; - - if (!ds1->active) - continue; - - ret = _arm64_rcg_make_node(&gn1, g, dn1, NULL); - if (ret < 0) - return ret; - - if (gn0 == gn1) - continue; - - ret = _arm64_rcg_make_edge(gn0, gn1); - if (ret < 0) - return ret; - } - - return 0; -} - -int arm64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_arm64_t* reg) -{ - scf_graph_node_t* gn0 = NULL; - scf_graph_node_t* gn1; - scf_dag_node_t* dn1; - scf_dn_status_t* ds1; - - int ret; - int i; - - if (dn || reg) { - ret = _arm64_rcg_make_node(&gn0, g, dn, reg); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - scf_logd("g->nodes->size: %d, active_vars: %d\n", g->nodes->size, c->active_vars->size); - - ret = _arm64_rcg_active_vars(g, c->active_vars); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (gn0) - return _arm64_rcg_to_active_vars(g, gn0, c->active_vars); - - return 0; -} - -static int _arm64_rcg_make2(scf_3ac_code_t* c, scf_dag_node_t* dn, scf_register_arm64_t* reg) -{ - if (c->rcg) - scf_graph_free(c->rcg); - - c->rcg = scf_graph_alloc(); - if (!c->rcg) - return -ENOMEM; - - return arm64_rcg_make(c, c->rcg, dn, reg); -} - -static int _arm64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; - scf_dag_node_t* dn = NULL; - scf_register_arm64_t* r = NULL; - scf_3ac_operand_t* src = NULL; - scf_3ac_operand_t* dst = NULL; - scf_graph_node_t* gn = NULL; - - int i; - int ret; - - if (c->srcs->size < 1) - return -EINVAL; - - ret = _arm64_rcg_active_vars(g, c->active_vars); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = _arm64_rcg_operands(g, c->srcs); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (c->dsts) { - - if (c->dsts->size > ARM64_ABI_RET_NB) { - scf_loge("\n"); - return -EINVAL; - } - - ret = _arm64_rcg_operands(g, c->dsts); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - for (i = 0; i < c->dsts->size; i++) { - dst = c->dsts->data[i]; - dn = dst->dag_node; - - if (SCF_VAR_VOID == dn->var->type && 0 == dn->var->nb_pointers) - continue; - - int is_float = scf_variable_float(dn->var); - int size = arm64_variable_size (dn->var); - - if (0 == i) - r = arm64_find_register_type_id_bytes(is_float, SCF_ARM64_REG_X0, size); - - else if (!is_float) - r = arm64_find_register_type_id_bytes(is_float, arm64_abi_ret_regs[i], size); - else - r = NULL; - - gn = NULL; - ret = _arm64_rcg_make_node(&gn, g, dn, r); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = _arm64_rcg_to_active_vars(g, gn, c->active_vars); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - } - - int nb_ints = 0; - int nb_floats = 0; - - arm64_call_rabi(&nb_ints, &nb_floats, c); - - for (i = 1; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - dn = src->dag_node; - - if (scf_variable_const(dn->var)) - continue; - - gn = NULL; - ret = _arm64_rcg_make_node(&gn, g, dn, dn->rabi2); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - scf_3ac_operand_t* src_pf = c->srcs->data[0]; - scf_graph_node_t* gn_pf = NULL; - scf_dag_node_t* dn_pf = src_pf->dag_node; - - if (!dn_pf->var->const_literal_flag) { - - ret = _arm64_rcg_make_node(&gn_pf, g, dn_pf, NULL); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - for (i = 0; i < nb_ints; i++) { - - scf_register_arm64_t* rabi = NULL; - scf_graph_node_t* gn_rabi = NULL; - - rabi = arm64_find_register_type_id_bytes(0, arm64_abi_regs[i], dn_pf->var->size); - - ret = _arm64_rcg_make_node(&gn_rabi, g, NULL, rabi); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - assert(gn_pf != gn_rabi); - - ret = _arm64_rcg_make_edge(gn_pf, gn_rabi); - if (ret < 0) - return ret; - } - } - - return ret; -} - -static int _arm64_rcg_call_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - if (c->rcg) - scf_graph_free(c->rcg); - - c->rcg = scf_graph_alloc(); - if (!c->rcg) - return -ENOMEM; - - int ret = _arm64_rcg_call(ctx, c, c->rcg); - if (ret < 0) - return ret; - - return _arm64_rcg_call(ctx, c, g); -} - -static int _arm64_rcg_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_logic_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - if (!c->srcs || c->srcs->size < 1) - return -EINVAL; - - scf_dag_node_t* dn = NULL; - scf_3ac_operand_t* src = c->srcs->data[c->srcs->size - 1]; - scf_arm64_context_t* arm64 = ctx->priv; - scf_3ac_operand_t* dst; - - if (!src || !src->dag_node) - return -EINVAL; - - if (c->dsts) { - dst = c->dsts->data[0]; - dn = dst->dag_node; - } - - return arm64_rcg_make(c, g, dn, NULL); -} - -static int _arm64_rcg_mul_div_mod2(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - if (c->rcg) - scf_graph_free(c->rcg); - - c->rcg = scf_graph_alloc(); - if (!c->rcg) - return -ENOMEM; - - int ret = _arm64_rcg_mul_div_mod(ctx, c, c->rcg); - if (ret < 0) - return ret; - - return _arm64_rcg_mul_div_mod(ctx, c, g); -} - -static int _arm64_rcg_mul_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_div_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_mod_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_add_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_sub_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - if (!c->srcs || c->srcs->size < 1) - return -EINVAL; - - scf_dag_node_t* dn = NULL; - scf_3ac_operand_t* count = c->srcs->data[c->srcs->size - 1]; - scf_graph_node_t* gn = NULL; - - if (!count || !count->dag_node) - return -EINVAL; - - if (c->dsts) { - scf_3ac_operand_t* dst = c->dsts->data[0]; - - dn = dst->dag_node; - } - - return arm64_rcg_make(c, g, dn, NULL); -} - -static int _arm64_rcg_shift2(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - if (c->rcg) - scf_graph_free(c->rcg); - - c->rcg = scf_graph_alloc(); - if (!c->rcg) - return -ENOMEM; - - int ret = _arm64_rcg_shift(ctx, c, c->rcg); - if (ret < 0) - return ret; - - return _arm64_rcg_shift(ctx, c, g); -} - -static int _arm64_rcg_shl_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_shift2(ctx, c, g); -} - -static int _arm64_rcg_shr_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_shift2(ctx, c, g); -} - -static int _arm64_rcg_bit_and_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_teq_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -#define ARM64_RCG_SET(setcc) \ -static int _arm64_rcg_##setcc##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - \ - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, dst->dag_node, NULL); \ -} -ARM64_RCG_SET(setz) -ARM64_RCG_SET(setnz) -ARM64_RCG_SET(setgt) -ARM64_RCG_SET(setge) -ARM64_RCG_SET(setlt) -ARM64_RCG_SET(setle) - -static int _arm64_rcg_eq_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_ne_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_gt_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_lt_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_add_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_sub_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_mul_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_div_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_mul_div_mod2(ctx, c, g); -} - -static int _arm64_rcg_shl_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_shift2(ctx, c, g); -} - -static int _arm64_rcg_shr_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return _arm64_rcg_shift2(ctx, c, g); -} - -static int _arm64_rcg_and_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_or_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int i; - - scf_register_arm64_t* r; - scf_3ac_operand_t* src; - scf_graph_node_t* gn; - scf_dag_node_t* dn; - - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - ret = arm64_rcg_make(c, g, NULL, NULL); - if (ret < 0) - return ret; - - if (!c->srcs) - return 0; - - for (i = 0; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - dn = src->dag_node; - - int is_float = scf_variable_float(dn->var); - int size = arm64_variable_size (dn->var); - - size = size > 4 ? 8 : 4; - - if (is_float) { - if (i > 0) { - scf_loge("\n"); - return -1; - } - - r = arm64_find_register_type_id_bytes(is_float, 0, size); - } else - r = arm64_find_register_type_id_bytes(is_float, arm64_abi_ret_regs[i], size); - - ret = _arm64_rcg_make_node(&gn, g, dn, r); - if (ret < 0) - return ret; - } - - return 0; -} - -static int _arm64_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int i; - - scf_register_arm64_t* r; - scf_3ac_operand_t* src; - scf_graph_node_t* gn; - scf_dag_node_t* dn; - - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - ret = arm64_rcg_make(c, g, NULL, NULL); - if (ret < 0) - return ret; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; -#if 0 - for (i = 0; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - dn = src->dag_node; - - int size = arm64_variable_size (dn->var); - size = size > 4 ? 8 : 4; - - if (0 == i) - r = arm64_find_register_type_id_bytes(0, SCF_ARM64_REG_DI, size); - - else if (1 == i) - r = arm64_find_register_type_id_bytes(0, SCF_ARM64_REG_AX, size); - - else if (2 == i) - r = arm64_find_register_type_id_bytes(0, SCF_ARM64_REG_CX, size); - else - return -EINVAL; - - ret = _arm64_rcg_make_node(&gn, g, dn, r, NULL); - if (ret < 0) - return ret; - } -#endif - return 0; -} - -static int _arm64_rcg_goto_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} - -#define ARM64_RCG_JCC(cc) \ -static int _arm64_rcg_##cc##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - return 0; \ -} - -ARM64_RCG_JCC(jz) -ARM64_RCG_JCC(jnz) -ARM64_RCG_JCC(jgt) -ARM64_RCG_JCC(jge) -ARM64_RCG_JCC(jlt) -ARM64_RCG_JCC(jle) - -ARM64_RCG_JCC(ja) -ARM64_RCG_JCC(jae) -ARM64_RCG_JCC(jb) -ARM64_RCG_JCC(jbe) - -static int _arm64_rcg_save_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_load_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} -static int _arm64_rcg_nop_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} -static int _arm64_rcg_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} - -#define ARM64_RCG_BINARY_ASSIGN(name) \ -static int _arm64_rcg_##name##_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} \ -static int _arm64_rcg_##name##_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} \ -static int _arm64_rcg_##name##_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} - -ARM64_RCG_BINARY_ASSIGN(add) -ARM64_RCG_BINARY_ASSIGN(sub) -ARM64_RCG_BINARY_ASSIGN(and) -ARM64_RCG_BINARY_ASSIGN(or) - -#define ARM64_RCG_SHIFT_ASSIGN(name) \ -static int _arm64_rcg_##name##_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - return _arm64_rcg_shift2(ctx, c, g); \ -} \ -static int _arm64_rcg_##name##_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - return _arm64_rcg_shift2(ctx, c, g); \ -} \ -static int _arm64_rcg_##name##_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - return _arm64_rcg_shift2(ctx, c, g); \ -} -ARM64_RCG_SHIFT_ASSIGN(shl) -ARM64_RCG_SHIFT_ASSIGN(shr) - -#define ARM64_RCG_UNARY_ASSIGN(name) \ -static int _arm64_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} \ -static int _arm64_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} \ -static int _arm64_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} \ -static int _arm64_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - int ret = _arm64_rcg_make2(c, NULL, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, NULL, NULL); \ -} -ARM64_RCG_UNARY_ASSIGN(inc) -ARM64_RCG_UNARY_ASSIGN(dec) - -#define ARM64_RCG_UNARY_POST_ASSIGN(name) \ -static int _arm64_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - \ - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, dst->dag_node, NULL); \ -} \ -static int _arm64_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - \ - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, dst->dag_node, NULL); \ -} \ -static int _arm64_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - \ - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, dst->dag_node, NULL); \ -} \ -static int _arm64_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ -{ \ - scf_3ac_operand_t* dst = c->dsts->data[0]; \ - \ - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); \ - if (ret < 0) \ - return ret; \ - return arm64_rcg_make(c, g, dst->dag_node, NULL); \ -} -ARM64_RCG_UNARY_POST_ASSIGN(inc_post) -ARM64_RCG_UNARY_POST_ASSIGN(dec_post) - -static int _arm64_rcg_address_of_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static int _arm64_rcg_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} -static int _arm64_rcg_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - return 0; -} - -static int _arm64_rcg_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_va_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _arm64_rcg_make2(c, NULL, NULL); - if (ret < 0) - return ret; - return arm64_rcg_make(c, g, NULL, NULL); -} - -static int _arm64_rcg_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - scf_3ac_operand_t* dst = c->dsts->data[0]; - - int ret = _arm64_rcg_make2(c, dst->dag_node, NULL); - if (ret < 0) - return ret; - return arm64_rcg_make(c, g, dst->dag_node, NULL); -} - -static arm64_rcg_handler_t arm64_rcg_handlers[] = { - - {SCF_OP_CALL, _arm64_rcg_call_handler}, - {SCF_OP_ARRAY_INDEX, _arm64_rcg_array_index_handler}, - - {SCF_OP_TYPE_CAST, _arm64_rcg_cast_handler}, - {SCF_OP_LOGIC_NOT, _arm64_rcg_logic_not_handler}, - {SCF_OP_BIT_NOT, _arm64_rcg_bit_not_handler}, - {SCF_OP_NEG, _arm64_rcg_neg_handler}, - - {SCF_OP_VA_START, _arm64_rcg_va_start_handler}, - {SCF_OP_VA_ARG, _arm64_rcg_va_arg_handler}, - {SCF_OP_VA_END, _arm64_rcg_va_end_handler}, - - {SCF_OP_INC, _arm64_rcg_inc_handler}, - {SCF_OP_DEC, _arm64_rcg_dec_handler}, - - {SCF_OP_INC_POST, _arm64_rcg_inc_post_handler}, - {SCF_OP_DEC_POST, _arm64_rcg_dec_post_handler}, - - {SCF_OP_DEREFERENCE, _arm64_rcg_dereference_handler}, - {SCF_OP_ADDRESS_OF, _arm64_rcg_address_of_handler}, - {SCF_OP_POINTER, _arm64_rcg_pointer_handler}, - - {SCF_OP_MUL, _arm64_rcg_mul_handler}, - {SCF_OP_DIV, _arm64_rcg_div_handler}, - {SCF_OP_MOD, _arm64_rcg_mod_handler}, - - {SCF_OP_ADD, _arm64_rcg_add_handler}, - {SCF_OP_SUB, _arm64_rcg_sub_handler}, - - {SCF_OP_SHL, _arm64_rcg_shl_handler}, - {SCF_OP_SHR, _arm64_rcg_shr_handler}, - - {SCF_OP_BIT_AND, _arm64_rcg_bit_and_handler}, - {SCF_OP_BIT_OR, _arm64_rcg_bit_or_handler}, - - {SCF_OP_EQ, _arm64_rcg_eq_handler}, - {SCF_OP_NE, _arm64_rcg_ne_handler}, - {SCF_OP_GT, _arm64_rcg_gt_handler}, - {SCF_OP_LT, _arm64_rcg_lt_handler}, - - {SCF_OP_ASSIGN, _arm64_rcg_assign_handler}, - {SCF_OP_ADD_ASSIGN, _arm64_rcg_add_assign_handler}, - {SCF_OP_SUB_ASSIGN, _arm64_rcg_sub_assign_handler}, - - {SCF_OP_MUL_ASSIGN, _arm64_rcg_mul_assign_handler}, - {SCF_OP_DIV_ASSIGN, _arm64_rcg_div_assign_handler}, - {SCF_OP_MOD_ASSIGN, _arm64_rcg_mod_assign_handler}, - - {SCF_OP_SHL_ASSIGN, _arm64_rcg_shl_assign_handler}, - {SCF_OP_SHR_ASSIGN, _arm64_rcg_shr_assign_handler}, - - {SCF_OP_AND_ASSIGN, _arm64_rcg_and_assign_handler}, - {SCF_OP_OR_ASSIGN, _arm64_rcg_or_assign_handler}, - - {SCF_OP_RETURN, _arm64_rcg_return_handler}, - - {SCF_OP_3AC_CMP, _arm64_rcg_cmp_handler}, - {SCF_OP_3AC_TEQ, _arm64_rcg_teq_handler}, - - {SCF_OP_3AC_SETZ, _arm64_rcg_setz_handler}, - {SCF_OP_3AC_SETNZ, _arm64_rcg_setnz_handler}, - {SCF_OP_3AC_SETGT, _arm64_rcg_setgt_handler}, - {SCF_OP_3AC_SETGE, _arm64_rcg_setge_handler}, - {SCF_OP_3AC_SETLT, _arm64_rcg_setlt_handler}, - {SCF_OP_3AC_SETLE, _arm64_rcg_setle_handler}, - - {SCF_OP_GOTO, _arm64_rcg_goto_handler}, - {SCF_OP_3AC_JZ, _arm64_rcg_jz_handler}, - {SCF_OP_3AC_JNZ, _arm64_rcg_jnz_handler}, - {SCF_OP_3AC_JGT, _arm64_rcg_jgt_handler}, - {SCF_OP_3AC_JGE, _arm64_rcg_jge_handler}, - {SCF_OP_3AC_JLT, _arm64_rcg_jlt_handler}, - {SCF_OP_3AC_JLE, _arm64_rcg_jle_handler}, - - {SCF_OP_3AC_JA, _arm64_rcg_ja_handler}, - {SCF_OP_3AC_JAE, _arm64_rcg_jae_handler}, - {SCF_OP_3AC_JB, _arm64_rcg_jb_handler}, - {SCF_OP_3AC_JBE, _arm64_rcg_jbe_handler}, - - {SCF_OP_3AC_SAVE, _arm64_rcg_save_handler}, - {SCF_OP_3AC_LOAD, _arm64_rcg_load_handler}, - - {SCF_OP_3AC_RESAVE, _arm64_rcg_save_handler}, - {SCF_OP_3AC_RELOAD, _arm64_rcg_load_handler}, - - {SCF_OP_3AC_NOP, _arm64_rcg_nop_handler}, - {SCF_OP_3AC_END, _arm64_rcg_end_handler}, - - {SCF_OP_3AC_INC, _arm64_rcg_inc_handler}, - {SCF_OP_3AC_DEC, _arm64_rcg_dec_handler}, - - {SCF_OP_3AC_PUSH_RAX, _arm64_rcg_push_rax_handler}, - {SCF_OP_3AC_POP_RAX, _arm64_rcg_pop_rax_handler}, - - {SCF_OP_3AC_MEMSET, _arm64_rcg_memset_handler}, - - - {SCF_OP_3AC_ASSIGN_DEREFERENCE, _arm64_rcg_assign_dereference_handler}, - {SCF_OP_3AC_ASSIGN_ARRAY_INDEX, _arm64_rcg_assign_array_index_handler}, - {SCF_OP_3AC_ASSIGN_POINTER, _arm64_rcg_assign_pointer_handler}, - - {SCF_OP_3AC_ADD_ASSIGN_DEREFERENCE, _arm64_rcg_add_assign_dereference_handler}, - {SCF_OP_3AC_ADD_ASSIGN_ARRAY_INDEX, _arm64_rcg_add_assign_array_index_handler}, - {SCF_OP_3AC_ADD_ASSIGN_POINTER, _arm64_rcg_add_assign_pointer_handler}, - - {SCF_OP_3AC_SUB_ASSIGN_DEREFERENCE, _arm64_rcg_sub_assign_dereference_handler}, - {SCF_OP_3AC_SUB_ASSIGN_ARRAY_INDEX, _arm64_rcg_sub_assign_array_index_handler}, - {SCF_OP_3AC_SUB_ASSIGN_POINTER, _arm64_rcg_sub_assign_pointer_handler}, - - {SCF_OP_3AC_AND_ASSIGN_DEREFERENCE, _arm64_rcg_and_assign_dereference_handler}, - {SCF_OP_3AC_AND_ASSIGN_ARRAY_INDEX, _arm64_rcg_and_assign_array_index_handler}, - {SCF_OP_3AC_AND_ASSIGN_POINTER, _arm64_rcg_and_assign_pointer_handler}, - - {SCF_OP_3AC_OR_ASSIGN_DEREFERENCE, _arm64_rcg_or_assign_dereference_handler}, - {SCF_OP_3AC_OR_ASSIGN_ARRAY_INDEX, _arm64_rcg_or_assign_array_index_handler}, - {SCF_OP_3AC_OR_ASSIGN_POINTER, _arm64_rcg_or_assign_pointer_handler}, - - {SCF_OP_3AC_INC_DEREFERENCE, _arm64_rcg_inc_dereference_handler}, - {SCF_OP_3AC_INC_ARRAY_INDEX, _arm64_rcg_inc_array_index_handler}, - {SCF_OP_3AC_INC_POINTER, _arm64_rcg_inc_pointer_handler}, - - {SCF_OP_3AC_INC_POST_DEREFERENCE, _arm64_rcg_inc_post_dereference_handler}, - {SCF_OP_3AC_INC_POST_ARRAY_INDEX, _arm64_rcg_inc_post_array_index_handler}, - {SCF_OP_3AC_INC_POST_POINTER, _arm64_rcg_inc_post_pointer_handler}, - - {SCF_OP_3AC_DEC_DEREFERENCE, _arm64_rcg_dec_dereference_handler}, - {SCF_OP_3AC_DEC_ARRAY_INDEX, _arm64_rcg_dec_array_index_handler}, - {SCF_OP_3AC_DEC_POINTER, _arm64_rcg_dec_pointer_handler}, - - {SCF_OP_3AC_DEC_POST_DEREFERENCE, _arm64_rcg_dec_post_dereference_handler}, - {SCF_OP_3AC_DEC_POST_ARRAY_INDEX, _arm64_rcg_dec_post_array_index_handler}, - {SCF_OP_3AC_DEC_POST_POINTER, _arm64_rcg_dec_post_pointer_handler}, - - {SCF_OP_3AC_ADDRESS_OF_ARRAY_INDEX, _arm64_rcg_address_of_array_index_handler}, - {SCF_OP_3AC_ADDRESS_OF_POINTER, _arm64_rcg_address_of_pointer_handler}, -}; - -arm64_rcg_handler_t* scf_arm64_find_rcg_handler(const int op_type) -{ - int i; - for (i = 0; i < sizeof(arm64_rcg_handlers) / sizeof(arm64_rcg_handlers[0]); i++) { - - arm64_rcg_handler_t* h = &(arm64_rcg_handlers[i]); - - if (op_type == h->type) - return h; - } - return NULL; -} diff --git a/native/arm64/scf_arm64_reg.c b/native/arm64/scf_arm64_reg.c deleted file mode 100644 index dfc0755..0000000 --- a/native/arm64/scf_arm64_reg.c +++ /dev/null @@ -1,1492 +0,0 @@ -#include"scf_arm64.h" - -scf_register_arm64_t arm64_registers[] = { - - {0, 4, "w0", ARM64_COLOR(0, 0, 0xf), NULL, 0, 0}, - {0, 8, "x0", ARM64_COLOR(0, 0, 0xff), NULL, 0, 0}, - - {1, 4, "w1", ARM64_COLOR(0, 1, 0xf), NULL, 0, 0}, - {1, 8, "x1", ARM64_COLOR(0, 1, 0xff), NULL, 0, 0}, - - {2, 4, "w2", ARM64_COLOR(0, 2, 0xf), NULL, 0, 0}, - {2, 8, "x2", ARM64_COLOR(0, 2, 0xff), NULL, 0, 0}, - - {3, 4, "w3", ARM64_COLOR(0, 3, 0xf), NULL, 0, 0}, - {3, 8, "x3", ARM64_COLOR(0, 3, 0xff), NULL, 0, 0}, - - {4, 4, "w4", ARM64_COLOR(0, 4, 0xf), NULL, 0, 0}, - {4, 8, "x4", ARM64_COLOR(0, 4, 0xff), NULL, 0, 0}, - - {5, 4, "w5", ARM64_COLOR(0, 5, 0xf), NULL, 0, 0}, - {5, 8, "x5", ARM64_COLOR(0, 5, 0xff), NULL, 0, 0}, - - {6, 4, "w6", ARM64_COLOR(0, 6, 0xf), NULL, 0, 0}, - {6, 8, "x6", ARM64_COLOR(0, 6, 0xff), NULL, 0, 0}, - - {7, 4, "w7", ARM64_COLOR(0, 7, 0xf), NULL, 0, 0}, - {7, 8, "x7", ARM64_COLOR(0, 7, 0xff), NULL, 0, 0}, - -// not use x8 - -// {8, 4, "w8", ARM64_COLOR(0, 8, 0xf), NULL, 0}, -// {8, 8, "x8", ARM64_COLOR(0, 8, 0xff), NULL, 0}, - - {9, 4, "w9", ARM64_COLOR(0, 9, 0xf), NULL, 0, 0}, - {9, 8, "x9", ARM64_COLOR(0, 9, 0xff), NULL, 0, 0}, - - {10, 4, "w10", ARM64_COLOR(0, 10, 0xf), NULL, 0, 0}, - {10, 8, "x10", ARM64_COLOR(0, 10, 0xff), NULL, 0, 0}, - - {11, 4, "w11", ARM64_COLOR(0, 11, 0xf), NULL, 0, 0}, - {11, 8, "x11", ARM64_COLOR(0, 11, 0xff), NULL, 0, 0}, - - {12, 4, "w12", ARM64_COLOR(0, 12, 0xf), NULL, 0, 0}, - {12, 8, "x12", ARM64_COLOR(0, 12, 0xff), NULL, 0, 0}, - - {13, 4, "w13", ARM64_COLOR(0, 13, 0xf), NULL, 0, 0}, - {13, 8, "x13", ARM64_COLOR(0, 13, 0xff), NULL, 0, 0}, - - {14, 4, "w14", ARM64_COLOR(0, 14, 0xf), NULL, 0, 0}, - {14, 8, "x14", ARM64_COLOR(0, 14, 0xff), NULL, 0, 0}, - - {15, 4, "w15", ARM64_COLOR(0, 15, 0xf), NULL, 0, 0}, - {15, 8, "x15", ARM64_COLOR(0, 15, 0xff), NULL, 0, 0}, - -// not use x16, x17, x18 - -// {16, 4, "w16", ARM64_COLOR(0, 16, 0xf), NULL, 0, 0}, -// {16, 8, "x16", ARM64_COLOR(0, 16, 0xff), NULL, 0, 0}, - -// {17, 4, "w17", ARM64_COLOR(0, 17, 0xf), NULL, 0, 0}, -// {17, 8, "x17", ARM64_COLOR(0, 17, 0xff), NULL, 0, 0}, - -// {18, 4, "w18", ARM64_COLOR(0, 18, 0xf), NULL, 0, 0}, -// {18, 8, "x18", ARM64_COLOR(0, 18, 0xff), NULL, 0, 0}, - - {19, 4, "w19", ARM64_COLOR(0, 19, 0xf), NULL, 0, 0}, - {19, 8, "x19", ARM64_COLOR(0, 19, 0xff), NULL, 0, 0}, - - {20, 4, "w20", ARM64_COLOR(0, 20, 0xf), NULL, 0, 0}, - {20, 8, "x20", ARM64_COLOR(0, 20, 0xff), NULL, 0, 0}, - - {21, 4, "w21", ARM64_COLOR(0, 21, 0xf), NULL, 0, 0}, - {21, 8, "x21", ARM64_COLOR(0, 21, 0xff), NULL, 0, 0}, - - {22, 4, "w22", ARM64_COLOR(0, 22, 0xf), NULL, 0, 0}, - {22, 8, "x22", ARM64_COLOR(0, 22, 0xff), NULL, 0, 0}, - - {23, 4, "w23", ARM64_COLOR(0, 23, 0xf), NULL, 0, 0}, - {23, 8, "x23", ARM64_COLOR(0, 23, 0xff), NULL, 0, 0}, - - {24, 4, "w24", ARM64_COLOR(0, 24, 0xf), NULL, 0, 0}, - {24, 8, "x24", ARM64_COLOR(0, 24, 0xff), NULL, 0, 0}, - - {25, 4, "w25", ARM64_COLOR(0, 25, 0xf), NULL, 0, 0}, - {25, 8, "x25", ARM64_COLOR(0, 25, 0xff), NULL, 0, 0}, - - {26, 4, "w26", ARM64_COLOR(0, 26, 0xf), NULL, 0, 0}, - {26, 8, "x26", ARM64_COLOR(0, 26, 0xff), NULL, 0, 0}, - - {27, 4, "w27", ARM64_COLOR(0, 27, 0xf), NULL, 0, 0}, - {27, 8, "x27", ARM64_COLOR(0, 27, 0xff), NULL, 0, 0}, - - {28, 4, "w28", ARM64_COLOR(0, 28, 0xf), NULL, 0, 0}, - {28, 8, "x28", ARM64_COLOR(0, 28, 0xff), NULL, 0, 0}, - -// fp = x29 = bp - {29, 4, "w29", ARM64_COLOR(0, 29, 0xf), NULL, 0, 0}, - {29, 8, "fp", ARM64_COLOR(0, 29, 0xff), NULL, 0, 0}, -// lr = x30 - {30, 4, "w30", ARM64_COLOR(0, 30, 0xf), NULL, 0, 0}, - {30, 8, "lr", ARM64_COLOR(0, 30, 0xff), NULL, 0, 0}, - {31, 8, "sp", ARM64_COLOR(0, 31, 0xff), NULL, 0, 0}, - - - {0, 2, "h0", ARM64_COLOR(1, 0, 0x3), NULL, 0, 0}, - {0, 4, "s0", ARM64_COLOR(1, 0, 0xf), NULL, 0, 0}, - {0, 8, "d0", ARM64_COLOR(1, 0, 0xff), NULL, 0, 0}, - - {1, 2, "h1", ARM64_COLOR(1, 1, 0x3), NULL, 0, 0}, - {1, 4, "s1", ARM64_COLOR(1, 1, 0xf), NULL, 0, 0}, - {1, 8, "d1", ARM64_COLOR(1, 1, 0xff), NULL, 0, 0}, - - {2, 2, "h2", ARM64_COLOR(1, 2, 0x3), NULL, 0, 0}, - {2, 4, "s2", ARM64_COLOR(1, 2, 0xf), NULL, 0, 0}, - {2, 8, "d2", ARM64_COLOR(1, 2, 0xff), NULL, 0, 0}, - - {3, 2, "h3", ARM64_COLOR(1, 3, 0x3), NULL, 0, 0}, - {3, 4, "s3", ARM64_COLOR(1, 3, 0xf), NULL, 0, 0}, - {3, 8, "d3", ARM64_COLOR(1, 3, 0xff), NULL, 0, 0}, - - {4, 2, "h4", ARM64_COLOR(1, 4, 0x3), NULL, 0, 0}, - {4, 4, "s4", ARM64_COLOR(1, 4, 0xf), NULL, 0, 0}, - {4, 8, "d4", ARM64_COLOR(1, 4, 0xff), NULL, 0, 0}, - - {5, 2, "h5", ARM64_COLOR(1, 5, 0x3), NULL, 0, 0}, - {5, 4, "s5", ARM64_COLOR(1, 5, 0xf), NULL, 0, 0}, - {5, 8, "d5", ARM64_COLOR(1, 5, 0xff), NULL, 0, 0}, - - {6, 2, "h6", ARM64_COLOR(1, 6, 0x3), NULL, 0, 0}, - {6, 4, "s6", ARM64_COLOR(1, 6, 0xf), NULL, 0, 0}, - {6, 8, "d6", ARM64_COLOR(1, 6, 0xff), NULL, 0, 0}, - - {7, 2, "h7", ARM64_COLOR(1, 7, 0x3), NULL, 0, 0}, - {7, 4, "s7", ARM64_COLOR(1, 7, 0xf), NULL, 0, 0}, - {7, 8, "d7", ARM64_COLOR(1, 7, 0xff), NULL, 0, 0}, - - {8, 2, "h8", ARM64_COLOR(1, 8, 0x3), NULL, 0, 0}, - {8, 4, "s8", ARM64_COLOR(1, 8, 0xf), NULL, 0, 0}, - {8, 8, "d8", ARM64_COLOR(1, 8, 0xff), NULL, 0, 0}, - - {9, 2, "h9", ARM64_COLOR(1, 9, 0x3), NULL, 0, 0}, - {9, 4, "s9", ARM64_COLOR(1, 9, 0xf), NULL, 0, 0}, - {9, 8, "d9", ARM64_COLOR(1, 9, 0xff), NULL, 0, 0}, - - {10, 2, "h10", ARM64_COLOR(1, 10, 0x3), NULL, 0, 0}, - {10, 4, "s10", ARM64_COLOR(1, 10, 0xf), NULL, 0, 0}, - {10, 8, "d10", ARM64_COLOR(1, 10, 0xff), NULL, 0, 0}, - - {11, 2, "h11", ARM64_COLOR(1, 11, 0x3), NULL, 0, 0}, - {11, 4, "s11", ARM64_COLOR(1, 11, 0xf), NULL, 0, 0}, - {11, 8, "d11", ARM64_COLOR(1, 11, 0xff), NULL, 0, 0}, - - {12, 2, "h12", ARM64_COLOR(1, 12, 0x3), NULL, 0, 0}, - {12, 4, "s12", ARM64_COLOR(1, 12, 0xf), NULL, 0, 0}, - {12, 8, "d12", ARM64_COLOR(1, 12, 0xff), NULL, 0, 0}, - - {13, 2, "h13", ARM64_COLOR(1, 13, 0x3), NULL, 0, 0}, - {13, 4, "s13", ARM64_COLOR(1, 13, 0xf), NULL, 0, 0}, - {13, 8, "d13", ARM64_COLOR(1, 13, 0xff), NULL, 0, 0}, - - {14, 2, "h14", ARM64_COLOR(1, 14, 0x3), NULL, 0, 0}, - {14, 4, "s14", ARM64_COLOR(1, 14, 0xf), NULL, 0, 0}, - {14, 8, "d14", ARM64_COLOR(1, 14, 0xff), NULL, 0, 0}, - - {15, 2, "h15", ARM64_COLOR(1, 15, 0x3), NULL, 0, 0}, - {15, 4, "s15", ARM64_COLOR(1, 15, 0xf), NULL, 0, 0}, - {15, 8, "d15", ARM64_COLOR(1, 15, 0xff), NULL, 0, 0}, - - {16, 2, "h16", ARM64_COLOR(1, 16, 0x3), NULL, 0, 0}, - {16, 4, "s16", ARM64_COLOR(1, 16, 0xf), NULL, 0, 0}, - {16, 8, "d16", ARM64_COLOR(1, 16, 0xff), NULL, 0, 0}, - - {17, 2, "h17", ARM64_COLOR(1, 17, 0x3), NULL, 0, 0}, - {17, 4, "s17", ARM64_COLOR(1, 17, 0xf), NULL, 0, 0}, - {17, 8, "d17", ARM64_COLOR(1, 17, 0xff), NULL, 0, 0}, - - {18, 2, "h18", ARM64_COLOR(1, 18, 0x3), NULL, 0, 0}, - {18, 4, "s18", ARM64_COLOR(1, 18, 0xf), NULL, 0, 0}, - {18, 8, "d18", ARM64_COLOR(1, 18, 0xff), NULL, 0, 0}, - - {19, 2, "h19", ARM64_COLOR(1, 19, 0x3), NULL, 0, 0}, - {19, 4, "s19", ARM64_COLOR(1, 19, 0xf), NULL, 0, 0}, - {19, 8, "d19", ARM64_COLOR(1, 19, 0xff), NULL, 0, 0}, - - {20, 2, "h20", ARM64_COLOR(1, 20, 0x3), NULL, 0, 0}, - {20, 4, "s20", ARM64_COLOR(1, 20, 0xf), NULL, 0, 0}, - {20, 8, "d20", ARM64_COLOR(1, 20, 0xff), NULL, 0, 0}, - - {21, 2, "h21", ARM64_COLOR(1, 21, 0x3), NULL, 0, 0}, - {21, 4, "s21", ARM64_COLOR(1, 21, 0xf), NULL, 0, 0}, - {21, 8, "d21", ARM64_COLOR(1, 21, 0xff), NULL, 0, 0}, - - {22, 2, "h22", ARM64_COLOR(1, 22, 0x3), NULL, 0, 0}, - {22, 4, "s22", ARM64_COLOR(1, 22, 0xf), NULL, 0, 0}, - {22, 8, "d22", ARM64_COLOR(1, 22, 0xff), NULL, 0, 0}, - - {23, 2, "h23", ARM64_COLOR(1, 23, 0x3), NULL, 0, 0}, - {23, 4, "s23", ARM64_COLOR(1, 23, 0xf), NULL, 0, 0}, - {23, 8, "d23", ARM64_COLOR(1, 23, 0xff), NULL, 0, 0}, - - {24, 2, "h24", ARM64_COLOR(1, 24, 0x3), NULL, 0, 0}, - {24, 4, "s24", ARM64_COLOR(1, 24, 0xf), NULL, 0, 0}, - {24, 8, "d24", ARM64_COLOR(1, 24, 0xff), NULL, 0, 0}, - - {25, 2, "h25", ARM64_COLOR(1, 25, 0x3), NULL, 0, 0}, - {25, 4, "s25", ARM64_COLOR(1, 25, 0xf), NULL, 0, 0}, - {25, 8, "d25", ARM64_COLOR(1, 25, 0xff), NULL, 0, 0}, - - {26, 2, "h26", ARM64_COLOR(1, 26, 0x3), NULL, 0, 0}, - {26, 4, "s26", ARM64_COLOR(1, 26, 0xf), NULL, 0, 0}, - {26, 8, "d26", ARM64_COLOR(1, 26, 0xff), NULL, 0, 0}, - - {27, 2, "h27", ARM64_COLOR(1, 27, 0x3), NULL, 0, 0}, - {27, 4, "s27", ARM64_COLOR(1, 27, 0xf), NULL, 0, 0}, - {27, 8, "d27", ARM64_COLOR(1, 27, 0xff), NULL, 0, 0}, - - {28, 2, "h28", ARM64_COLOR(1, 28, 0x3), NULL, 0, 0}, - {28, 4, "s28", ARM64_COLOR(1, 28, 0xf), NULL, 0, 0}, - {28, 8, "d28", ARM64_COLOR(1, 28, 0xff), NULL, 0, 0}, - - {29, 2, "h29", ARM64_COLOR(1, 29, 0x3), NULL, 0, 0}, - {29, 4, "s29", ARM64_COLOR(1, 29, 0xf), NULL, 0, 0}, - {29, 8, "d29", ARM64_COLOR(1, 29, 0xff), NULL, 0, 0}, - - {30, 2, "h30", ARM64_COLOR(1, 30, 0x3), NULL, 0, 0}, - {30, 4, "s30", ARM64_COLOR(1, 30, 0xf), NULL, 0, 0}, - {30, 8, "d30", ARM64_COLOR(1, 30, 0xff), NULL, 0, 0}, - - {31, 2, "h31", ARM64_COLOR(1, 31, 0x3), NULL, 0, 0}, - {31, 4, "s31", ARM64_COLOR(1, 31, 0xf), NULL, 0, 0}, - {31, 8, "d31", ARM64_COLOR(1, 31, 0xff), NULL, 0, 0}, -}; - -int arm64_reg_cached_vars(scf_register_arm64_t* r) -{ - int nb_vars = 0; - int i; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r2 = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r2->id - || SCF_ARM64_REG_FP == r2->id - || SCF_ARM64_REG_LR == r2->id) - continue; - - if (!ARM64_COLOR_CONFLICT(r->color, r2->color)) - continue; - - nb_vars += r2->dag_nodes->size; - } - - return nb_vars; -} - -int arm64_registers_init() -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - assert(!r->dag_nodes); - - r->dag_nodes = scf_vector_alloc(); - if (!r->dag_nodes) - return -ENOMEM; - - r->used = 0; - } - - return 0; -} - -void arm64_registers_clear() -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (r->dag_nodes) { - scf_vector_free(r->dag_nodes); - r->dag_nodes = NULL; - } - - r->used = 0; - } -} - -int arm64_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_arm64_t** saved_regs) -{ - int i; - int j; - scf_register_arm64_t* r; - scf_register_arm64_t* r2; - scf_instruction_t* inst; - scf_register_arm64_t* sp = arm64_find_register("sp"); - - uint32_t opcode; - - int ret; - int size = 0; - int k = 0; - - for (j = 0; j < nb_regs; j++) { - r2 = arm64_find_register_type_id_bytes(0, regs[j], 8); - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (0 == r->dag_nodes->size) - continue; - - if (ARM64_COLOR_CONFLICT(r2->color, r->color)) - break; - } - - if (i == sizeof(arm64_registers) / sizeof(arm64_registers[0])) - continue; - - if (stack_size > 0) { - ret = arm64_make_inst_G2P(c, f, r2, sp, size + stack_size, 8); - if (ret < 0) - return ret; - } else { - opcode = (0xf8 << 24) | (0x1f8 << 12) | (0x3 << 10) | (sp->id << 5) | r2->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - saved_regs[k++] = r2; - size += 8; - } - - if (size & 0xf) { - r2 = saved_regs[k - 1]; - - if (stack_size > 0) { - ret = arm64_make_inst_G2P(c, f, r2, sp, size + stack_size, 8); - if (ret < 0) - return ret; - } else { - opcode = (0xf8 << 24) | (0x1f8 << 12) | (0x3 << 10) | (sp->id << 5) | r2->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - saved_regs[k++] = r2; - size += 8; - } - - if (stack_size > 0) { - for (j = 0; j < k / 2; j++) { - - i = k - 1 - j; - SCF_XCHG(saved_regs[i], saved_regs[j]); - } - } - - return size; -} - -int arm64_push_regs(scf_vector_t* instructions, uint32_t* regs, int nb_regs) -{ -#if 0 - int i; - int j; - scf_register_arm64_t* r; - scf_register_arm64_t* r2; - scf_instruction_t* inst; - scf_arm64_OpCode_t* push = arm64_find_OpCode(SCF_ARM64_PUSH, 8,8, SCF_ARM64_G); - - for (j = 0; j < nb_regs; j++) { - r2 = arm64_find_register_type_id_bytes(0, regs[j], 8); - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (0 == r->dag_nodes->size) - continue; - - if (ARM64_COLOR_CONFLICT(r2->color, r->color)) - break; - } - - if (i == sizeof(arm64_registers) / sizeof(arm64_registers[0])) - continue; - - inst = arm64_make_inst_G(push, r2); - ARM64_INST_ADD_CHECK(instructions, inst); - } - return 0; -#endif - return -1; -} - -int arm64_pop_regs(scf_3ac_code_t* c, scf_register_arm64_t** regs, int nb_regs, scf_register_arm64_t** updated_regs, int nb_updated) -{ - int i; - int j; - - scf_register_arm64_t* sp = arm64_find_register("sp"); - scf_register_arm64_t* r; - scf_register_arm64_t* r2; - scf_instruction_t* inst; - - for (j = nb_regs - 1; j >= 0; j--) { - r2 = regs[j]; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (0 == r->dag_nodes->size) - continue; - - if (ARM64_COLOR_CONFLICT(r2->color, r->color)) - break; - } - - if (i == sizeof(arm64_registers) / sizeof(arm64_registers[0])) - continue; - - for (i = 0; i < nb_updated; i++) { - - r = updated_regs[i]; - - if (ARM64_COLOR_CONFLICT(r2->color, r->color)) - break; - } - - if (i == nb_updated) { - uint32_t pop = (0xf8 << 24) | (0x1 << 22) | (0x8 << 12) | (0x1 << 10) | (0x1f << 5) | r2->id; - - inst = arm64_make_inst(c, pop); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } else { - uint32_t add8 = (0x91 << 24) | (0x8 << 10) | (sp->id << 5) | sp->id; - inst = arm64_make_inst(c, add8); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - } - return 0; -} - -int arm64_registers_reset() -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (!r->dag_nodes) - continue; - - int j = 0; - while (j < r->dag_nodes->size) { - scf_dag_node_t* dn = r->dag_nodes->data[j]; - - if (dn->var->w) - scf_logw("drop: v_%d_%d/%s\n", dn->var->w->line, dn->var->w->pos, dn->var->w->text->data); - else - scf_logw("drop: v_%#lx\n", 0xffff & (uintptr_t)dn->var); - - int ret = scf_vector_del(r->dag_nodes, dn); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - dn->loaded = 0; - dn->color = 0; - } - } - - return 0; -} - -scf_register_arm64_t* arm64_find_register(const char* name) -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (!strcmp(r->name, name)) - return r; - } - return NULL; -} - -scf_register_arm64_t* arm64_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes) -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (ARM64_COLOR_TYPE(r->color) == type && r->id == id && r->bytes == bytes) - return r; - } - return NULL; -} - -scf_register_arm64_t* arm64_find_register_color(intptr_t color) -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (r->color == color) - return r; - } - return NULL; -} - -scf_register_arm64_t* arm64_find_register_color_bytes(intptr_t color, int bytes) -{ - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (ARM64_COLOR_CONFLICT(r->color, color) && r->bytes == bytes) - return r; - } - return NULL; -} - -scf_vector_t* arm64_register_colors() -{ - scf_vector_t* colors = scf_vector_alloc(); - if (!colors) - return NULL; - - int i; - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - int ret = scf_vector_add(colors, (void*)r->color); - if (ret < 0) { - scf_vector_free(colors); - return NULL; - } - } -#if 0 - srand(time(NULL)); - for (i = 0; i < colors->size; i++) { - int j = rand() % colors->size; - - void* t = colors->data[i]; - colors->data[i] = colors->data[j]; - colors->data[j] = t; - } -#endif - return colors; -} - -int arm64_save_var2(scf_dag_node_t* dn, scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_variable_t* v = dn->var; - scf_rela_t* rela = NULL; - scf_arm64_OpCode_t* mov; - scf_instruction_t* inst; - - int size = arm64_variable_size(v); - int is_float = scf_variable_float(v); - - assert(size == r->bytes); - - if (scf_variable_const(v)) { - scf_logw("const literal var: v_%s_%d_%d not save\n", v->w->text->data, v->w->line, v->w->pos); - goto end; - } - - // if temp var in register, alloc it in stack - if (0 == v->bp_offset && !v->global_flag && !v->local_flag) { - - int tmp = f->local_vars_size; - tmp += size; - - if (tmp & 0x7) - tmp = (tmp + 7) >> 3 << 3; - - v->bp_offset = -tmp; - v->tmp_flag = 1; - - f->local_vars_size = tmp; - } - -#if 1 - if (v->w) - scf_logw("save var: v_%d_%d/%s, ", v->w->line, v->w->pos, v->w->text->data); - else - scf_logw("save var: v_%#lx, ", 0xffff & (uintptr_t)v); - printf("size: %d, bp_offset: %d, r: %s\n", size, v->bp_offset, r->name); -#endif - - int ret = arm64_make_inst_G2M(c, f, r, NULL, v); - if (ret < 0) - return ret; - -end: - // if this var is function argment, it become a normal local var - v->arg_flag = 0; - dn->color = -1; - dn->loaded = 0; - - scf_vector_del(r->dag_nodes, dn); - return 0; -} - -int arm64_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - if (dn->color <= 0) - return -EINVAL; - - scf_register_arm64_t* r = arm64_find_register_color(dn->color); - - return arm64_save_var2(dn, r, c, f); -} - -int arm64_save_reg(scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f) -{ - int i = 0; - while (i < r->dag_nodes->size) { - - scf_dag_node_t* dn = r->dag_nodes->data[i]; - - int ret = arm64_save_var(dn, c, f); - if (ret < 0) { - scf_loge("i: %d, size: %d, r: %s, dn->var: %s\n", i, r->dag_nodes->size, r->name, dn->var->w->text->data); - return ret; - } - } - - return 0; -} - -int arm64_overflow_reg(scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f) -{ - int i; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r2 = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r2->id - || SCF_ARM64_REG_FP == r2->id - || SCF_ARM64_REG_LR == r2->id) - continue; - - if (!ARM64_COLOR_CONFLICT(r->color, r2->color)) - continue; - - int ret = arm64_save_reg(r2, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - r->used = 1; - return 0; -} - -int arm64_overflow_reg2(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_register_arm64_t* r2; - scf_dag_node_t* dn2; - - int i; - int j; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - r2 = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r2->id - || SCF_ARM64_REG_FP == r2->id - || SCF_ARM64_REG_LR == r2->id) - continue; - - if (!ARM64_COLOR_CONFLICT(r->color, r2->color)) - continue; - - for (j = 0; j < r2->dag_nodes->size; ) { - dn2 = r2->dag_nodes->data[j]; - - if (dn2 == dn) { - j++; - continue; - } - - int ret = arm64_save_var(dn2, c, f); - if (ret < 0) - return ret; - } - } - - r->used = 1; - return 0; -} - -static int _arm64_overflow_reg3(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_register_arm64_t* r2; - scf_dn_status_t* ds2; - scf_dag_node_t* dn2; - - int i; - int j; - int ret; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - r2 = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r2->id - || SCF_ARM64_REG_FP == r2->id - || SCF_ARM64_REG_LR == r2->id) - continue; - - if (!ARM64_COLOR_CONFLICT(r->color, r2->color)) - continue; - - for (j = 0; j < r2->dag_nodes->size; ) { - dn2 = r2->dag_nodes->data[j]; - - if (dn2 == dn) { - j++; - continue; - } - - ds2 = scf_vector_find_cmp(c->active_vars, dn2, scf_dn_status_cmp); - if (!ds2) { - j++; - continue; - } - - if (!ds2->active) { - j++; - continue; - } -#if 1 - scf_variable_t* v = dn->var; - scf_variable_t* v2 = dn2->var; - if (v->w) - scf_loge("v_%d_%d/%s, bp_offset: %d\n", v->w->line, v->w->pos, v->w->text->data, v->bp_offset); - else - scf_loge("v_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v, v->bp_offset); - - if (v2->w) - scf_loge("v2_%d_%d/%s, bp_offset: %d\n", v2->w->line, v2->w->pos, v2->w->text->data, v2->bp_offset); - else - scf_loge("v2_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v2, v2->bp_offset); -#endif - int ret = arm64_save_var(dn2, c, f); - if (ret < 0) - return ret; - } - } - - r->used = 1; - return 0; -} - -int arm64_reg_used(scf_register_arm64_t* r, scf_dag_node_t* dn) -{ - scf_register_arm64_t* r2; - scf_dag_node_t* dn2; - - int i; - int j; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - r2 = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r2->id - || SCF_ARM64_REG_FP == r2->id - || SCF_ARM64_REG_LR == r2->id) - continue; - - if (!ARM64_COLOR_CONFLICT(r->color, r2->color)) - continue; - - for (j = 0; j < r2->dag_nodes->size; j++) { - dn2 = r2->dag_nodes->data[j]; - - if (dn2 != dn) - return 1; - } - } - return 0; -} - -static scf_register_arm64_t* _arm64_reg_cached_min_vars(scf_register_arm64_t** regs, int nb_regs) -{ - scf_register_arm64_t* r_min = NULL; - - int min = 0; - int i; - - for (i = 0; i < nb_regs; i++) { - scf_register_arm64_t* r = regs[i]; - - int nb_vars = arm64_reg_cached_vars(r); - - if (!r_min) { - r_min = r; - min = nb_vars; - continue; - } - - if (min > nb_vars) { - r_min = r; - min = nb_vars; - } - } - - return r_min; -} - -scf_register_arm64_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float) -{ - scf_vector_t* neighbors = NULL; - scf_graph_node_t* gn = NULL; - - scf_register_arm64_t* free_regs[sizeof(arm64_registers) / sizeof(arm64_registers[0])]; - - int nb_free_regs = 0; - int bytes = 8; - int ret; - int i; - int j; - - assert(c->rcg); - - if (dn) { - is_float = scf_variable_float(dn->var); - bytes = arm64_variable_size (dn->var); - } - - ret = arm64_rcg_find_node(&gn, c->rcg, dn, NULL); - if (ret < 0) - neighbors = c->rcg->nodes; - else - neighbors = gn->neighbors; - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (r->bytes < bytes || ARM64_COLOR_TYPE(r->color) != is_float) - continue; - - for (j = 0; j < neighbors->size; j++) { - - scf_graph_node_t* neighbor = neighbors->data[j]; - arm64_rcg_node_t* rn = neighbor->data; - - if (rn->dag_node) { - if (rn->dag_node->color <= 0) - continue; - - if (ARM64_COLOR_CONFLICT(r->color, rn->dag_node->color)) - break; - } else { - assert(rn->reg); - - if (ARM64_COLOR_CONFLICT(r->color, rn->reg->color)) - break; - } - } - - if (j == neighbors->size) - free_regs[nb_free_regs++] = r; - } - - if (nb_free_regs > 0) - return _arm64_reg_cached_min_vars(free_regs, nb_free_regs); - - for (i = 0; i < sizeof(arm64_registers) / sizeof(arm64_registers[0]); i++) { - - scf_register_arm64_t* r = &(arm64_registers[i]); - - if (SCF_ARM64_REG_SP == r->id - || SCF_ARM64_REG_FP == r->id - || SCF_ARM64_REG_LR == r->id) - continue; - - if (r->bytes < bytes || ARM64_COLOR_TYPE(r->color) != is_float) - continue; - - if (c->dsts) { - scf_3ac_operand_t* dst; - - for (j = 0; j < c->dsts->size; j++) { - dst = c->dsts->data[j]; - - if (dst->dag_node && dst->dag_node->color > 0 - && ARM64_COLOR_CONFLICT(r->color, dst->dag_node->color)) - break; - } - - if (j < c->dsts->size) - continue; - } - - if (c->srcs) { - scf_3ac_operand_t* src; - - for (j = 0; j < c->srcs->size; j++) { - src = c->srcs->data[j]; - - if (src->dag_node && src->dag_node->color > 0 - && ARM64_COLOR_CONFLICT(r->color, src->dag_node->color)) - break; - } - - if (j < c->srcs->size) - continue; - } - - return r; - } - - return NULL; -} - -static int _arm64_load_reg_const(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_instruction_t* inst; - scf_arm64_OpCode_t* lea; - scf_arm64_OpCode_t* mov; - - scf_variable_t* v = dn->var; - - r->used = 1; - - int size = arm64_variable_size(v); - - if (SCF_FUNCTION_PTR == v->type) { - - assert(v->func_ptr); - assert(v->const_literal_flag); - - v->global_flag = 1; - v->local_flag = 0; - v->tmp_flag = 0; - - return arm64_make_inst_ADR2G(c, f, r, v); - - } else if (v->nb_dimentions > 0) { - assert(v->const_literal_flag); - - return arm64_make_inst_ADR2G(c, f, r, v); - } - - return arm64_make_inst_I2G(c, r, v->data.u64, size); -} - -int arm64_load_reg(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) -{ - if (dn->loaded) - return 0; - - scf_arm64_OpCode_t* mov; - scf_instruction_t* inst; - scf_rela_t* rela = NULL; - - int is_float = scf_variable_float(dn->var); - int var_size = arm64_variable_size(dn->var); - - r->used = 1; - - if (!is_float) { - - if (scf_variable_const(dn->var)) { - - int ret = _arm64_load_reg_const(r, dn, c, f); - if (ret < 0) - return ret; - - dn->loaded = 1; - return 0; - } - - if (!dn->var->global_flag && !dn->var->local_flag && !dn->var->tmp_flag) - return 0; - - if (scf_variable_const_string(dn->var)) { - - int ret = arm64_make_inst_ISTR2G(c, f, r, dn->var); - if (ret < 0) - return ret; - - dn->loaded = 1; - return 0; - } - - if (0 == dn->var->bp_offset && !dn->var->global_flag) { - scf_loge("\n"); - return -EINVAL; - } - - if ((dn->var->nb_dimentions > 0 && dn->var->const_literal_flag) - || (dn->var->type >= SCF_STRUCT && 0 == dn->var->nb_pointers)) { - - int ret = arm64_make_inst_ADR2G(c, f, r, dn->var); - if (ret < 0) - return ret; - - dn->loaded = 1; - return 0; - } - - int ret = arm64_make_inst_M2G(c, f, r, NULL, dn->var); - if (ret < 0) - return ret; - - dn->loaded = 1; - return 0; - } - - if (!dn->var->global_flag && !dn->var->local_flag && !dn->var->tmp_flag) - return 0; - - if (0 == dn->var->bp_offset && !dn->var->global_flag) { - scf_loge("\n"); - return -EINVAL; - } - - int ret = arm64_make_inst_M2GF(c, f, r, NULL, dn->var); - if (ret < 0) - return ret; - - dn->loaded = 1; - return 0; -} - -int arm64_select_reg(scf_register_arm64_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag) -{ - if (0 == dn->color) - return -EINVAL; - - scf_register_arm64_t* r; - - int ret; - int is_float = scf_variable_float(dn->var); - int var_size = arm64_variable_size(dn->var); - - if (dn->color > 0) { - r = arm64_find_register_color(dn->color); -#if 1 - ret = _arm64_overflow_reg3(r, dn, c, f); - if (ret < 0) { - scf_loge("\n"); - return -1; - } -#endif - } else { - r = arm64_select_overflowed_reg(dn, c, is_float); - if (!r) { - scf_loge("\n"); - return -1; - } - - ret = arm64_overflow_reg(r, c, f); - if (ret < 0) { - scf_loge("overflow reg failed\n"); - return ret; - } - assert(0 == r->dag_nodes->size); - - r = arm64_find_register_type_id_bytes(is_float, r->id, var_size); - assert(0 == r->dag_nodes->size); - - dn->color = r->color; - } - - ret = scf_vector_add_unique(r->dag_nodes, dn); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (load_flag) { - ret = arm64_load_reg(r, dn, c, f); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } else - dn->loaded = 1; - - r->used = 1; - *preg = r; - return 0; -} - -int arm64_select_free_reg(scf_register_arm64_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float) -{ - scf_register_arm64_t* r; - - r = arm64_select_overflowed_reg(NULL, c, is_float); - if (!r) { - scf_loge("\n"); - return -1; - } - - int ret = arm64_overflow_reg(r, c, f); - if (ret < 0) { - scf_loge("overflow reg failed\n"); - return ret; - } - assert(0 == r->dag_nodes->size); - - r = arm64_find_register_type_id_bytes(0, r->id, 8); - assert(0 == r->dag_nodes->size); - - ret = arm64_rcg_make(c, c->rcg, NULL, r); - if (ret < 0) - return ret; - - r->used = 1; - - *preg = r; - return 0; -} - -int arm64_dereference_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_register_arm64_t* rb = NULL; - scf_variable_t* vb = base->var; - - scf_logw("base->color: %ld\n", base->color); - - int ret = arm64_select_reg(&rb, base, c, f, 1); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - scf_logw("base->color: %ld\n", base->color); - - if (vb->nb_pointers + vb->nb_dimentions > 1 || vb->type >= SCF_STRUCT) - sib->size = 8; - else { - sib->size = vb->data_size; - assert(8 >= vb->data_size); - } - - sib->base = rb; - sib->index = NULL; - sib->scale = 0; - sib->disp = 0; - return 0; -} - -int arm64_pointer_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_variable_t* vb = base ->var; - scf_variable_t* vm = member->var; - scf_register_arm64_t* rb = NULL; - scf_instruction_t* inst; - - int ret; - int32_t disp = 0; - - if (vb->nb_pointers > 0 && 0 == vb->nb_dimentions) { - - ret = arm64_select_reg(&rb, base, c, f, 1); - if (ret < 0) - return ret; - - } else if (vb->local_flag) { - - rb = arm64_find_register("fp"); - disp = vb->bp_offset; - - } else if (vb->global_flag) { - - ret = arm64_select_reg(&rb, base, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_ADR2G(c, f, rb, vb); - if (ret < 0) - return ret; - - } else { - ret = arm64_select_reg(&rb, base, c, f, 0); - if (ret < 0) - return ret; - } - - disp += vm->offset; - - sib->base = rb; - sib->index = NULL; - sib->scale = 0; - sib->disp = disp; - sib->size = arm64_variable_size(vm); - return 0; -} - -int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_dag_node_t* scale, scf_3ac_code_t* c, scf_function_t* f) -{ - scf_variable_t* vb = base ->var; - scf_variable_t* vi = index->var; - - scf_register_arm64_t* rb = NULL; - scf_register_arm64_t* ri = NULL; - scf_register_arm64_t* rs = NULL; - scf_register_arm64_t* rd = NULL; - - scf_arm64_OpCode_t* xor; - scf_arm64_OpCode_t* add; - scf_arm64_OpCode_t* shl; - scf_arm64_OpCode_t* lea; - scf_arm64_OpCode_t* mov; - scf_instruction_t* inst; - - int ret; - int i; - - uint32_t opcode; - int32_t disp = 0; - - if (vb->nb_pointers > 0 && 0 == vb->nb_dimentions) { - - ret = arm64_select_reg(&rb, base, c, f, 1); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } else if (vb->local_flag) { - - rb = arm64_find_register("fp"); - disp = vb->bp_offset; - - } else if (vb->global_flag) { - scf_rela_t* rela = NULL; - - if (0 == base->color) - base->color = -1; - - ret = arm64_select_reg(&rb, base, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - opcode = (0x90 << 24) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vb, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rb->id << 5) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vb, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - } else { - ret = arm64_select_reg(&rb, base, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - int32_t s = scale->var->data.i; - assert(s > 0); - - if (vb->nb_pointers + vb->nb_dimentions > 1 || vb->type >= SCF_STRUCT) - sib->size = 8; - else { - sib->size = vb->data_size; - assert(8 >= vb->data_size); - } - - if (0 == index->color) { - disp += vi->data.i * s; - - sib->base = rb; - sib->index = NULL; - sib->scale = 0; - sib->disp = disp; - return 0; - } - - ret = arm64_select_reg(&ri, index, c, f, 1); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - scf_register_arm64_t* ri2 = arm64_find_register_color_bytes(ri->color, 8); - - if (ri->bytes < ri2->bytes) { - - if (scf_variable_signed(index->var)) { - - opcode = (0x93 << 24) | (0x1 << 22) | (0x1f << 10) | (ri->id << 5) | ri->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - ri = ri2; - } - - if (1 != s - && 2 != s - && 4 != s - && 8 != s) { - - assert(8 == scale->var->size); - - ret = arm64_select_reg(&rs, scale, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - opcode = (0xd2 << 24) | (0x1 << 23) | ((s & 0xffff) << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - opcode = (0xf2 << 24) | (0x1 << 23) | (((s >> 16) & 0xffff) << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - scf_logw("s: %d\n", s); - - opcode = (0x9b << 24) | (ri->id << 16) | (0x1f << 10) | (rs->id << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - ri = rs; - s = 1; - } - - if (disp != 0) { - - if (!rs) { - ret = arm64_select_reg(&rs, scale, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - if (disp > 0 && disp <= 0xfff) - opcode = (0x91 << 24) | (disp << 10) | (rb->id << 5) | rs->id; - - else if (disp < 0 && -disp <= 0xfff) - opcode = (0xd1 << 24) | ((-disp) << 10) | (rb->id << 5) | rs->id; - - else { - ret = arm64_make_inst_I2G(c, rs, disp, 4); - if (ret < 0) - return ret; - - opcode = (0x8b << 24) | (rb->id << 16) | (rs->id << 5) | rs->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - } else { - assert(1 == s); - - if (disp > 0 && disp <= 0xfff) - opcode = (0x91 << 24) | (disp << 10) | (rs->id << 5) | rs->id; - - else if (disp < 0 && -disp <= 0xfff) - opcode = (0xd1 << 24) | ((-disp) << 10) | (rs->id << 5) | rs->id; - - else { - ret = arm64_select_free_reg(&rd, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, rd, disp, 4); - if (ret < 0) - return ret; - - opcode = (0x8b << 24) | (rd->id << 16) | (rs->id << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - opcode = (0x8b << 24) | (rb->id << 16) | (rs->id << 5) | rs->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - ri = NULL; - } - - rb = rs; - } - - sib->base = rb; - sib->index = ri; - sib->scale = s; - sib->disp = 0; - return 0; -} - -void arm64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c) -{ - scf_3ac_operand_t* src = NULL; - scf_dag_node_t* dn = NULL; - - int nfloats = 0; - int nints = 0; - int i; - - for (i = 1; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - dn = src->dag_node; - - int is_float = scf_variable_float(dn->var); - int size = arm64_variable_size (dn->var); - - if (is_float) { - if (nfloats < ARM64_ABI_NB) - dn->rabi2 = arm64_find_register_type_id_bytes(is_float, arm64_abi_float_regs[nfloats++], size); - else - dn->rabi2 = NULL; - } else { - if (nints < ARM64_ABI_NB) - dn->rabi2 = arm64_find_register_type_id_bytes(is_float, arm64_abi_regs[nints++], size); - else - dn->rabi2 = NULL; - } - - src->rabi = dn->rabi2; - } - - if (p_nints) - *p_nints = nints; - - if (p_nfloats) - *p_nfloats = nfloats; -} - diff --git a/native/arm64/scf_arm64_reg.h b/native/arm64/scf_arm64_reg.h deleted file mode 100644 index d23872d..0000000 --- a/native/arm64/scf_arm64_reg.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef SCF_ARM64_REG_H -#define SCF_ARM64_REG_H - -#include"scf_native.h" -#include"scf_arm64_util.h" - -#define ARM64_COLOR(type, id, mask) ((type) << 24 | (id) << 16 | (mask)) -#define ARM64_COLOR_TYPE(c) ((c) >> 24) -#define ARM64_COLOR_ID(c) (((c) >> 16) & 0xff) -#define ARM64_COLOR_MASK(c) ((c) & 0xffff) -#define ARM64_COLOR_CONFLICT(c0, c1) ( (c0) >> 16 == (c1) >> 16 && (c0) & (c1) & 0xffff ) - -#define ARM64_COLOR_BYTES(c) \ - ({ \ - int n = 0;\ - intptr_t minor = (c) & 0xffff; \ - while (minor) { \ - minor &= minor - 1; \ - n++;\ - } \ - n;\ - }) - -#define ARM64_SELECT_REG_CHECK(pr, dn, c, f, load_flag) \ - do {\ - int ret = arm64_select_reg(pr, dn, c, f, load_flag); \ - if (ret < 0) { \ - scf_loge("\n"); \ - return ret; \ - } \ - assert(dn->color > 0); \ - } while (0) - -// ABI: rdi rsi rdx rcx r8 r9 -static uint32_t arm64_abi_regs[] = -{ - SCF_ARM64_REG_X0, - SCF_ARM64_REG_X1, - SCF_ARM64_REG_X2, - SCF_ARM64_REG_X3, - SCF_ARM64_REG_X4, - SCF_ARM64_REG_X5, - SCF_ARM64_REG_X6, - SCF_ARM64_REG_X7, -}; - -static uint32_t arm64_abi_float_regs[] = -{ - SCF_ARM64_REG_D0, - SCF_ARM64_REG_D1, - SCF_ARM64_REG_D2, - SCF_ARM64_REG_D3, - SCF_ARM64_REG_D4, - SCF_ARM64_REG_D5, - SCF_ARM64_REG_D6, - SCF_ARM64_REG_D7, -}; -#define ARM64_ABI_NB (sizeof(arm64_abi_regs) / sizeof(arm64_abi_regs[0])) - -static uint32_t arm64_abi_ret_regs[] = -{ - SCF_ARM64_REG_X0, - SCF_ARM64_REG_X1, - SCF_ARM64_REG_X2, - SCF_ARM64_REG_X3, -}; -#define ARM64_ABI_RET_NB (sizeof(arm64_abi_ret_regs) / sizeof(arm64_abi_ret_regs[0])) - -static uint32_t arm64_abi_caller_saves[] = -{ - SCF_ARM64_REG_X0, - SCF_ARM64_REG_X1, - SCF_ARM64_REG_X2, - SCF_ARM64_REG_X3, - SCF_ARM64_REG_X4, - SCF_ARM64_REG_X5, - SCF_ARM64_REG_X6, - SCF_ARM64_REG_X7, - - SCF_ARM64_REG_X9, - SCF_ARM64_REG_X10, - SCF_ARM64_REG_X11, - SCF_ARM64_REG_X12, - SCF_ARM64_REG_X13, - SCF_ARM64_REG_X14, - SCF_ARM64_REG_X15, -}; -#define ARM64_ABI_CALLER_SAVES_NB (sizeof(arm64_abi_caller_saves) / sizeof(arm64_abi_caller_saves[0])) - -static uint32_t arm64_abi_callee_saves[] = -{ - SCF_ARM64_REG_X19, - SCF_ARM64_REG_X20, - SCF_ARM64_REG_X21, - SCF_ARM64_REG_X22, - SCF_ARM64_REG_X23, - SCF_ARM64_REG_X24, - SCF_ARM64_REG_X25, - SCF_ARM64_REG_X26, - SCF_ARM64_REG_X27, - SCF_ARM64_REG_X28, - SCF_ARM64_REG_X29, - SCF_ARM64_REG_X30, -}; -#define ARM64_ABI_CALLEE_SAVES_NB (sizeof(arm64_abi_callee_saves) / sizeof(arm64_abi_callee_saves[0])) - -typedef struct { - uint32_t id; - int bytes; - char* name; - - intptr_t color; - - scf_vector_t* dag_nodes; - - uint32_t updated; - uint32_t used; -} scf_register_arm64_t; - -typedef struct { - scf_register_arm64_t* base; - scf_register_arm64_t* index; - - int32_t scale; - int32_t disp; - int32_t size; -} arm64_sib_t; - -static inline int arm64_variable_size(scf_variable_t* v) -{ - if (v->nb_dimentions > 0) - return 8; - - if (v->type >= SCF_STRUCT && 0 == v->nb_pointers) - return 8; - - return v->size < 4 ? 4 : v->size; -} - -typedef int (*arm64_sib_fill_pt)(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_registers_init(); -int arm64_registers_reset(); -void arm64_registers_clear(); -scf_vector_t* arm64_register_colors(); - -scf_register_arm64_t* arm64_find_register(const char* name); - -scf_register_arm64_t* arm64_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes); - -scf_register_arm64_t* arm64_find_register_color(intptr_t color); - -scf_register_arm64_t* arm64_find_register_color_bytes(intptr_t color, int bytes); - -scf_register_arm64_t* arm64_find_abi_register(int index, int bytes); - -scf_register_arm64_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float); - -int arm64_reg_cached_vars(scf_register_arm64_t* r); - -int arm64_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_save_var2(scf_dag_node_t* dn, scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_push_regs(scf_vector_t* instructions, uint32_t* regs, int nb_regs); -int arm64_pop_regs(scf_3ac_code_t* c, scf_register_arm64_t** regs, int nb_regs, scf_register_arm64_t** updated_regs, int nb_updated); - -int arm64_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_arm64_t** saved_regs); - -int arm64_save_reg(scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_load_reg(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); -int arm64_reg_used(scf_register_arm64_t* r, scf_dag_node_t* dn); - -int arm64_overflow_reg (scf_register_arm64_t* r, scf_3ac_code_t* c, scf_function_t* f); -int arm64_overflow_reg2(scf_register_arm64_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_select_reg(scf_register_arm64_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag); - -int arm64_select_free_reg(scf_register_arm64_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float); - -int arm64_dereference_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_pointer_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f); - -int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_dag_node_t* scale, scf_3ac_code_t* c, scf_function_t* f); - -void arm64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c); - - -static inline int arm64_inst_data_is_reg(scf_inst_data_t* id) -{ - scf_register_t* fp = (scf_register_t*)arm64_find_register("fp"); - scf_register_t* sp = (scf_register_t*)arm64_find_register("sp"); - - if (!id->flag && id->base && id->base != sp && id->base != fp && 0 == id->imm_size) - return 1; - return 0; -} - -static inline int arm64_inst_data_is_local(scf_inst_data_t* id) -{ - scf_register_t* fp = (scf_register_t*)arm64_find_register("fp"); - scf_register_t* sp = (scf_register_t*)arm64_find_register("sp"); - - if (id->flag && (id->base == fp || id->base == sp)) - return 1; - return 0; -} - -static inline int arm64_inst_data_is_global(scf_inst_data_t* id) -{ - if (id->flag && !id->base) - return 1; - return 0; -} - -static inline int arm64_inst_data_is_const(scf_inst_data_t* id) -{ - if (!id->flag && id->imm_size > 0) - return 1; - return 0; -} - -#endif - diff --git a/native/arm64/scf_arm64_util.c b/native/arm64/scf_arm64_util.c deleted file mode 100644 index b52b974..0000000 --- a/native/arm64/scf_arm64_util.c +++ /dev/null @@ -1,844 +0,0 @@ -#include"scf_arm64.h" - -scf_instruction_t* arm64_make_inst(scf_3ac_code_t* c, uint32_t opcode) -{ - scf_instruction_t* inst; - - inst = calloc(1, sizeof(scf_instruction_t)); - if (!inst) - return NULL; - - inst->c = c; - inst->code[0] = opcode & 0xff; - inst->code[1] = (opcode >> 8) & 0xff; - inst->code[2] = (opcode >> 16) & 0xff; - inst->code[3] = (opcode >> 24) & 0xff; - inst->len = 4; - - return inst; -} - -int arm64_make_inst_I2G(scf_3ac_code_t* c, scf_register_arm64_t* rd, uint64_t imm, int bytes) -{ - scf_instruction_t* inst; - - uint64_t invert = ~imm; - uint32_t opcode; - - if (0 == (invert >> 32)) { - - // movn rd, invert[15:0] - opcode = (0x92 << 24) | (0x1 << 23) | ((invert & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if (invert >> 16) { - // movk rd, imm[31:16] - opcode = (0xf2 << 24) | (0x1 << 23) | (0x1 << 21) | (((imm >> 16) & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - return 0; - } - - // mov rd, imm[15:0] - opcode = (0xd2 << 24) | (0x1 << 23) | ((imm & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - if ((imm >> 16) & 0xffff) { - - // movk rd, imm[31:16] - opcode = (0xf2 << 24) | (0x1 << 23) | (0x1 << 21) | (((imm >> 16) & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - if (8 == bytes) { - - if ((imm >> 32) & 0xffff) { - - // movk rd, imm[47:32] - opcode = (0xf2 << 24) | (0x1 << 23) | (0x2 << 21) | (((imm >> 32) & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - - if ((imm >> 48) & 0xffff) { - - // movk rd, imm[63:48] - opcode = (0xf2 << 24) | (0x1 << 23) | (0x3 << 21) | (((imm >> 48) & 0xffff) << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } - } - - return 0; -} - -int arm64_make_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_variable_t* vs) -{ - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - int64_t offset; - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - int size = arm64_variable_size(vs); - - if (vs->local_flag || vs->tmp_flag) { - - offset = vs->bp_offset; - - if (offset >= 0 && offset <= 0xfff) - - opcode = (0x91 << 24) | (offset << 10) | (fp->id << 5) | rd->id; - - else if (offset < 0 && -offset <= 0xfff) - - opcode = (0xd1 << 24) | ((-offset) << 10) | (fp->id << 5) | rd->id; - - else { - int ret = arm64_make_inst_I2G(c, rd, offset, 8); - if (ret < 0) - return ret; - - opcode = (0x8b << 24) | (fp->id << 16) | (rd->id << 5) | rd->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - } else if (vs->global_flag) { - offset = 0; - - opcode = (0x90 << 24) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - } else { - scf_loge("temp var should give a register\n"); - return -EINVAL; - } - - return 0; -} - -int arm64_make_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, scf_variable_t* vs) -{ - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_register_arm64_t* ri = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - int32_t offset; - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - int size = arm64_variable_size(vs); - - if (!rb) { - if (vs->local_flag || vs->tmp_flag) { - - offset = vs->bp_offset; - rb = fp; - - } else if (vs->global_flag) { - offset = 0; - - opcode = (0x90 << 24) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - rb = rd; - - } else { - scf_loge("temp var should give a register\n"); - return -EINVAL; - } - - } else { - if (vs->local_flag || vs->tmp_flag) - offset = vs->bp_offset; - else - offset = vs->offset; - } - - if (1 == size) { - S = 0; - SIZE = 0; - - } else if (2 == size) { - - if (offset & 0x1) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 1; - SIZE = 1; - - } else if (4 == size) { - - if (offset & 0x3) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 2; - SIZE = 2; - - } else if (8 == size) { - - if (offset & 0x7) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 3; - SIZE = 3; - } else - return -EINVAL; - - - if (offset >= 0 && offset < 0xfff) - opcode = (0x39 << 24) | (offset << 10); - - else if (offset < 0 && offset >= -0xff) - opcode = (0x38 << 24) | ((offset & 0x1ff) << 12); - - else { - int ret = arm64_select_free_reg(&ri, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return -EINVAL; - } - - ret = arm64_make_inst_I2G(c, ri, offset, 4); - if (ret < 0) - return ret; - - opcode = (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10); - } - - if (rd->bytes > size && scf_variable_signed(vs)) - opcode |= 0x2 << 22; - else - opcode |= 0x1 << 22; - - opcode |= (SIZE << 30) | (rb->id << 5) | rd->id; - - opcode |= ARM64_COLOR_TYPE(rd->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -int arm64_make_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rs, scf_register_arm64_t* rb, scf_variable_t* vs) -{ - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_register_arm64_t* ri = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - int32_t offset; - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - int size = arm64_variable_size(vs); - - if (!rb) { - if (vs->local_flag || vs->tmp_flag) { - - offset = vs->bp_offset; - rb = fp; - - } else if (vs->global_flag) { - offset = 0; - - int ret = arm64_select_free_reg(&rb, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return -EINVAL; - } - - opcode = (0x90 << 24) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rb->id << 5) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - } else { - scf_loge("temp var should give a register\n"); - return -EINVAL; - } - - } else { - if (vs->local_flag || vs->tmp_flag) - offset = vs->bp_offset; - else - offset = vs->offset; - } - - if (1 == size) { - S = 0; - SIZE = 0; - - } else if (2 == size) { - - if (offset & 0x1) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 1; - SIZE = 1; - - } else if (4 == size) { - - if (offset & 0x3) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 2; - SIZE = 2; - - } else if (8 == size) { - - if (offset & 0x7) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 3; - SIZE = 3; - - } else - return -EINVAL; - - if (offset >= 0 && offset < 0xfff) - - opcode = (SIZE << 30) | (0x39 << 24) | (offset << 10) | (rb->id << 5) | rs->id; - - else if (offset < 0 && offset >= -0xff) - - opcode = (SIZE << 30) | (0x38 << 24) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rs->id; - - else { - int ret = arm64_select_free_reg(&ri, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return -EINVAL; - } - - ret = arm64_make_inst_I2G(c, ri, offset, 4); - if (ret < 0) - return ret; - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; - } - - opcode |= ARM64_COLOR_TYPE(rs->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -int arm64_make_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_variable_t* v) -{ - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - int size1 = arm64_variable_size(v); - - assert(8 == rd->bytes); - assert(8 == size1); - - v->global_flag = 1; - v->local_flag = 0; - v->tmp_flag = 0; - - uint32_t opcode; - - opcode = (0x90 << 24) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rd->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - return 0; -} - -int arm64_make_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rs, scf_register_arm64_t* rb, int32_t offset, int size) -{ - scf_register_arm64_t* ri = NULL; - scf_instruction_t* inst = NULL; - - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - if (!rb) - return -EINVAL; - - if (1 == size) { - S = 0; - SIZE = 0; - - } else if (2 == size) { - - if (offset & 0x1) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 1; - SIZE = 1; - - } else if (4 == size) { - - if (offset & 0x3) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 2; - SIZE = 2; - - } else if (8 == size) { - - if (offset & 0x7) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 3; - SIZE = 3; - - } else - return -EINVAL; - - if (offset >= 0 && offset < 0xfff) - - opcode = (SIZE << 30) | (0x39 << 24) | (offset << 10) | (rb->id << 5) | rs->id; - - else if (offset < 0 && offset >= -0xff) - - opcode = (SIZE << 30) | (0x38 << 24) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rs->id; - - else { - int ret = arm64_select_free_reg(&ri, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return -EINVAL; - } - - ret = arm64_make_inst_I2G(c, ri, offset, 4); - if (ret < 0) - return ret; - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; - } - - opcode |= ARM64_COLOR_TYPE(rs->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -int arm64_make_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, int32_t offset, int size) -{ - scf_register_arm64_t* ri = NULL; - scf_instruction_t* inst = NULL; - - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - if (!rb) - return -EINVAL; - - if (1 == size) { - S = 0; - SIZE = 0; - - } else if (2 == size) { - - if (offset & 0x1) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 1; - SIZE = 1; - - } else if (4 == size) { - - if (offset & 0x3) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 2; - SIZE = 2; - - } else if (8 == size) { - - if (offset & 0x7) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 3; - SIZE = 3; - - } else - return -EINVAL; - - if (offset >= 0 && offset < 0xfff) - - opcode = (SIZE << 30) | (0x39 << 24) | (0x1 << 22) | (offset << 10) | (rb->id << 5) | rd->id; - - else if (offset < 0 && offset >= -0xff) - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rd->id; - - else { - int ret = arm64_select_free_reg(&ri, c, f, 0); - if (ret < 0) { - scf_loge("\n"); - return -EINVAL; - } - - ret = arm64_make_inst_I2G(c, ri, offset, 4); - if (ret < 0) - return ret; - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rd->id; - } - - opcode |= ARM64_COLOR_TYPE(rd->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -int arm64_make_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, int32_t offset) -{ - scf_register_arm64_t* r = NULL; - scf_instruction_t* inst = NULL; - - uint32_t opcode = 0; - uint32_t u24i = 0x91; - uint32_t u24r = 0x8b; - - if (offset < 0) { - offset = -offset; - u24i = 0xd1; - u24r = 0xcb; - } - - if (offset <= 0xfff) - opcode = (u24i << 24) | (offset << 10) | (rd->id << 5) | rd->id; - - else if (0 == (offset & 0xfff) && (offset >> 12) <= 0xfff) - - opcode = (u24i << 24) | (0x1 << 22) | ((offset >> 12) << 10) | (rd->id << 5) | rd->id; - - else { - int ret = arm64_select_free_reg(&r, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, r, offset, 4); - if (ret < 0) - return ret; - - opcode = (u24r << 24) | (r->id << 16) | (rd->id << 5) | rd->id; - } - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -int arm64_make_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, arm64_sib_t* sib) -{ - scf_register_arm64_t* rb = sib->base; - scf_register_arm64_t* ri = sib->index; - scf_instruction_t* inst = NULL; - - assert(0 == sib->disp); - - if (!rb || !ri) - return -EINVAL; - - uint32_t opcode; - uint32_t SH; - - if (1 == sib->scale) - SH = 0; - - else if (2 == sib->scale) - SH = 1; - - else if (4 == sib->scale) - SH = 2; - - else if (8 == sib->scale) - SH = 3; - else - return -EINVAL; - - opcode = (0x8b << 24) | (ri->id << 16) | (SH << 10) | (rb->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; -} - -int arm64_make_inst_SIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, arm64_sib_t* sib) -{ - scf_register_arm64_t* rb = sib->base; - scf_register_arm64_t* ri = sib->index; - scf_instruction_t* inst = NULL; - - assert(0 == sib->disp); - - if (!rb || !ri) - return -EINVAL; - - int scale = sib->scale; - int size = sib->size; - - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - if (1 == scale) - S = 0; - - - if (1 == size) - SIZE = 0; - - else if (2 == size) - SIZE = 1; - - else if (4 == size) - SIZE = 2; - - else if (8 == size) - SIZE = 3; - else - return -EINVAL; - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rd->id; - - opcode |= ARM64_COLOR_TYPE(rd->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -int arm64_make_inst_G2SIB(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rs, arm64_sib_t* sib) -{ - scf_register_arm64_t* rb = sib->base; - scf_register_arm64_t* ri = sib->index; - scf_instruction_t* inst = NULL; - - assert(0 == sib->disp); - - if (!rb || !ri) - return -EINVAL; - - int scale = sib->scale; - int size = sib->size; - - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - if (1 == scale) - S = 0; - - - if (1 == size) - SIZE = 0; - - else if (2 == size) - SIZE = 1; - - else if (4 == size) - SIZE = 2; - - else if (8 == size) - SIZE = 3; - else - return -EINVAL; - - opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; - - opcode |= ARM64_COLOR_TYPE(rs->color) << 26; - - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} - -int arm64_make_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64_t* rd, scf_register_arm64_t* rb, scf_variable_t* vs) -{ - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_register_arm64_t* ro = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; - - int32_t offset; - uint32_t opcode; - uint32_t SIZE = 0; - uint32_t S = 1; - - int size = arm64_variable_size(vs); - - if (!rb) { - if (vs->local_flag || vs->tmp_flag) { - - offset = vs->bp_offset; - rb = fp; - - } else if (vs->global_flag) { - offset = 0; - - int ret = arm64_select_free_reg(&rb, c, f, 0); - if (ret < 0) - return ret; - - opcode = (0x90 << 24) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADR_PREL_PG_HI21; - - opcode = (0x91 << 24) | (rb->id << 5) | rb->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); - rela->type = R_AARCH64_ADD_ABS_LO12_NC; - - } else { - scf_loge("temp var should give a register\n"); - return -EINVAL; - } - - } else { - if (vs->local_flag || vs->tmp_flag) - offset = vs->bp_offset; - else - offset = vs->offset; - } - - if (1 == size) { - S = 0; - SIZE = 0; - - } else if (2 == size) { - - if (offset & 0x1) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 1; - SIZE = 1; - - } else if (4 == size) { - - if (offset & 0x3) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 2; - SIZE = 2; - - } else if (8 == size) { - - if (offset & 0x7) { - scf_loge("memory align error\n"); - return -EINVAL; - } - - offset >> 3; - SIZE = 3; - } else - return -EINVAL; - - - if (offset >= 0 && offset < 0xfff) - opcode = (0x3d << 24) | (0x1 << 22) | (offset << 10); - - else if (offset < 0 && offset >= -0xff) - opcode = (0x3c << 24) | (0x1 << 22) | ((offset & 0x1ff) << 12); - - else { - int ret = arm64_select_free_reg(&ro, c, f, 0); - if (ret < 0) - return ret; - - ret = arm64_make_inst_I2G(c, ro, offset, 4); - if (ret < 0) - return ret; - - opcode = (0x3c << 24) | (0x1 << 22) | (0x1 << 21) | (ro->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10); - } - - opcode |= (SIZE << 30) | (rb->id << 5) | rd->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - - return 0; -} diff --git a/native/arm64/scf_arm64_util.h b/native/arm64/scf_arm64_util.h deleted file mode 100644 index b1809cf..0000000 --- a/native/arm64/scf_arm64_util.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef SCF_ARM64_UTIL_H -#define SCF_ARM64_UTIL_H - -#include"scf_def.h" - -enum scf_arm64_OpCode_types { - SCF_ARM64_MOV = 0, - - SCF_ARM64_MOVSX, - SCF_ARM64_MOVZX, - - SCF_ARM64_MOVS, - SCF_ARM64_STOS, - - SCF_ARM64_LEA, - - SCF_ARM64_PUSH, - SCF_ARM64_POP, - - SCF_ARM64_INC, - SCF_ARM64_DEC, - - // 10 - SCF_ARM64_XOR, - SCF_ARM64_AND, - SCF_ARM64_OR, - SCF_ARM64_NOT, - - SCF_ARM64_NEG, - - // 15 - SCF_ARM64_CALL, - SCF_ARM64_RET, - - SCF_ARM64_ADD, - SCF_ARM64_SUB, - - SCF_ARM64_MUL, - SCF_ARM64_DIV, - - // 21 - SCF_ARM64_IMUL, - SCF_ARM64_IDIV, - - // sign-extend ax to dx:ax - SCF_ARM64_CBW, - SCF_ARM64_CWD = SCF_ARM64_CBW, - SCF_ARM64_CDQ = SCF_ARM64_CBW, - SCF_ARM64_CQO = SCF_ARM64_CBW, - - // 24 - SCF_ARM64_SAR, - SCF_ARM64_SHR, - SCF_ARM64_SHL, - - SCF_ARM64_CMP, - SCF_ARM64_TEST, - - SCF_ARM64_SETZ, - SCF_ARM64_SETNZ, - - // 31 - SCF_ARM64_SETG, - SCF_ARM64_SETGE, - - SCF_ARM64_SETL, - SCF_ARM64_SETLE, - - SCF_ARM64_ADDSS, - SCF_ARM64_ADDSD, - - SCF_ARM64_SUBSS, - SCF_ARM64_SUBSD, - - SCF_ARM64_MULSS, - SCF_ARM64_MULSD, - - // 41 - SCF_ARM64_DIVSS, - SCF_ARM64_DIVSD, - - SCF_ARM64_MOVSS, - SCF_ARM64_MOVSD, - - SCF_ARM64_UCOMISS, - SCF_ARM64_UCOMISD, - - // 47 - SCF_ARM64_CVTSI2SD, - SCF_ARM64_CVTSI2SS, - - SCF_ARM64_CVTSS2SD, - SCF_ARM64_CVTSD2SS, - - SCF_ARM64_CVTTSD2SI, - SCF_ARM64_CVTTSS2SI, - - SCF_ARM64_PXOR, - - SCF_ARM64_JZ, - SCF_ARM64_JNZ, - - SCF_ARM64_JG, - SCF_ARM64_JGE, - - SCF_ARM64_JL, - SCF_ARM64_JLE, - - SCF_ARM64_JA, - SCF_ARM64_JAE, - - SCF_ARM64_JB, - SCF_ARM64_JBE, - - SCF_ARM64_JMP, - - SCF_ARM64_NB -}; - -enum scf_x64_REGs { - SCF_ARM64_REG_W0 = 0, - SCF_ARM64_REG_X0 = 0, - SCF_ARM64_REG_S0 = 0, - SCF_ARM64_REG_D0 = 0, - - SCF_ARM64_REG_W1 = 1, - SCF_ARM64_REG_X1 = 1, - SCF_ARM64_REG_S1 = 1, - SCF_ARM64_REG_D1 = 1, - - SCF_ARM64_REG_W2 = 2, - SCF_ARM64_REG_X2 = 2, - SCF_ARM64_REG_S2 = 2, - SCF_ARM64_REG_D2 = 2, - - SCF_ARM64_REG_W3 = 3, - SCF_ARM64_REG_X3 = 3, - SCF_ARM64_REG_S3 = 3, - SCF_ARM64_REG_D3 = 3, - - SCF_ARM64_REG_W4 = 4, - SCF_ARM64_REG_X4 = 4, - SCF_ARM64_REG_S4 = 4, - SCF_ARM64_REG_D4 = 4, - - SCF_ARM64_REG_W5 = 5, - SCF_ARM64_REG_X5 = 5, - SCF_ARM64_REG_S5 = 5, - SCF_ARM64_REG_D5 = 5, - - SCF_ARM64_REG_W6 = 6, - SCF_ARM64_REG_X6 = 6, - SCF_ARM64_REG_S6 = 6, - SCF_ARM64_REG_D6 = 6, - - SCF_ARM64_REG_W7 = 7, - SCF_ARM64_REG_X7 = 7, - SCF_ARM64_REG_S7 = 7, - SCF_ARM64_REG_D7 = 7, - - SCF_ARM64_REG_W8 = 8, - SCF_ARM64_REG_X8 = 8, - - SCF_ARM64_REG_W9 = 9, - SCF_ARM64_REG_X9 = 9, - - SCF_ARM64_REG_W10 = 10, - SCF_ARM64_REG_X10 = 10, - - SCF_ARM64_REG_W11 = 11, - SCF_ARM64_REG_X11 = 11, - - SCF_ARM64_REG_W12 = 12, - SCF_ARM64_REG_X12 = 12, - - SCF_ARM64_REG_W13 = 13, - SCF_ARM64_REG_X13 = 13, - - SCF_ARM64_REG_W14 = 14, - SCF_ARM64_REG_X14 = 14, - - SCF_ARM64_REG_W15 = 15, - SCF_ARM64_REG_X15 = 15, - - SCF_ARM64_REG_W16 = 16, - SCF_ARM64_REG_X16 = 16, - - SCF_ARM64_REG_W17 = 17, - SCF_ARM64_REG_X17 = 17, - - SCF_ARM64_REG_W18 = 18, - SCF_ARM64_REG_X18 = 18, - - SCF_ARM64_REG_W19 = 19, - SCF_ARM64_REG_X19 = 19, - - SCF_ARM64_REG_W20 = 20, - SCF_ARM64_REG_X20 = 20, - - SCF_ARM64_REG_W21 = 21, - SCF_ARM64_REG_X21 = 21, - - SCF_ARM64_REG_W22 = 22, - SCF_ARM64_REG_X22 = 22, - - SCF_ARM64_REG_W23 = 23, - SCF_ARM64_REG_X23 = 23, - - SCF_ARM64_REG_W24 = 24, - SCF_ARM64_REG_X24 = 24, - - SCF_ARM64_REG_W25 = 25, - SCF_ARM64_REG_X25 = 25, - - SCF_ARM64_REG_W26 = 26, - SCF_ARM64_REG_X26 = 26, - - SCF_ARM64_REG_W27 = 27, - SCF_ARM64_REG_X27 = 27, - - SCF_ARM64_REG_W28 = 28, - SCF_ARM64_REG_X28 = 28, - - SCF_ARM64_REG_X29 = 29, - SCF_ARM64_REG_FP = 29, - - SCF_ARM64_REG_X30 = 30, - SCF_ARM64_REG_LR = 30, - - SCF_ARM64_REG_SP = 31, -}; - -enum scf_x64_EG_types { - SCF_ARM64_G = 0, - SCF_ARM64_I = 1, - SCF_ARM64_G2E = 2, - SCF_ARM64_E2G = 3, - SCF_ARM64_I2E = 4, - SCF_ARM64_I2G = 5, - SCF_ARM64_E = 6, -}; - -#endif - diff --git a/native/risc/scf_arm64.c b/native/risc/scf_arm64.c new file mode 100644 index 0000000..d72007b --- /dev/null +++ b/native/risc/scf_arm64.c @@ -0,0 +1,1609 @@ +#include"scf_risc.h" + +int arm64_inst_I2G(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes) +{ + scf_instruction_t* inst; + + uint64_t invert = ~imm; + uint32_t opcode; + + if (0 == (invert >> 32)) { + + // movn rd, invert[15:0] + opcode = (0x92 << 24) | (0x1 << 23) | ((invert & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (invert >> 16) { + // movk rd, imm[31:16] + opcode = (0xf2 << 24) | (0x1 << 23) | (0x1 << 21) | (((imm >> 16) & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + return 0; + } + + // mov rd, imm[15:0] + opcode = (0xd2 << 24) | (0x1 << 23) | ((imm & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if ((imm >> 16) & 0xffff) { + + // movk rd, imm[31:16] + opcode = (0xf2 << 24) | (0x1 << 23) | (0x1 << 21) | (((imm >> 16) & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + if (8 == bytes) { + + if ((imm >> 32) & 0xffff) { + + // movk rd, imm[47:32] + opcode = (0xf2 << 24) | (0x1 << 23) | (0x2 << 21) | (((imm >> 32) & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + if ((imm >> 48) & 0xffff) { + + // movk rd, imm[63:48] + opcode = (0xf2 << 24) | (0x1 << 23) | (0x3 << 21) | (((imm >> 48) & 0xffff) << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + } + + return 0; +} + +int arm64_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int64_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + int size = risc_variable_size(vs); + + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + + if (offset >= 0 && offset <= 0xfff) + + opcode = (0x91 << 24) | (offset << 10) | (fp->id << 5) | rd->id; + + else if (offset < 0 && -offset <= 0xfff) + + opcode = (0xd1 << 24) | ((-offset) << 10) | (fp->id << 5) | rd->id; + + else { + int ret = arm64_inst_I2G(c, rd, offset, 8); + if (ret < 0) + return ret; + + opcode = (0x8b << 24) | (fp->id << 16) | (rd->id << 5) | rd->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else if (vs->global_flag) { + offset = 0; + + opcode = (0x90 << 24) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0x91 << 24) | (rd->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + return 0; +} + +int arm64_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + int size = risc_variable_size(vs); + + if (!rb) { + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + rb = fp; + + } else if (vs->global_flag) { + offset = 0; + + opcode = (0x90 << 24) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0x91 << 24) | (rd->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + rb = rd; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + } else { + if (vs->local_flag || vs->tmp_flag) + offset = vs->bp_offset; + else + offset = vs->offset; + } + + if (1 == size) { + S = 0; + SIZE = 0; + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + } else + return -EINVAL; + + + if (offset >= 0 && offset < 0xfff) + opcode = (0x39 << 24) | (offset << 10); + + else if (offset < 0 && offset >= -0xff) + opcode = (0x38 << 24) | ((offset & 0x1ff) << 12); + + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm64_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10); + } + + if (rd->bytes > size && scf_variable_signed(vs)) + opcode |= 0x2 << 22; + else + opcode |= 0x1 << 22; + + opcode |= (SIZE << 30) | (rb->id << 5) | rd->id; + + opcode |= RISC_COLOR_TYPE(rd->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm64_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + int size = risc_variable_size(vs); + + if (!rb) { + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + rb = fp; + + } else if (vs->global_flag) { + offset = 0; + + int ret = risc_select_free_reg(&rb, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm64_inst_ADR2G(c, f, rb, vs); + if (ret < 0) + return -EINVAL; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + } else { + if (vs->local_flag || vs->tmp_flag) + offset = vs->bp_offset; + else + offset = vs->offset; + } + + if (1 == size) { + S = 0; + SIZE = 0; + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= 0 && offset < 0xfff) + + opcode = (SIZE << 30) | (0x39 << 24) | (offset << 10) | (rb->id << 5) | rs->id; + + else if (offset < 0 && offset >= -0xff) + + opcode = (SIZE << 30) | (0x38 << 24) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rs->id; + + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm64_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; + } + + opcode |= RISC_COLOR_TYPE(rs->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm64_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* v) +{ + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int size1 = risc_variable_size(v); + + assert(8 == rd->bytes); + assert(8 == size1); + + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + + uint32_t opcode; + + opcode = (0x90 << 24) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0x91 << 24) | (rd->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + return 0; +} + +int arm64_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size) +{ + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + if (!rb) + return -EINVAL; + + if (1 == size) { + S = 0; + SIZE = 0; + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= 0 && offset < 0xfff) + + opcode = (SIZE << 30) | (0x39 << 24) | (offset << 10) | (rb->id << 5) | rs->id; + + else if (offset < 0 && offset >= -0xff) + + opcode = (SIZE << 30) | (0x38 << 24) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rs->id; + + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm64_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; + } + + opcode |= RISC_COLOR_TYPE(rs->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm64_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size) +{ + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + if (!rb) + return -EINVAL; + + if (1 == size) { + S = 0; + SIZE = 0; + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= 0 && offset < 0xfff) + + opcode = (SIZE << 30) | (0x39 << 24) | (0x1 << 22) | (offset << 10) | (rb->id << 5) | rd->id; + + else if (offset < 0 && offset >= -0xff) + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | ((offset & 0x1ff) << 12) | (rb->id << 5) | rd->id; + + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm64_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rd->id; + } + + opcode |= RISC_COLOR_TYPE(rd->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm64_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset) +{ + scf_register_t* r = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode = 0; + uint32_t u24i = 0x91; + uint32_t u24r = 0x8b; + + if (offset < 0) { + offset = -offset; + u24i = 0xd1; + u24r = 0xcb; + } + + if (offset <= 0xfff) + opcode = (u24i << 24) | (offset << 10) | (rd->id << 5) | rd->id; + + else if (0 == (offset & 0xfff) && (offset >> 12) <= 0xfff) + + opcode = (u24i << 24) | (0x1 << 22) | ((offset >> 12) << 10) | (rd->id << 5) | rd->id; + + else { + int ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + ret = arm64_inst_I2G(c, r, offset, 4); + if (ret < 0) + return ret; + + opcode = (u24r << 24) | (r->id << 16) | (rd->id << 5) | rd->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm64_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + uint32_t opcode; + uint32_t SH; + + if (1 == sib->scale) + SH = 0; + + else if (2 == sib->scale) + SH = 1; + + else if (4 == sib->scale) + SH = 2; + + else if (8 == sib->scale) + SH = 3; + else + return -EINVAL; + + opcode = (0x8b << 24) | (ri->id << 16) | (SH << 10) | (rb->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm64_inst_SIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + int scale = sib->scale; + int size = sib->size; + + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + if (1 == scale) + S = 0; + + + if (1 == size) + SIZE = 0; + + else if (2 == size) + SIZE = 1; + + else if (4 == size) + SIZE = 2; + + else if (8 == size) + SIZE = 3; + else + return -EINVAL; + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rd->id; + + opcode |= RISC_COLOR_TYPE(rd->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm64_inst_G2SIB(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + int scale = sib->scale; + int size = sib->size; + + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + if (1 == scale) + S = 0; + + + if (1 == size) + SIZE = 0; + + else if (2 == size) + SIZE = 1; + + else if (4 == size) + SIZE = 2; + + else if (8 == size) + SIZE = 3; + else + return -EINVAL; + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 21) | (ri->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10) | (rb->id << 5) | rs->id; + + opcode |= RISC_COLOR_TYPE(rs->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm64_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* ro = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + int size = risc_variable_size(vs); + + if (!rb) { + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + rb = fp; + + } else if (vs->global_flag) { + offset = 0; + + int ret = risc_select_free_reg(&rb, c, f, 0); + if (ret < 0) + return ret; + + opcode = (0x90 << 24) | rb->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0x91 << 24) | (rb->id << 5) | rb->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + } else { + if (vs->local_flag || vs->tmp_flag) + offset = vs->bp_offset; + else + offset = vs->offset; + } + + if (1 == size) { + S = 0; + SIZE = 0; + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + } else + return -EINVAL; + + + if (offset >= 0 && offset < 0xfff) + opcode = (0x3d << 24) | (0x1 << 22) | (offset << 10); + + else if (offset < 0 && offset >= -0xff) + opcode = (0x3c << 24) | (0x1 << 22) | ((offset & 0x1ff) << 12); + + else { + int ret = risc_select_free_reg(&ro, c, f, 0); + if (ret < 0) + return ret; + + ret = arm64_inst_I2G(c, ro, offset, 4); + if (ret < 0) + return ret; + + opcode = (0x3c << 24) | (0x1 << 22) | (0x1 << 21) | (ro->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 10); + } + + opcode |= (SIZE << 30) | (rb->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +scf_instruction_t* arm64_inst_PUSH(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf8 << 24) | (0x1f8 << 12) | (0x3 << 10) | (0x1f << 5) | r->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_POP(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf8 << 24) | (0x1 << 22) | (0x8 << 12) | (0x1 << 10) | (0x1f << 5) | r->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_RET(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xd65f03c0; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MOV_SP(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x91 << 24) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MVN(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xaa << 24) | (0x1 << 21) | (rs->id << 16) | (0x1f << 10) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FMOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | ((8 == rd->bytes) << 22) | (0x1 << 21) | (0x1 << 14) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MOVSX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (1 == size) + S = 0x7; + else if (2 == size) + S = 0xf; + else if (4 == size) + S = 0x1f; + else + return NULL; + + opcode = (0x93 << 24) | (0x1 << 22) | (S << 10) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MOVZX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (1 == size) + S = 0x7; + else if (2 == size) + S = 0xf; + else + return NULL; + + opcode = (0x53 << 24) | (S << 10) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (0x3 << 14) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTSD2SS(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = (0x1e << 24) | (0x1 << 22) | (0x1 << 21) | (0x1 << 17) | (0x1 << 14) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTF2SI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = ((8 == rd->bytes) << 31) | (0x1e << 24) | ((8 == rs->bytes) << 22) | (0x7 << 19) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTF2UI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = ((8 == rd->bytes) << 31) | (0x1e << 24) | ((8 == rs->bytes) << 22) | (0x7 << 19) | (rs->id << 5) | rd->id; + opcode |= 1 << 16; + + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTSI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (rs->id << 5) | rd->id; + opcode |= ((8 == rs->bytes) << 31) | ((8 == rd->bytes) << 22); + + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CVTUI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 17) | (rs->id << 5) | rd->id; + opcode |= ((8 == rs->bytes) << 31) | ((8 == rd->bytes) << 22); + opcode |= 1 << 16; + + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SUB_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t sh = 0; + + if (imm > 0xfff) { + + if (0 == (imm & 0xfff) && (imm >> 12) <= 0xfff) { + imm >>= 12; + sh = 1; + } else { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + } + + opcode = (0x51 << 24) | (sh << 22) | (imm << 10) | (rs->id << 5) | rd->id; + opcode |= (8 == rd->bytes) << 31; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CMP_IMM(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t sh = 0; + + if (imm > 0xfff) { + + if (0 == (imm & 0xfff) && (imm >> 12) <= 0xfff) { + imm >>= 12; + sh = 1; + } else { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + } + + opcode = (0x71 << 24) | (sh << 22) | (imm << 10) | (rs->id << 5) | 0x1f; + opcode |= (8 == rs->bytes) << 31; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_ADD_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t sh = 0; + + if (imm > 0xfff) { + + if (0 == (imm & 0xfff) && (imm >> 12) <= 0xfff) { + imm >>= 12; + sh = 1; + } else { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + } + + opcode = (0x91 << 24) | (sh << 22) | (imm << 10) | (rs->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_ADD_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x8b << 24) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SHL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x9a << 24) | (0x3 << 22) | (0x1 << 13) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SHR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x9a << 24) | (0x3 << 22) | (0x1 << 13) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= 0x1 << 10; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_ASR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x9a << 24) | (0x3 << 22) | (0x1 << 13) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= 0x1 << 11; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_AND_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x8a << 24) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_OR_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xaa << 24) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SUB_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rs0->bytes) << 31) | (0x4b << 24) | (rs1->id << 16) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_CMP_G(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rs0->bytes) << 31) | (0x6b << 24) | (rs1->id << 16) | (rs0->id << 5) | 0x1f; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FCMP(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 13); + opcode |= (rs1->id << 16) | (rs0->id << 5); + opcode |= ((8 == rs0->bytes) << 22); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_NEG(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rd->bytes) << 31) | (0x4b << 24) | (rs->id << 16) | (0x1f << 10) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_TEQ(scf_3ac_code_t* c, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rs->bytes) << 31) | (0x6a << 24) | (rs->id << 16) | (rs->id << 5) | 0x1f; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FADD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 13) | (0x1 << 11); + opcode |= (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= (8 == rd->bytes) << 22; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x7 << 11); + opcode |= (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= ((8 == rd->bytes) << 22); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x9b << 24) | (rs1->id << 16) | (0x1f << 10) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FMUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x1 << 11); + opcode |= (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= ((8 == rd->bytes) << 22); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_FDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1e << 24) | (0x1 << 21) | (0x3 << 11); + opcode |= (rs1->id << 16) | (rs0->id << 5) | rd->id; + opcode |= ((8 == rd->bytes) << 22); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_DIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rs0->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs1->id << 16) | (0x2 << 10) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == rs0->bytes) << 31) | (0x1a << 24) | (0x3 << 22) | (rs1->id << 16) | (0x3 << 10) | (rs0->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = ((8 == ra->bytes) << 31) | (0x1b << 24) | (rm->id << 16) | (0x1 << 15) | (ra->id << 10) | (rn->id << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_BL(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x25 << 26; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_BLR(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xd63f << 16) | (r->id << 5); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_SETZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 1; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm64_inst_SETNZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm64_inst_SETGT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xd; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm64_inst_SETGE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xb; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm64_inst_SETLT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xa; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm64_inst_SETLE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xc; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JMP(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x14000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x54000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JNZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x54000001; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JGT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x5400000c; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JGE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x5400000a; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JLT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x5400000b; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JLE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x5400000d; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm64_inst_JA(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm64_inst_JB(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm64_inst_JAE(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm64_inst_JBE(scf_3ac_code_t* c) +{ + return NULL; +} + +void risc_set_jmp_offset(scf_instruction_t* inst, int32_t bytes) +{ + if (0x54 == inst->code[3]) { + + if (bytes >= 0 && bytes < (0x1 << 20)) { + bytes >>= 2; + bytes <<= 5; + + } else if (bytes < 0 && bytes > -(0x1 << 20)) { + + bytes >>= 2; + bytes &= 0x7ffff; + bytes <<= 5; + } else + assert(0); + + inst->code[0] |= 0xff & bytes; + inst->code[1] |= 0xff & (bytes >> 8); + inst->code[2] |= 0xff & (bytes >> 16); + + } else { + assert(0x14 == inst->code[3]); + + bytes >>= 2; + + assert(bytes < (0x1 << 26) && bytes > -(0x1 << 26)); + + inst->code[0] |= 0xff & bytes; + inst->code[1] |= 0xff & (bytes >> 8); + inst->code[2] |= 0xff & (bytes >> 16); + inst->code[3] |= 0x3 & (bytes >> 24); + } +} + +scf_inst_ops_t inst_ops_arm64 = +{ + .name = "arm64", + + .BL = arm64_inst_BL, + .BLR = arm64_inst_BLR, + .PUSH = arm64_inst_PUSH, + .POP = arm64_inst_POP, + .TEQ = arm64_inst_TEQ, + .NEG = arm64_inst_NEG, + + .MOVZX = arm64_inst_MOVZX, + .MOVSX = arm64_inst_MOVSX, + .MVN = arm64_inst_MVN, + .MOV_G = arm64_inst_MOV_G, + .MOV_SP = arm64_inst_MOV_SP, + + .ADD_G = arm64_inst_ADD_G, + .ADD_IMM = arm64_inst_ADD_IMM, + .SUB_G = arm64_inst_SUB_G, + .SUB_IMM = arm64_inst_SUB_IMM, + .CMP_G = arm64_inst_CMP_G, + .CMP_IMM = arm64_inst_CMP_IMM, + .AND_G = arm64_inst_AND_G, + .OR_G = arm64_inst_OR_G, + + .MUL = arm64_inst_MUL, + .DIV = arm64_inst_DIV, + .SDIV = arm64_inst_SDIV, + .MSUB = arm64_inst_MSUB, + + .SHL = arm64_inst_SHL, + .SHR = arm64_inst_SHR, + .ASR = arm64_inst_ASR, + + .CVTSS2SD = arm64_inst_CVTSS2SD, + .CVTSD2SS = arm64_inst_CVTSD2SS, + .CVTF2SI = arm64_inst_CVTF2SI, + .CVTF2UI = arm64_inst_CVTF2UI, + .CVTSI2F = arm64_inst_CVTSI2F, + .CVTUI2F = arm64_inst_CVTUI2F, + + .FCMP = arm64_inst_FCMP, + .FADD = arm64_inst_FADD, + .FSUB = arm64_inst_FSUB, + .FMUL = arm64_inst_FMUL, + .FDIV = arm64_inst_FDIV, + .FMOV_G = arm64_inst_FMOV_G, + + .JA = arm64_inst_JA, + .JB = arm64_inst_JB, + .JZ = arm64_inst_JZ, + .JNZ = arm64_inst_JNZ, + .JGT = arm64_inst_JGT, + .JGE = arm64_inst_JGE, + .JLT = arm64_inst_JLT, + .JLE = arm64_inst_JLE, + .JAE = arm64_inst_JAE, + .JBE = arm64_inst_JBE, + .JMP = arm64_inst_JMP, + .RET = arm64_inst_RET, + + .SETZ = arm64_inst_SETZ, + .SETNZ = arm64_inst_SETNZ, + .SETGT = arm64_inst_SETGT, + .SETGE = arm64_inst_SETGE, + .SETLT = arm64_inst_SETLT, + .SETLE = arm64_inst_SETLE, + + .I2G = arm64_inst_I2G, + .M2G = arm64_inst_M2G, + .M2GF = arm64_inst_M2GF, + .G2M = arm64_inst_G2M, + .G2P = arm64_inst_G2P, + .P2G = arm64_inst_P2G, + .ISTR2G = arm64_inst_ISTR2G, + .SIB2G = arm64_inst_SIB2G, + .G2SIB = arm64_inst_G2SIB, + .ADR2G = arm64_inst_ADR2G, + .ADRP2G = arm64_inst_ADRP2G, + .ADRSIB2G = arm64_inst_ADRSIB2G, + + .set_jmp_offset = risc_set_jmp_offset, +}; + diff --git a/native/arm64/scf_arm64.c b/native/risc/scf_risc.c similarity index 65% rename from native/arm64/scf_arm64.c rename to native/risc/scf_risc.c index 5fcb403..05617b1 100644 --- a/native/arm64/scf_arm64.c +++ b/native/risc/scf_risc.c @@ -1,34 +1,56 @@ -#include"scf_arm64.h" +#include"scf_risc.h" #include"scf_elf.h" #include"scf_basic_block.h" #include"scf_3ac.h" -extern scf_native_ops_t native_ops_arm64; +extern scf_inst_ops_t inst_ops_arm64; -int scf_arm64_open(scf_native_t* ctx) +static scf_inst_ops_t* inst_ops_array[] = { - scf_arm64_context_t* arm64 = calloc(1, sizeof(scf_arm64_context_t)); - if (!arm64) + &inst_ops_arm64, + + NULL +}; + +int scf_risc_open(scf_native_t* ctx, const char* arch) +{ + scf_inst_ops_t* iops = NULL; + + int i; + for (i = 0; inst_ops_array[i]; i++) { + + if (!strcmp(inst_ops_array[i]->name, arch)) { + iops = inst_ops_array[i]; + break; + } + } + + if (!iops) + return -EINVAL; + + scf_risc_context_t* risc = calloc(1, sizeof(scf_risc_context_t)); + if (!risc) return -ENOMEM; - ctx->priv = arm64; + ctx->iops = iops; + ctx->priv = risc; return 0; } -int scf_arm64_close(scf_native_t* ctx) +int scf_risc_close(scf_native_t* ctx) { - scf_arm64_context_t* arm64 = ctx->priv; + scf_risc_context_t* risc = ctx->priv; - if (arm64) { - arm64_registers_clear(); + if (risc) { + risc_registers_clear(); - free(arm64); - arm64 = NULL; + free(risc); + risc = NULL; } return 0; } -static void _arm64_argv_rabi(scf_function_t* f) +static void _risc_argv_rabi(scf_function_t* f) { scf_variable_t* v; @@ -36,7 +58,7 @@ static void _arm64_argv_rabi(scf_function_t* f) f->args_float = 0; int bp_int = -8; - int bp_floats = -8 - (int)ARM64_ABI_NB * 8; + int bp_floats = -8 - (int)RISC_ABI_NB * 8; int bp_others = 16; int i; @@ -49,21 +71,21 @@ static void _arm64_argv_rabi(scf_function_t* f) } int is_float = scf_variable_float(v); - int size = arm64_variable_size(v); + int size = risc_variable_size(v); if (is_float) { - if (f->args_float < ARM64_ABI_NB) { + if (f->args_float < RISC_ABI_NB) { - v->rabi = arm64_find_register_type_id_bytes(is_float, arm64_abi_float_regs[f->args_float], size); + v->rabi = risc_find_register_type_id_bytes(is_float, risc_abi_float_regs[f->args_float], size); v->bp_offset = bp_floats; bp_floats -= 8; f->args_float++; continue; } - } else if (f->args_int < ARM64_ABI_NB) { + } else if (f->args_int < RISC_ABI_NB) { - v->rabi = arm64_find_register_type_id_bytes(is_float, arm64_abi_regs[f->args_int], size); + v->rabi = risc_find_register_type_id_bytes(is_float, risc_abi_regs[f->args_int], size); v->bp_offset = bp_int; bp_int -= 8; f->args_int++; @@ -76,11 +98,11 @@ static void _arm64_argv_rabi(scf_function_t* f) } } -static int _arm64_function_init(scf_function_t* f, scf_vector_t* local_vars) +static int _risc_function_init(scf_function_t* f, scf_vector_t* local_vars) { scf_variable_t* v; - int ret = arm64_registers_init(); + int ret = risc_registers_init(); if (ret < 0) return ret; @@ -91,9 +113,9 @@ static int _arm64_function_init(scf_function_t* f, scf_vector_t* local_vars) v->bp_offset = 0; } - _arm64_argv_rabi(f); + _risc_argv_rabi(f); - int local_vars_size = 8 + ARM64_ABI_NB * 8 * 2; + int local_vars_size = 8 + RISC_ABI_NB * 8 * 2; for (i = 0; i < local_vars->size; i++) { v = local_vars->data[i]; @@ -119,69 +141,69 @@ static int _arm64_function_init(scf_function_t* f, scf_vector_t* local_vars) return local_vars_size; } -static int _arm64_save_rabi(scf_function_t* f) +static int _risc_save_rabi(scf_function_t* f) { - scf_register_arm64_t* rbp; + scf_register_t* rbp; scf_instruction_t* inst; - scf_arm64_OpCode_t* mov; - - scf_register_arm64_t* rdi; - scf_register_arm64_t* rsi; - scf_register_arm64_t* rdx; - scf_register_arm64_t* rcx; - scf_register_arm64_t* r8; - scf_register_arm64_t* r9; - - scf_register_arm64_t* xmm0; - scf_register_arm64_t* xmm1; - scf_register_arm64_t* xmm2; - scf_register_arm64_t* xmm3; + scf_risc_OpCode_t* mov; + + scf_register_t* rdi; + scf_register_t* rsi; + scf_register_t* rdx; + scf_register_t* rcx; + scf_register_t* r8; + scf_register_t* r9; + + scf_register_t* xmm0; + scf_register_t* xmm1; + scf_register_t* xmm2; + scf_register_t* xmm3; #if 0 if (f->vargs_flag) { inst = NULL; - mov = arm64_find_OpCode(SCF_ARM64_MOV, 8,8, SCF_ARM64_G2E); + mov = risc_find_OpCode(SCF_RISC_MOV, 8,8, SCF_RISC_G2E); - rbp = arm64_find_register("rbp"); + rbp = risc_find_register("rbp"); - rdi = arm64_find_register("rdi"); - rsi = arm64_find_register("rsi"); - rdx = arm64_find_register("rdx"); - rcx = arm64_find_register("rcx"); - r8 = arm64_find_register("r8"); - r9 = arm64_find_register("r9"); + rdi = risc_find_register("rdi"); + rsi = risc_find_register("rsi"); + rdx = risc_find_register("rdx"); + rcx = risc_find_register("rcx"); + r8 = risc_find_register("r8"); + r9 = risc_find_register("r9"); -#define ARM64_SAVE_RABI(offset, rabi) \ +#define RISC_SAVE_RABI(offset, rabi) \ do { \ - inst = arm64_make_inst_G2P(mov, rbp, offset, rabi); \ - ARM64_INST_ADD_CHECK(f->init_insts, inst); \ + inst = ctx->iops->G2P(mov, rbp, offset, rabi); \ + RISC_INST_ADD_CHECK(f->init_insts, inst); \ f->init_code_bytes += inst->len; \ } while (0) - ARM64_SAVE_RABI(-8, rdi); - ARM64_SAVE_RABI(-16, rsi); - ARM64_SAVE_RABI(-24, rdx); - ARM64_SAVE_RABI(-32, rcx); - ARM64_SAVE_RABI(-40, r8); - ARM64_SAVE_RABI(-48, r9); + RISC_SAVE_RABI(-8, rdi); + RISC_SAVE_RABI(-16, rsi); + RISC_SAVE_RABI(-24, rdx); + RISC_SAVE_RABI(-32, rcx); + RISC_SAVE_RABI(-40, r8); + RISC_SAVE_RABI(-48, r9); - mov = arm64_find_OpCode(SCF_ARM64_MOVSD, 8,8, SCF_ARM64_G2E); + mov = risc_find_OpCode(SCF_RISC_MOVSD, 8,8, SCF_RISC_G2E); - xmm0 = arm64_find_register("xmm0"); - xmm1 = arm64_find_register("xmm1"); - xmm2 = arm64_find_register("xmm2"); - xmm3 = arm64_find_register("xmm3"); + xmm0 = risc_find_register("xmm0"); + xmm1 = risc_find_register("xmm1"); + xmm2 = risc_find_register("xmm2"); + xmm3 = risc_find_register("xmm3"); - ARM64_SAVE_RABI(-56, xmm0); - ARM64_SAVE_RABI(-64, xmm1); - ARM64_SAVE_RABI(-72, xmm2); - ARM64_SAVE_RABI(-80, xmm3); + RISC_SAVE_RABI(-56, xmm0); + RISC_SAVE_RABI(-64, xmm1); + RISC_SAVE_RABI(-72, xmm2); + RISC_SAVE_RABI(-80, xmm3); } #endif return 0; } -static int _arm64_function_finish(scf_function_t* f) +static int _risc_function_finish(scf_native_t* ctx, scf_function_t* f) { if (!f->init_insts) { f->init_insts = scf_vector_alloc(); @@ -190,27 +212,24 @@ static int _arm64_function_finish(scf_function_t* f) } else scf_vector_clear(f->init_insts, free); - scf_register_arm64_t* sp = arm64_find_register("sp"); - scf_register_arm64_t* fp = arm64_find_register("fp"); - scf_register_arm64_t* r; + scf_register_t* sp = risc_find_register("sp"); + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* r; scf_instruction_t* inst = NULL; uint32_t opcode; if (f->bp_used_flag) { - opcode = (0xf8 << 24) | (0x1f8 << 12) | (0x3 << 10) | (sp->id << 5) | fp->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(f->init_insts, inst); + inst = ctx->iops->PUSH(NULL, fp); + RISC_INST_ADD_CHECK(f->init_insts, inst); f->init_code_bytes = inst->len; - opcode = (0x91 << 24) | (sp->id << 5) | fp->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(f->init_insts, inst); + inst = ctx->iops->MOV_SP(NULL, fp, sp); + RISC_INST_ADD_CHECK(f->init_insts, inst); f->init_code_bytes += inst->len; uint32_t local = f->local_vars_size; - uint32_t sh = 0; if (!(local & 0xf)) local += 8; @@ -224,15 +243,14 @@ static int _arm64_function_finish(scf_function_t* f) return -EINVAL; } - sh = 1; + local <<= 12; } - opcode = (0xd1 << 24) | (sh << 22) | (local << 10) | (sp->id << 5) | sp->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(f->init_insts, inst); + inst = ctx->iops->SUB_IMM(NULL, sp, sp, local); + RISC_INST_ADD_CHECK(f->init_insts, inst); f->init_code_bytes += inst->len; - int ret = _arm64_save_rabi(f); + int ret = _risc_save_rabi(f); if (ret < 0) return ret; @@ -240,29 +258,28 @@ static int _arm64_function_finish(scf_function_t* f) f->init_code_bytes = 0; int i; - for (i = 0; i < ARM64_ABI_CALLEE_SAVES_NB; i++) { + for (i = 0; i < RISC_ABI_CALLEE_SAVES_NB; i++) { - r = arm64_find_register_type_id_bytes(0, arm64_abi_callee_saves[i], 8); + r = risc_find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8); if (!r->used) { - r = arm64_find_register_type_id_bytes(0, arm64_abi_callee_saves[i], 4); + r = risc_find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4); if (!r->used) continue; } - opcode = (0xf8 << 24) | (0x1f8 << 12) | (0x3 << 10) | (sp->id << 5) | r->id; - inst = arm64_make_inst(NULL, opcode); - ARM64_INST_ADD_CHECK(f->init_insts, inst); + inst = ctx->iops->PUSH(NULL, r); + RISC_INST_ADD_CHECK(f->init_insts, inst); f->init_code_bytes += inst->len; } - arm64_registers_clear(); + risc_registers_clear(); return 0; } -static void _arm64_rcg_node_printf(arm64_rcg_node_t* rn) +static void _risc_rcg_node_printf(risc_rcg_node_t* rn) { if (rn->dag_node) { scf_variable_t* v = rn->dag_node->var; @@ -279,21 +296,21 @@ static void _arm64_rcg_node_printf(arm64_rcg_node_t* rn) printf("color: %ld, type: %ld, id: %ld, mask: %ld", rn->dag_node->color, - ARM64_COLOR_TYPE(rn->dag_node->color), - ARM64_COLOR_ID(rn->dag_node->color), - ARM64_COLOR_MASK(rn->dag_node->color)); + RISC_COLOR_TYPE(rn->dag_node->color), + RISC_COLOR_ID(rn->dag_node->color), + RISC_COLOR_MASK(rn->dag_node->color)); } else { scf_logw("v_%#lx, %p,%p, color: %ld, type: %ld, id: %ld, mask: %ld", (uintptr_t)v & 0xffff, v, rn->dag_node, rn->dag_node->color, - ARM64_COLOR_TYPE(rn->dag_node->color), - ARM64_COLOR_ID(rn->dag_node->color), - ARM64_COLOR_MASK(rn->dag_node->color)); + RISC_COLOR_TYPE(rn->dag_node->color), + RISC_COLOR_ID(rn->dag_node->color), + RISC_COLOR_MASK(rn->dag_node->color)); } if (rn->dag_node->color > 0) { - scf_register_arm64_t* r = arm64_find_register_color(rn->dag_node->color); + scf_register_t* r = risc_find_register_color(rn->dag_node->color); printf(", reg: %s\n", r->name); } else { printf("\n"); @@ -301,13 +318,13 @@ static void _arm64_rcg_node_printf(arm64_rcg_node_t* rn) } else if (rn->reg) { scf_logw("r/%s, color: %ld, type: %ld, major: %ld, minor: %ld\n", rn->reg->name, rn->reg->color, - ARM64_COLOR_TYPE(rn->reg->color), - ARM64_COLOR_ID(rn->reg->color), - ARM64_COLOR_MASK(rn->reg->color)); + RISC_COLOR_TYPE(rn->reg->color), + RISC_COLOR_ID(rn->reg->color), + RISC_COLOR_MASK(rn->reg->color)); } } -static void _arm64_inst_printf(scf_3ac_code_t* c) +static void _risc_inst_printf(scf_3ac_code_t* c) { if (!c->instructions) return; @@ -323,7 +340,7 @@ static void _arm64_inst_printf(scf_3ac_code_t* c) printf("\n"); } -static int _arm64_argv_prepare(scf_graph_t* g, scf_basic_block_t* bb, scf_function_t* f) +static int _risc_argv_prepare(scf_graph_t* g, scf_basic_block_t* bb, scf_function_t* f) { scf_graph_node_t* gn; scf_dag_node_t* dn; @@ -348,7 +365,7 @@ static int _arm64_argv_prepare(scf_graph_t* g, scf_basic_block_t* bb, scf_functi if (l == scf_list_sentinel(&f->dag_list_head)) continue; - int ret = _arm64_rcg_make_node(&gn, g, dn, v->rabi); + int ret = _risc_rcg_make_node(&gn, g, dn, v->rabi); if (ret < 0) return ret; @@ -363,7 +380,7 @@ static int _arm64_argv_prepare(scf_graph_t* g, scf_basic_block_t* bb, scf_functi return 0; } -static int _arm64_argv_save(scf_basic_block_t* bb, scf_function_t* f) +static int _risc_argv_save(scf_basic_block_t* bb, scf_function_t* f) { scf_list_t* l; scf_3ac_code_t* c; @@ -391,14 +408,14 @@ static int _arm64_argv_save(scf_basic_block_t* bb, scf_function_t* f) int i; for (i = 0; i < f->argv->size; i++) { - scf_variable_t* v = f->argv->data[i]; + scf_variable_t* v = f->argv->data[i]; assert(v->arg_flag); - scf_dag_node_t* dn; - scf_dag_node_t* dn2; + scf_dag_node_t* dn; + scf_dag_node_t* dn2; scf_dn_status_t* active; - scf_register_arm64_t* rabi; + scf_register_t* rabi; for (l = scf_list_head(&f->dag_list_head); l != scf_list_sentinel(&f->dag_list_head); l = scf_list_next(l)) { @@ -430,14 +447,14 @@ static int _arm64_argv_save(scf_basic_block_t* bb, scf_function_t* f) dn2 = active->dag_node; if (dn2 != dn && dn2->color > 0 - && ARM64_COLOR_CONFLICT(dn2->color, rabi->color)) { + && RISC_COLOR_CONFLICT(dn2->color, rabi->color)) { save_flag = 1; break; } } if (save_flag) { - int ret = arm64_save_var2(dn, rabi, c, f); + int ret = risc_save_var2(dn, rabi, c, f); if (ret < 0) return ret; } else { @@ -452,17 +469,17 @@ static int _arm64_argv_save(scf_basic_block_t* bb, scf_function_t* f) return 0; } -static int _arm64_make_bb_rcg(scf_graph_t* g, scf_basic_block_t* bb, scf_native_t* ctx) +static int _risc_make_bb_rcg(scf_graph_t* g, scf_basic_block_t* bb, scf_native_t* ctx) { scf_list_t* l; scf_3ac_code_t* c; - arm64_rcg_handler_t* h; + risc_rcg_handler_t* h; for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); l = scf_list_next(l)) { c = scf_list_data(l, scf_3ac_code_t, list); - h = scf_arm64_find_rcg_handler(c->op->type); + h = scf_risc_find_rcg_handler(c->op->type); if (!h) { scf_loge("3ac operator '%s' not supported\n", c->op->name); return -EINVAL; @@ -477,17 +494,17 @@ static int _arm64_make_bb_rcg(scf_graph_t* g, scf_basic_block_t* bb, scf_native_ return 0; } -static int _arm64_bb_regs_from_graph(scf_basic_block_t* bb, scf_graph_t* g) +static int _risc_bb_regs_from_graph(scf_basic_block_t* bb, scf_graph_t* g) { int i; for (i = 0; i < g->nodes->size; i++) { scf_graph_node_t* gn = g->nodes->data[i]; - arm64_rcg_node_t* rn = gn->data; + risc_rcg_node_t* rn = gn->data; scf_dag_node_t* dn = rn->dag_node; scf_dn_status_t* ds; if (!dn) { - _arm64_rcg_node_printf(rn); + _risc_rcg_node_printf(rn); continue; } @@ -503,17 +520,17 @@ static int _arm64_bb_regs_from_graph(scf_basic_block_t* bb, scf_graph_t* g) ds->color = gn->color; dn->color = gn->color; - _arm64_rcg_node_printf(rn); + _risc_rcg_node_printf(rn); } printf("\n"); return 0; } -static int _arm64_select_bb_regs(scf_basic_block_t* bb, scf_native_t* ctx) +static int _risc_select_bb_regs(scf_basic_block_t* bb, scf_native_t* ctx) { - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; scf_graph_t* g = scf_graph_alloc(); if (!g) @@ -525,26 +542,26 @@ static int _arm64_select_bb_regs(scf_basic_block_t* bb, scf_native_t* ctx) int i; if (0 == bb->index) { - ret = _arm64_argv_prepare(g, bb, f); + ret = _risc_argv_prepare(g, bb, f); if (ret < 0) goto error; } - ret = _arm64_make_bb_rcg(g, bb, ctx); + ret = _risc_make_bb_rcg(g, bb, ctx); if (ret < 0) goto error; - colors = arm64_register_colors(); + colors = risc_register_colors(); if (!colors) { ret = -ENOMEM; goto error; } - ret = scf_arm64_graph_kcolor(g, 16, colors); + ret = scf_risc_graph_kcolor(g, 16, colors); if (ret < 0) goto error; - ret = _arm64_bb_regs_from_graph(bb, g); + ret = _risc_bb_regs_from_graph(bb, g); error: if (colors) @@ -556,10 +573,10 @@ error: } -static int _arm64_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx) +static int _risc_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx) { - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; scf_graph_t* g = scf_graph_alloc(); if (!g) @@ -572,7 +589,7 @@ static int _arm64_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx) int i; if (0 == bbg->pre->index) { - ret = _arm64_argv_prepare(g, bb, f); + ret = _risc_argv_prepare(g, bb, f); if (ret < 0) goto error; } @@ -580,22 +597,22 @@ static int _arm64_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx) for (i = 0; i < bbg->body->size; i++) { bb = bbg->body->data[i]; - ret = _arm64_make_bb_rcg(g, bb, ctx); + ret = _risc_make_bb_rcg(g, bb, ctx); if (ret < 0) goto error; } - colors = arm64_register_colors(); + colors = risc_register_colors(); if (!colors) { ret = -ENOMEM; goto error; } - ret = scf_arm64_graph_kcolor(g, 16, colors); + ret = scf_risc_graph_kcolor(g, 16, colors); if (ret < 0) goto error; - ret = _arm64_bb_regs_from_graph(bbg->pre, g); + ret = _risc_bb_regs_from_graph(bbg->pre, g); if (ret < 0) goto error; @@ -608,7 +625,7 @@ error: return ret; } -static int _arm64_make_insts_for_list(scf_native_t* ctx, scf_basic_block_t* bb, int bb_offset) +static int _risc_make_insts_for_list(scf_native_t* ctx, scf_basic_block_t* bb, int bb_offset) { scf_3ac_code_t* cmp = NULL; scf_3ac_code_t* c = NULL; @@ -619,7 +636,7 @@ static int _arm64_make_insts_for_list(scf_native_t* ctx, scf_basic_block_t* bb, c = scf_list_data(l, scf_3ac_code_t, list); - arm64_inst_handler_t* h = scf_arm64_find_inst_handler(c->op->type); + risc_inst_handler_t* h = scf_risc_find_inst_handler(c->op->type); if (!h) { scf_loge("3ac operator '%s' not supported\n", c->op->name); return -EINVAL; @@ -636,13 +653,13 @@ static int _arm64_make_insts_for_list(scf_native_t* ctx, scf_basic_block_t* bb, continue; scf_3ac_code_print(c, NULL); - _arm64_inst_printf(c); + _risc_inst_printf(c); } return bb_offset; } -static void _arm64_set_offset_for_jmps(scf_native_t* ctx, scf_function_t* f) +static void _risc_set_offset_for_jmps(scf_native_t* ctx, scf_function_t* f) { int i; @@ -678,40 +695,11 @@ static void _arm64_set_offset_for_jmps(scf_native_t* ctx, scf_function_t* f) assert(0 == (bytes & 0x3)); - if (0x54 == inst->code[3]) { - - if (bytes >= 0 && bytes < (0x1 << 20)) { - bytes >>= 2; - bytes <<= 5; - - } else if (bytes < 0 && bytes > -(0x1 << 20)) { - - bytes >>= 2; - bytes &= 0x7ffff; - bytes <<= 5; - } else - assert(0); - - inst->code[0] |= 0xff & bytes; - inst->code[1] |= 0xff & (bytes >> 8); - inst->code[2] |= 0xff & (bytes >> 16); - - } else { - assert(0x14 == inst->code[3]); - - bytes >>= 2; - - assert(bytes < (0x1 << 26) && bytes > -(0x1 << 26)); - - inst->code[0] |= 0xff & bytes; - inst->code[1] |= 0xff & (bytes >> 8); - inst->code[2] |= 0xff & (bytes >> 16); - inst->code[3] |= 0x3 & (bytes >> 24); - } + ctx->iops->set_jmp_offset(inst, bytes); } } -static void _arm64_set_offset_for_relas(scf_native_t* ctx, scf_function_t* f, scf_vector_t* relas) +static void _risc_set_offset_for_relas(scf_native_t* ctx, scf_function_t* f, scf_vector_t* relas) { int i; for (i = 0; i < relas->size; i++) { @@ -750,7 +738,7 @@ static void _arm64_set_offset_for_relas(scf_native_t* ctx, scf_function_t* f, sc } } -static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) +static int _risc_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) { scf_basic_block_t* pre; scf_basic_block_t* post; @@ -779,13 +767,13 @@ static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) scf_variable_t* v = dn->var; - intptr_t color = arm64_bb_find_color(pre->dn_colors_exit, dn); + intptr_t color = risc_bb_find_color(pre->dn_colors_exit, dn); int updated = 0; for (i = 0; i < bbg->body->size; i++) { bb = bbg->body->data[i]; - intptr_t color2 = arm64_bb_find_color(bb->dn_colors_exit, dn); + intptr_t color2 = risc_bb_find_color(bb->dn_colors_exit, dn); if (color2 != color) updated++; @@ -795,7 +783,7 @@ static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) if (color <= 0) continue; - int ret = arm64_bb_save_dn(color, dn, c, post, f); + int ret = risc_bb_save_dn(color, dn, c, post, f); if (ret < 0) return ret; @@ -812,7 +800,7 @@ static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) src = c2->srcs->data[0]; dn2 = src->dag_node; - ret = arm64_bb_save_dn(color, dn2, c2, bb, f); + ret = risc_bb_save_dn(color, dn2, c2, bb, f); if (ret < 0) return ret; @@ -855,11 +843,11 @@ static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) if (l2 == scf_list_sentinel(&bb->save_list_head)) continue; - intptr_t color = arm64_bb_find_color(bb->dn_colors_exit, dn); + intptr_t color = risc_bb_find_color(bb->dn_colors_exit, dn); if (color <= 0) continue; - int ret = arm64_bb_save_dn(color, dn, c, bb, f); + int ret = risc_bb_save_dn(color, dn, c, bb, f); if (ret < 0) return ret; @@ -872,7 +860,7 @@ static int _arm64_bbg_fix_saves(scf_bb_group_t* bbg, scf_function_t* f) return 0; } -static void _arm64_bbg_fix_loads(scf_bb_group_t* bbg) +static void _risc_bbg_fix_loads(scf_bb_group_t* bbg) { if (0 == bbg->body->size) return; @@ -925,7 +913,7 @@ static void _arm64_bbg_fix_loads(scf_bb_group_t* bbg) } } -static void _arm64_set_offsets(scf_function_t* f) +static void _risc_set_offsets(scf_function_t* f) { scf_instruction_t* inst; scf_basic_block_t* bb; @@ -964,10 +952,10 @@ static void _arm64_set_offsets(scf_function_t* f) } } -int _scf_arm64_select_inst(scf_native_t* ctx) +int _scf_risc_select_inst(scf_native_t* ctx) { - scf_arm64_context_t* arm64 = ctx->priv; - scf_function_t* f = arm64->f; + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; scf_basic_block_t* bb; scf_basic_block_t* end; scf_bb_group_t* bbg; @@ -989,20 +977,20 @@ int _scf_arm64_select_inst(scf_native_t* ctx) continue; } - ret = _arm64_select_bb_regs(bb, ctx); + ret = _risc_select_bb_regs(bb, ctx); if (ret < 0) return ret; - arm64_init_bb_colors(bb); + risc_init_bb_colors(bb); if (0 == bb->index) { - ret = _arm64_argv_save(bb, f); + ret = _risc_argv_save(bb, f); if (ret < 0) return ret; } scf_loge("************ bb: %d, cmp_flag: %d\n", bb->index, bb->cmp_flag); - ret = _arm64_make_insts_for_list(ctx, bb, 0); + ret = _risc_make_insts_for_list(ctx, bb, 0); if (ret < 0) return ret; } @@ -1010,14 +998,14 @@ int _scf_arm64_select_inst(scf_native_t* ctx) for (i = 0; i < f->bb_groups->size; i++) { bbg = f->bb_groups->data[i]; - ret = _arm64_select_bb_group_regs(bbg, ctx); + ret = _risc_select_bb_group_regs(bbg, ctx); if (ret < 0) return ret; - arm64_init_bb_colors(bbg->pre); + risc_init_bb_colors(bbg->pre); if (0 == bbg->pre->index) { - ret = _arm64_argv_save(bbg->pre, f); + ret = _risc_argv_save(bbg->pre, f); if (ret < 0) return ret; } @@ -1029,19 +1017,19 @@ int _scf_arm64_select_inst(scf_native_t* ctx) assert(!bb->native_flag); if (0 != j) { - ret = arm64_load_bb_colors2(bb, bbg, f); + ret = risc_load_bb_colors2(bb, bbg, f); if (ret < 0) return ret; } scf_loge("************ bb: %d, cmp_flag: %d\n", bb->index, bb->cmp_flag); - ret = _arm64_make_insts_for_list(ctx, bb, 0); + ret = _risc_make_insts_for_list(ctx, bb, 0); if (ret < 0) return ret; bb->native_flag = 1; scf_loge("************ bb: %d\n", bb->index); - ret = arm64_save_bb_colors(bb->dn_colors_exit, bbg, bb); + ret = risc_save_bb_colors(bb->dn_colors_exit, bbg, bb); if (ret < 0) return ret; } @@ -1050,23 +1038,23 @@ int _scf_arm64_select_inst(scf_native_t* ctx) for (i = 0; i < f->bb_loops->size; i++) { bbg = f->bb_loops->data[i]; - ret = _arm64_select_bb_group_regs(bbg, ctx); + ret = _risc_select_bb_group_regs(bbg, ctx); if (ret < 0) return ret; - arm64_init_bb_colors(bbg->pre); + risc_init_bb_colors(bbg->pre); if (0 == bbg->pre->index) { - ret = _arm64_argv_save(bbg->pre, f); + ret = _risc_argv_save(bbg->pre, f); if (ret < 0) return ret; } - ret = _arm64_make_insts_for_list(ctx, bbg->pre, 0); + ret = _risc_make_insts_for_list(ctx, bbg->pre, 0); if (ret < 0) return ret; - ret = arm64_save_bb_colors(bbg->pre->dn_colors_exit, bbg, bbg->pre); + ret = risc_save_bb_colors(bbg->pre->dn_colors_exit, bbg, bbg->pre); if (ret < 0) return ret; @@ -1076,47 +1064,47 @@ int _scf_arm64_select_inst(scf_native_t* ctx) assert(!bb->native_flag); - ret = arm64_load_bb_colors(bb, bbg, f); + ret = risc_load_bb_colors(bb, bbg, f); if (ret < 0) return ret; - ret = _arm64_make_insts_for_list(ctx, bb, 0); + ret = _risc_make_insts_for_list(ctx, bb, 0); if (ret < 0) return ret; bb->native_flag = 1; - ret = arm64_save_bb_colors(bb->dn_colors_exit, bbg, bb); + ret = risc_save_bb_colors(bb->dn_colors_exit, bbg, bb); if (ret < 0) return ret; } - _arm64_bbg_fix_loads(bbg); + _risc_bbg_fix_loads(bbg); - ret = _arm64_bbg_fix_saves(bbg, f); + ret = _risc_bbg_fix_saves(bbg, f); if (ret < 0) return ret; for (j = 0; j < bbg->body->size; j++) { bb = bbg->body->data[j]; - ret = arm64_fix_bb_colors(bb, bbg, f); + ret = risc_fix_bb_colors(bb, bbg, f); if (ret < 0) return ret; } } - ret = _arm64_make_insts_for_list(ctx, end, 0); + ret = _risc_make_insts_for_list(ctx, end, 0); if (ret < 0) return ret; #if 0 - if (arm64_optimize_peephole(ctx, f) < 0) { + if (risc_optimize_peephole(ctx, f) < 0) { scf_loge("\n"); return -1; } #endif - _arm64_set_offsets(f); + _risc_set_offsets(f); - _arm64_set_offset_for_jmps( ctx, f); + _risc_set_offset_for_jmps( ctx, f); return 0; } @@ -1140,11 +1128,12 @@ static int _find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results) return 0; } -int scf_arm64_select_inst(scf_native_t* ctx, scf_function_t* f) +int scf_risc_select_inst(scf_native_t* ctx, scf_function_t* f) { - scf_arm64_context_t* arm64 = ctx->priv; + scf_risc_context_t* risc = ctx->priv; - arm64->f = f; + risc->f = f; + f->iops = ctx->iops; scf_vector_t* local_vars = scf_vector_alloc(); if (!local_vars) @@ -1154,7 +1143,7 @@ int scf_arm64_select_inst(scf_native_t* ctx, scf_function_t* f) if (ret < 0) return ret; - int local_vars_size = _arm64_function_init(f, local_vars); + int local_vars_size = _risc_function_init(f, local_vars); if (local_vars_size < 0) return -1; @@ -1170,25 +1159,25 @@ int scf_arm64_select_inst(scf_native_t* ctx, scf_function_t* f) f->local_vars_size = local_vars_size; f->bp_used_flag = 1; - ret = _scf_arm64_select_inst(ctx); + ret = _scf_risc_select_inst(ctx); if (ret < 0) return ret; - ret = _arm64_function_finish(f); + ret = _risc_function_finish(ctx, f); if (ret < 0) return ret; - _arm64_set_offset_for_relas(ctx, f, f->text_relas); - _arm64_set_offset_for_relas(ctx, f, f->data_relas); + _risc_set_offset_for_relas(ctx, f, f->text_relas); + _risc_set_offset_for_relas(ctx, f, f->data_relas); return 0; } -scf_native_ops_t native_ops_arm64 = { +scf_native_ops_t native_ops_risc = { .name = "arm64", - .open = scf_arm64_open, - .close = scf_arm64_close, + .open = scf_risc_open, + .close = scf_risc_close, - .select_inst = scf_arm64_select_inst, + .select_inst = scf_risc_select_inst, }; diff --git a/native/risc/scf_risc.h b/native/risc/scf_risc.h new file mode 100644 index 0000000..0e50dca --- /dev/null +++ b/native/risc/scf_risc.h @@ -0,0 +1,182 @@ +#ifndef SCF_RISC_H +#define SCF_RISC_H + +#include"scf_native.h" +#include"scf_risc_util.h" +#include"scf_risc_reg.h" +#include"scf_risc_opcode.h" +#include"scf_graph.h" +#include"scf_elf.h" + +#define RISC_INST_ADD_CHECK(vec, inst) \ + do { \ + if (!(inst)) { \ + scf_loge("\n"); \ + return -ENOMEM; \ + } \ + int ret = scf_vector_add((vec), (inst)); \ + if (ret < 0) { \ + scf_loge("\n"); \ + free(inst); \ + return ret; \ + } \ + } while (0) + +#define RISC_RELA_ADD_CHECK(vec, rela, c, v, f) \ + do { \ + rela = calloc(1, sizeof(scf_rela_t)); \ + if (!rela) \ + return -ENOMEM; \ + \ + (rela)->code = (c); \ + (rela)->var = (v); \ + (rela)->func = (f); \ + (rela)->inst = (c)->instructions->data[(c)->instructions->size - 1]; \ + (rela)->addend = 0; \ + \ + int ret = scf_vector_add((vec), (rela)); \ + if (ret < 0) { \ + free(rela); \ + rela = NULL; \ + return ret; \ + } \ + } while (0) + +#define RISC_PEEPHOLE_DEL 1 +#define RISC_PEEPHOLE_OK 0 + +typedef struct { + + scf_function_t* f; + +} scf_risc_context_t; + +typedef struct { + scf_dag_node_t* dag_node; + + scf_register_t* reg; + + scf_risc_OpCode_t* OpCode; + +} risc_rcg_node_t; + +typedef struct { + int type; + int (*func)(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g); +} risc_rcg_handler_t; + +typedef struct { + int type; + int (*func)(scf_native_t* ctx, scf_3ac_code_t* c); +} risc_inst_handler_t; + +risc_rcg_handler_t* scf_risc_find_rcg_handler(const int op_type); +risc_inst_handler_t* scf_risc_find_inst_handler(const int op_type); + +int risc_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); +int _risc_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); + +int scf_risc_open (scf_native_t* ctx, const char* arch); +int scf_risc_close (scf_native_t* ctx); +int scf_risc_select(scf_native_t* ctx); + +int risc_optimize_peephole(scf_native_t* ctx, scf_function_t* f); + +int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors); + + +intptr_t risc_bb_find_color (scf_vector_t* dn_colors, scf_dag_node_t* dn); +int risc_save_bb_colors(scf_vector_t* dn_colors, scf_bb_group_t* bbg, scf_basic_block_t* bb); + +int risc_bb_load_dn (intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f); +int risc_bb_save_dn (intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f); +int risc_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f); +int risc_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f); + +int risc_fix_bb_colors (scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); +int risc_load_bb_colors (scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); +int risc_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); +void risc_init_bb_colors (scf_basic_block_t* bb); + + +scf_instruction_t* risc_make_inst (scf_3ac_code_t* c, uint32_t opcode); +scf_instruction_t* risc_make_inst_BL (scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_BLR (scf_3ac_code_t* c, scf_register_t* r); +scf_instruction_t* risc_make_inst_PUSH (scf_3ac_code_t* c, scf_register_t* r); +scf_instruction_t* risc_make_inst_POP (scf_3ac_code_t* c, scf_register_t* r); +scf_instruction_t* risc_make_inst_TEQ (scf_3ac_code_t* c, scf_register_t* rs); +scf_instruction_t* risc_make_inst_NEG (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_MSUB (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra); +scf_instruction_t* risc_make_inst_MUL (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_SDIV (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_DIV (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_FDIV (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_FMUL (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_FSUB (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_FADD (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_SUB_G (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_ADD_G (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_ADD_IMM (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); +scf_instruction_t* risc_make_inst_SUB_IMM (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); +scf_instruction_t* risc_make_inst_CMP_IMM(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm); +scf_instruction_t* risc_make_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_MOVZX (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size); +scf_instruction_t* risc_make_inst_MOVSX (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size); +scf_instruction_t* risc_make_inst_FMOV_G (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_MVN (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_MOV_G (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_MOV_SP (scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_AND_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_OR_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_CMP_G(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_SHL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_SHR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); +scf_instruction_t* risc_make_inst_ASR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + +scf_instruction_t* risc_make_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_CVTSD2SS(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_CVTF2SI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_CVTF2UI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_CVTSI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_CVTUI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); +scf_instruction_t* risc_make_inst_FCMP(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); + +scf_instruction_t* risc_make_inst_JA (scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JB (scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JZ (scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JNZ(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JGT(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JGE(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JLT(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JLE(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JMP(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JAE(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_JBE(scf_3ac_code_t* c); +scf_instruction_t* risc_make_inst_RET(scf_3ac_code_t* c); + +scf_instruction_t* risc_make_inst_SETZ (scf_3ac_code_t* c, scf_register_t* rd); +scf_instruction_t* risc_make_inst_SETNZ(scf_3ac_code_t* c, scf_register_t* rd); +scf_instruction_t* risc_make_inst_SETGT(scf_3ac_code_t* c, scf_register_t* rd); +scf_instruction_t* risc_make_inst_SETGE(scf_3ac_code_t* c, scf_register_t* rd); +scf_instruction_t* risc_make_inst_SETLT(scf_3ac_code_t* c, scf_register_t* rd); +scf_instruction_t* risc_make_inst_SETLE(scf_3ac_code_t* c, scf_register_t* rd); + +void risc_set_jmp_offset(scf_instruction_t* inst, int32_t bytes); + +int risc_make_inst_I2G (scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes); +int risc_make_inst_M2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); +int risc_make_inst_M2GF (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); +int risc_make_inst_G2M (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs); +int risc_make_inst_G2P (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size); +int risc_make_inst_P2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size); +int risc_make_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); +int risc_make_inst_SIB2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); +int risc_make_inst_G2SIB (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); +int risc_make_inst_ADR2G (scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); +int risc_make_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset); +int risc_make_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + +int risc_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); + +#endif + diff --git a/native/arm64/scf_arm64_bb_color.c b/native/risc/scf_risc_bb_color.c similarity index 76% rename from native/arm64/scf_arm64_bb_color.c rename to native/risc/scf_risc_bb_color.c index e160a54..668b018 100644 --- a/native/arm64/scf_arm64_bb_color.c +++ b/native/risc/scf_risc_bb_color.c @@ -1,16 +1,16 @@ -#include"scf_arm64.h" +#include"scf_risc.h" #include"scf_elf.h" #include"scf_basic_block.h" #include"scf_3ac.h" -void arm64_init_bb_colors(scf_basic_block_t* bb) +void risc_init_bb_colors(scf_basic_block_t* bb) { scf_dag_node_t* dn; scf_dn_status_t* ds; int i; - arm64_registers_reset(); + risc_registers_reset(); for (i = 0; i < bb->dn_colors_entry->size; i++) { ds = bb->dn_colors_entry->data[i]; @@ -32,7 +32,7 @@ void arm64_init_bb_colors(scf_basic_block_t* bb) printf("color: %ld, loaded: %d", dn->color, dn->loaded); if (dn->color > 0) { - scf_register_arm64_t* r = arm64_find_register_color(dn->color); + scf_register_t* r = risc_find_register_color(dn->color); printf(", reg: %s", r->name); } printf("\n"); @@ -40,7 +40,7 @@ void arm64_init_bb_colors(scf_basic_block_t* bb) } } -int arm64_save_bb_colors(scf_vector_t* dn_colors, scf_bb_group_t* bbg, scf_basic_block_t* bb) +int risc_save_bb_colors(scf_vector_t* dn_colors, scf_bb_group_t* bbg, scf_basic_block_t* bb) { scf_dag_node_t* dn; scf_dn_status_t* ds0; @@ -88,7 +88,7 @@ int arm64_save_bb_colors(scf_vector_t* dn_colors, scf_bb_group_t* bbg, scf_basic return 0; } -intptr_t arm64_bb_find_color(scf_vector_t* dn_colors, scf_dag_node_t* dn) +intptr_t risc_bb_find_color(scf_vector_t* dn_colors, scf_dag_node_t* dn) { scf_dn_status_t* ds = NULL; @@ -104,10 +104,10 @@ intptr_t arm64_bb_find_color(scf_vector_t* dn_colors, scf_dag_node_t* dn) return ds->color; } -int arm64_bb_load_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f) +int risc_bb_load_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f) { scf_variable_t* v = dn->var; - scf_register_arm64_t* r; + scf_register_t* r; scf_instruction_t* inst; int inst_bytes; @@ -122,9 +122,9 @@ int arm64_bb_load_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ dn->loaded = 0; - r = arm64_find_register_color(color); + r = risc_find_register_color(color); - ret = arm64_load_reg(r, dn, c, f); + ret = risc_load_reg(r, dn, c, f); if (ret < 0) { scf_loge("\n"); return ret; @@ -135,10 +135,10 @@ int arm64_bb_load_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ return 0; } -int arm64_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f) +int risc_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_function_t* f) { scf_variable_t* v = dn->var; - scf_register_arm64_t* r; + scf_register_t* r; scf_instruction_t* inst; int inst_bytes; @@ -154,9 +154,9 @@ int arm64_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ return -ENOMEM; } - r = arm64_find_register_color(color); + r = risc_find_register_color(color); - ret = arm64_save_var2(dn, r, c, f); + ret = risc_save_var2(dn, r, c, f); if (ret < 0) { scf_loge("\n"); return ret; @@ -165,12 +165,15 @@ int arm64_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ return 0; } -int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f) +int risc_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f) { - scf_instruction_t* cmp = NULL; - scf_instruction_t* inst; - scf_3ac_code_t* c; - scf_list_t* l; + scf_register_t* r16 = risc_find_register_type_id_bytes(0, 16, 8); + scf_register_t* r17 = risc_find_register_type_id_bytes(0, 17, 8); + scf_register_t* r0; + scf_instruction_t* cmp = NULL; + scf_instruction_t* inst; + scf_3ac_code_t* c; + scf_list_t* l; scf_variable_t* v = dn->var; if (v->w) @@ -178,8 +181,8 @@ int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, uint32_t opcode; uint32_t mov; - uint32_t r0; - uint32_t r1; + uint32_t i0; + uint32_t i1; l = scf_list_tail(&bb->code_list_head); c = scf_list_data(l, scf_3ac_code_t, list); @@ -198,26 +201,26 @@ int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, switch (cmp->code[3] & 0x7f) { case 0x71: // imm - r0 = (opcode >> 5) & 0x1f; - mov = (0xaa << 24) | (r0 << 16) | (0x1f << 5) | 0x10; // use r16 to backup r0 - inst = arm64_make_inst(c, mov); - ARM64_INST_ADD_CHECK(c->instructions, inst); + i0 = (opcode >> 5) & 0x1f; + r0 = risc_find_register_type_id_bytes(0, i0, 8); + inst = f->iops->MOV_G(c, r16, r0); // use r16 to backup r0 + RISC_INST_ADD_CHECK(c->instructions, inst); opcode &= ~(0x1f << 5); opcode |= (0x10 << 5); break; case 0x6b: // register - r0 = (opcode >> 5) & 0x1f; - r1 = (opcode >> 16) & 0x1f; + i0 = (opcode >> 5) & 0x1f; + i1 = (opcode >> 16) & 0x1f; - mov = (0xaa << 24) | (r0 << 16) | (0x1f << 5) | 0x10; // use r16 to backup r0 - inst = arm64_make_inst(c, mov); - ARM64_INST_ADD_CHECK(c->instructions, inst); + r0 = risc_find_register_type_id_bytes(0, i0, 8); + inst = f->iops->MOV_G(c, r16, r0); // use r16 to backup r0 + RISC_INST_ADD_CHECK(c->instructions, inst); - mov = (0xaa << 24) | (r1 << 16) | (0x1f << 5) | 0x11; // use r17 to backup r0 - inst = arm64_make_inst(c, mov); - ARM64_INST_ADD_CHECK(c->instructions, inst); + r0 = risc_find_register_type_id_bytes(0, i1, 8); + inst = f->iops->MOV_G(c, r17, r0); // use r17 to backup r1 + RISC_INST_ADD_CHECK(c->instructions, inst); opcode &= ~(0x1f << 5); opcode |= (0x10 << 5); @@ -238,17 +241,17 @@ int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, cmp->code[3] = 0xff & (opcode >> 24); } - int ret = arm64_bb_load_dn(color, dn, c, bb, f); + int ret = risc_bb_load_dn(color, dn, c, bb, f); if (ret < 0) return ret; if (cmp) - ARM64_INST_ADD_CHECK(c->instructions, cmp); + RISC_INST_ADD_CHECK(c->instructions, cmp); return 0; } -int arm64_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f) +int risc_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f) { scf_3ac_operand_t* src; scf_3ac_code_t* c; @@ -265,7 +268,7 @@ int arm64_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, if (src->dag_node == dn) { - if (arm64_bb_save_dn(color, dn, c, bb, f) < 0) { + if (risc_bb_save_dn(color, dn, c, bb, f) < 0) { scf_loge("\n"); return -1; } @@ -279,7 +282,7 @@ int arm64_bb_save_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, return 0; } -int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) +int risc_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) { scf_basic_block_t* prev; scf_dn_status_t* ds; @@ -291,7 +294,7 @@ int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functio int j; int k; - if (arm64_save_bb_colors(bb->dn_colors_entry, bbg, bb) < 0) { + if (risc_save_bb_colors(bb->dn_colors_entry, bbg, bb) < 0) { scf_loge("\n"); return -1; } @@ -347,7 +350,7 @@ int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functio assert(k < prev->dn_colors_exit->size); - if (arm64_bb_save_dn2(ds2->color, dn, prev, f) < 0) { + if (risc_bb_save_dn2(ds2->color, dn, prev, f) < 0) { scf_loge("\n"); return -1; } @@ -358,7 +361,7 @@ int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functio } if (color != dn->color && color > 0) { - scf_register_arm64_t* r = arm64_find_register_color(color); + scf_register_t* r = risc_find_register_color(color); scf_vector_del(r->dag_nodes, dn); } @@ -377,7 +380,7 @@ int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functio printf("v_%#lx", 0xffff & (uintptr_t)v); if (dn->color > 0) { - scf_register_arm64_t* r = arm64_find_register_color(dn->color); + scf_register_t* r = risc_find_register_color(dn->color); printf(", %s", r->name); } @@ -388,7 +391,7 @@ int arm64_load_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functio return 0; } -int arm64_fix_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) +int risc_fix_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) { scf_basic_block_t* prev; scf_dn_status_t* ds; @@ -434,14 +437,14 @@ int arm64_fix_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function continue; if (ds2->color > 0) { - if (arm64_bb_save_dn2(ds2->color, dn, prev, f) < 0) { + if (risc_bb_save_dn2(ds2->color, dn, prev, f) < 0) { scf_loge("\n"); return -1; } } if (ds->color > 0) { - if (arm64_bb_load_dn2(ds->color, dn, prev, f) < 0) { + if (risc_bb_load_dn2(ds->color, dn, prev, f) < 0) { scf_loge("\n"); return -1; } @@ -452,9 +455,9 @@ int arm64_fix_bb_colors(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function return 0; } -int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) +int risc_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f) { - scf_register_arm64_t* r; + scf_register_t* r; scf_basic_block_t* prev; scf_dn_status_t* ds; scf_dn_status_t* ds2; @@ -465,7 +468,7 @@ int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functi int j; int k; - if (arm64_save_bb_colors(bb->dn_colors_entry, bbg, bb) < 0) { + if (risc_save_bb_colors(bb->dn_colors_entry, bbg, bb) < 0) { scf_loge("\n"); return -1; } @@ -521,7 +524,7 @@ int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functi assert(k < prev->dn_colors_exit->size); - if (arm64_bb_save_dn2(ds2->color, dn, prev, f) < 0) { + if (risc_bb_save_dn2(ds2->color, dn, prev, f) < 0) { scf_loge("\n"); return -1; } @@ -532,7 +535,7 @@ int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functi } if (color != dn->color && color > 0) { - r = arm64_find_register_color(color); + r = risc_find_register_color(color); scf_vector_del(r->dag_nodes, dn); } @@ -554,7 +557,7 @@ int arm64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_functi printf("v_%#lx", 0xffff & (uintptr_t)v); #endif if (dn->color > 0) { - r = arm64_find_register_color(dn->color); + r = risc_find_register_color(dn->color); if (dn->loaded) assert(0 == scf_vector_add_unique(r->dag_nodes, dn)); diff --git a/native/arm64/scf_arm64_graph.c b/native/risc/scf_risc_graph.c similarity index 74% rename from native/arm64/scf_arm64_graph.c rename to native/risc/scf_risc_graph.c index dda10ac..f05b156 100644 --- a/native/arm64/scf_arm64_graph.c +++ b/native/risc/scf_risc_graph.c @@ -1,9 +1,9 @@ #include"scf_graph.h" -#include"scf_arm64.h" +#include"scf_risc.h" -static intptr_t _arm64_color_select(scf_graph_node_t* node, scf_vector_t* colors) +static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors) { - arm64_rcg_node_t* rn = node->data; + risc_rcg_node_t* rn = node->data; if (!rn->dag_node) { assert(rn->reg); @@ -13,10 +13,10 @@ static intptr_t _arm64_color_select(scf_graph_node_t* node, scf_vector_t* colors int i; for (i = 0; i < colors->size; i++) { intptr_t c = (intptr_t)(colors->data[i]); - int bytes = ARM64_COLOR_BYTES(c); - uint32_t type = ARM64_COLOR_TYPE(c); + int bytes = RISC_COLOR_BYTES(c); + uint32_t type = RISC_COLOR_TYPE(c); - if (bytes == arm64_variable_size(rn->dag_node->var) + if (bytes == risc_variable_size(rn->dag_node->var) && type == scf_variable_float(rn->dag_node->var)) return c; } @@ -24,14 +24,14 @@ static intptr_t _arm64_color_select(scf_graph_node_t* node, scf_vector_t* colors return 0; } -static int _arm64_color_del(scf_vector_t* colors, intptr_t color) +static int _risc_color_del(scf_vector_t* colors, intptr_t color) { int i = 0; while (i < colors->size) { intptr_t c = (intptr_t)(colors->data[i]); - if (ARM64_COLOR_CONFLICT(c, color)) { + if (RISC_COLOR_CONFLICT(c, color)) { int ret = scf_vector_del(colors, (void*)c); if (ret < 0) return ret; @@ -44,13 +44,13 @@ static int _arm64_color_del(scf_vector_t* colors, intptr_t color) return 0; } -static int _arm64_kcolor_check(scf_graph_t* graph) +static int _risc_kcolor_check(scf_graph_t* graph) { int i; for (i = 0; i < graph->nodes->size; i++) { scf_graph_node_t* node = graph->nodes->data[i]; - arm64_rcg_node_t* rn = node->data; + risc_rcg_node_t* rn = node->data; if (rn->reg) assert(node->color > 0); @@ -62,7 +62,7 @@ static int _arm64_kcolor_check(scf_graph_t* graph) return 0; } -static int _arm64_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted_nodes) +static int _risc_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted_nodes) { while (graph->nodes->size > 0) { @@ -71,7 +71,7 @@ static int _arm64_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted while (i < graph->nodes->size) { scf_graph_node_t* node = graph->nodes->data[i]; - arm64_rcg_node_t* rn = node->data; + risc_rcg_node_t* rn = node->data; scf_logd("graph->nodes->size: %d, neighbors: %d, k: %d, node: %p, rn->reg: %p\n", graph->nodes->size, node->neighbors->size, k, node, rn->reg); @@ -110,7 +110,7 @@ static int _arm64_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted return 0; } -static int _arm64_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, +static int _risc_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, scf_vector_t* deleted_nodes) { scf_logd("graph->nodes->size: %d\n", graph->nodes->size); @@ -120,7 +120,7 @@ static int _arm64_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, for (i = deleted_nodes->size - 1; i >= 0; i--) { scf_graph_node_t* node = deleted_nodes->data[i]; - arm64_rcg_node_t* rn = node->data; + risc_rcg_node_t* rn = node->data; if (node->neighbors->size >= k) assert(rn->reg); @@ -135,11 +135,11 @@ static int _arm64_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, scf_graph_node_t* neighbor = node->neighbors->data[j]; if (neighbor->color > 0) { - int ret = _arm64_color_del(colors2, neighbor->color); + int ret = _risc_color_del(colors2, neighbor->color); if (ret < 0) goto error; - if (ARM64_COLOR_CONFLICT(node->color, neighbor->color)) { + if (RISC_COLOR_CONFLICT(node->color, neighbor->color)) { scf_logd("node: %p, neighbor: %p, color: %#lx:%#lx\n", node, neighbor, node->color, neighbor->color); scf_logd("node: %p, dn: %p, reg: %p\n", node, rn->dag_node, rn->reg); //assert(!rn->reg); @@ -157,7 +157,7 @@ static int _arm64_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, assert(colors2->size >= 0); if (0 == node->color) { - node->color = _arm64_color_select(node, colors2); + node->color = _risc_color_select(node, colors2); if (0 == node->color) { node->color = -1; scf_logd("colors2->size: %d\n", colors2->size); @@ -179,14 +179,14 @@ error: return -1; } -static int _arm64_kcolor_find_not_neighbor(scf_graph_t* graph, int k, scf_graph_node_t** pp0, scf_graph_node_t** pp1) +static int _risc_kcolor_find_not_neighbor(scf_graph_t* graph, int k, scf_graph_node_t** pp0, scf_graph_node_t** pp1) { assert(graph->nodes->size >= k); scf_graph_node_t* node0; scf_graph_node_t* node1; - arm64_rcg_node_t* rn0; - arm64_rcg_node_t* rn1; + risc_rcg_node_t* rn0; + risc_rcg_node_t* rn1; scf_dag_node_t* dn0; scf_dag_node_t* dn1; @@ -247,14 +247,14 @@ static int _arm64_kcolor_find_not_neighbor(scf_graph_t* graph, int k, scf_graph_ return -1; } -static scf_graph_node_t* _arm64_max_neighbors(scf_graph_t* graph) +static scf_graph_node_t* _risc_max_neighbors(scf_graph_t* graph) { scf_graph_node_t* node_max = NULL; int max = 0; int i; for (i = 0; i < graph->nodes->size; i++) { scf_graph_node_t* node = graph->nodes->data[i]; - arm64_rcg_node_t* rn = node->data; + risc_rcg_node_t* rn = node->data; if (rn->reg) { assert(node->color > 0); @@ -267,7 +267,7 @@ static scf_graph_node_t* _arm64_max_neighbors(scf_graph_t* graph) } } - arm64_rcg_node_t* rn = node_max->data; + risc_rcg_node_t* rn = node_max->data; if (rn->dag_node->var->w) scf_logi("max_neighbors: %d, %s\n", max, rn->dag_node->var->w->text->data); @@ -277,7 +277,7 @@ static scf_graph_node_t* _arm64_max_neighbors(scf_graph_t* graph) return node_max; } -static void _arm64_kcolor_process_conflict(scf_graph_t* graph) +static void _risc_kcolor_process_conflict(scf_graph_t* graph) { int i; int j; @@ -286,7 +286,7 @@ static void _arm64_kcolor_process_conflict(scf_graph_t* graph) for (i = 0; i < graph->nodes->size - 1; i++) { scf_graph_node_t* gn0 = graph->nodes->data[i]; - arm64_rcg_node_t* rn0 = gn0->data; + risc_rcg_node_t* rn0 = gn0->data; scf_logd("i: %d, rn0->dag_node: %p, rn0->reg: %p\n", i, rn0->dag_node, rn0->reg); if (0 == gn0->color) @@ -295,13 +295,13 @@ static void _arm64_kcolor_process_conflict(scf_graph_t* graph) for (j = i + 1; j < graph->nodes->size; j++) { scf_graph_node_t* gn1 = graph->nodes->data[j]; - arm64_rcg_node_t* rn1 = gn1->data; + risc_rcg_node_t* rn1 = gn1->data; scf_logd("j: %d, rn1->dag_node: %p, rn1->reg: %p\n", j, rn1->dag_node, rn1->reg); if (0 == gn1->color) continue; - if (!ARM64_COLOR_CONFLICT(gn0->color, gn1->color)) + if (!RISC_COLOR_CONFLICT(gn0->color, gn1->color)) continue; if (!rn0->dag_node) { @@ -336,7 +336,7 @@ static void _arm64_kcolor_process_conflict(scf_graph_t* graph) } } -static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) +static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) { int ret = -1; scf_vector_t* colors2 = NULL; @@ -347,14 +347,14 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) scf_logd("graph->nodes->size: %d, k: %d\n", graph->nodes->size, k); - ret = _arm64_kcolor_delete(graph, k, deleted_nodes); + ret = _risc_kcolor_delete(graph, k, deleted_nodes); if (ret < 0) goto error; - if (0 == _arm64_kcolor_check(graph)) { + if (0 == _risc_kcolor_check(graph)) { scf_logd("graph->nodes->size: %d\n", graph->nodes->size); - ret = _arm64_kcolor_fill(graph, k, colors, deleted_nodes); + ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes); if (ret < 0) goto error; @@ -372,12 +372,12 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) scf_graph_node_t* node0 = NULL; scf_graph_node_t* node1 = NULL; - if (0 == _arm64_kcolor_find_not_neighbor(graph, k, &node0, &node1)) { + if (0 == _risc_kcolor_find_not_neighbor(graph, k, &node0, &node1)) { assert(node0); assert(node1); - arm64_rcg_node_t* rn0 = node0->data; - arm64_rcg_node_t* rn1 = node1->data; + risc_rcg_node_t* rn0 = node0->data; + risc_rcg_node_t* rn1 = node1->data; assert(!colors2); colors2 = scf_vector_clone(colors); @@ -386,21 +386,21 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) goto error; } - int reg_size0 = arm64_variable_size(rn0->dag_node->var); - int reg_size1 = arm64_variable_size(rn1->dag_node->var); + int reg_size0 = risc_variable_size(rn0->dag_node->var); + int reg_size1 = risc_variable_size(rn1->dag_node->var); if (reg_size0 > reg_size1) { - node0->color = _arm64_color_select(node0, colors2); + node0->color = _risc_color_select(node0, colors2); if (0 == node0->color) goto overflow; - intptr_t type = ARM64_COLOR_TYPE(node0->color); - intptr_t id = ARM64_COLOR_ID(node0->color); + intptr_t type = RISC_COLOR_TYPE(node0->color); + intptr_t id = RISC_COLOR_ID(node0->color); intptr_t mask = (1 << reg_size1) - 1; - node1->color = ARM64_COLOR(type, id, mask); + node1->color = RISC_COLOR(type, id, mask); - ret = _arm64_color_del(colors2, node0->color); + ret = _risc_color_del(colors2, node0->color); if (ret < 0) { scf_loge("\n"); goto error; @@ -409,17 +409,17 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) assert(!scf_vector_find(colors2, (void*)node1->color)); } else { - node1->color = _arm64_color_select(node1, colors2); + node1->color = _risc_color_select(node1, colors2); if (0 == node1->color) goto overflow; - intptr_t type = ARM64_COLOR_TYPE(node1->color); - intptr_t id = ARM64_COLOR_ID(node1->color); + intptr_t type = RISC_COLOR_TYPE(node1->color); + intptr_t id = RISC_COLOR_ID(node1->color); intptr_t mask = (1 << reg_size0) - 1; - node0->color = ARM64_COLOR(type, id, mask); + node0->color = RISC_COLOR(type, id, mask); - ret = _arm64_color_del(colors2, node1->color); + ret = _risc_color_del(colors2, node1->color); if (ret < 0) { scf_loge("\n"); goto error; @@ -436,7 +436,7 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) if (ret < 0) goto error; - ret = scf_arm64_graph_kcolor(graph, k - 1, colors2); + ret = scf_risc_graph_kcolor(graph, k - 1, colors2); if (ret < 0) goto error; @@ -452,7 +452,7 @@ static int _arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) colors2 = NULL; } else { overflow: - node_max = _arm64_max_neighbors(graph); + node_max = _risc_max_neighbors(graph); assert(node_max); ret = scf_graph_delete_node(graph, node_max); @@ -460,7 +460,7 @@ overflow: goto error; node_max->color = -1; - ret = scf_arm64_graph_kcolor(graph, k, colors); + ret = scf_risc_graph_kcolor(graph, k, colors); if (ret < 0) goto error; @@ -469,7 +469,7 @@ overflow: goto error; } - ret = _arm64_kcolor_fill(graph, k, colors, deleted_nodes); + ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes); if (ret < 0) goto error; @@ -487,16 +487,16 @@ error: return ret; } -int scf_arm64_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) +int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) { if (!graph || !colors || 0 == colors->size) { scf_loge("\n"); return -EINVAL; } - _arm64_kcolor_process_conflict(graph); + _risc_kcolor_process_conflict(graph); - return _arm64_graph_kcolor(graph, k, colors); + return _risc_graph_kcolor(graph, k, colors); } diff --git a/native/risc/scf_risc_inst.c b/native/risc/scf_risc_inst.c new file mode 100644 index 0000000..d266348 --- /dev/null +++ b/native/risc/scf_risc_inst.c @@ -0,0 +1,5789 @@ +#include"scf_risc.h" + +#define RISC_INST_OP3_CHECK() \ + if (!c->dsts || c->dsts->size != 1) \ + return -EINVAL; \ + \ + if (!c->srcs || c->srcs->size != 2) \ + return -EINVAL; \ + \ + scf_risc_context_t* risc = ctx->priv; \ + scf_function_t* f = risc->f; \ + \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + scf_3ac_operand_t* src0 = c->srcs->data[0]; \ + scf_3ac_operand_t* src1 = c->srcs->data[1]; \ + \ + if (!src0 || !src0->dag_node) \ + return -EINVAL; \ + \ + if (!src1 || !src1->dag_node) \ + return -EINVAL; \ + \ + if (!dst || !dst->dag_node) \ + return -EINVAL; \ + \ + if (src0->dag_node->var->size != src1->dag_node->var->size) {\ + scf_loge("size: %d, %d\n", src0->dag_node->var->size, src1->dag_node->var->size); \ + return -EINVAL; \ + } + + +static int _risc_inst_call_stack_size(scf_3ac_code_t* c) +{ + int stack_size = 0; + + int i; + for (i = 1; i < c->srcs->size; i++) { + scf_3ac_operand_t* src = c->srcs->data[i]; + scf_variable_t* v = src->dag_node->var; + + if (src->dag_node->rabi2) + continue; + + int size = risc_variable_size(v); + if (size & 0x7) + size = (size + 7) >> 3 << 3; + + v->sp_offset = stack_size; + stack_size += size; + } + assert(0 == (stack_size & 0x7)); + + if (stack_size & 0xf) + stack_size += 8; + + return stack_size; +} + +static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* sp = risc_find_register("sp"); + + scf_risc_OpCode_t* lea; + scf_risc_OpCode_t* mov; + scf_risc_OpCode_t* movx; + scf_instruction_t* inst; + + uint32_t opcode; + + int nb_floats = 0; + int ret; + int i; + for (i = c->srcs->size - 1; i >= 1; i--) { + scf_3ac_operand_t* src = c->srcs->data[i]; + scf_variable_t* v = src->dag_node->var; + scf_register_t* rd = src->rabi; + scf_register_t* rabi = src->dag_node->rabi2; + scf_register_t* rs = NULL; + + int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + + if (!rabi) { + rabi = risc_find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size); + + ret = risc_overflow_reg(rabi, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + movx = NULL; + + if (!is_float) { + mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_G2E); + + if (size < 8) { + if (scf_variable_signed(v)) + movx = risc_find_OpCode(SCF_RISC_MOVSX, size, 8, SCF_RISC_E2G); + else if (size < 4) + movx = risc_find_OpCode(SCF_RISC_MOVZX, size, 8, SCF_RISC_E2G); + } + + if (0 == src->dag_node->color) { + + ret = risc_overflow_reg(rabi, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = risc_load_const(rabi, src->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + rabi = risc_find_register_color_bytes(rabi->color, 8); + rs = rabi; + } else { + if (src->dag_node->color < 0) + src->dag_node->color = rabi->color; + } + } else { + nb_floats++; + + if (0 == src->dag_node->color) { + src->dag_node->color = -1; + v->global_flag = 1; + } + + if (SCF_VAR_FLOAT == v->type) { + mov = risc_find_OpCode(SCF_RISC_MOVSS, 4, 4, SCF_RISC_G2E); + movx = risc_find_OpCode(SCF_RISC_CVTSS2SD, 4, 8, SCF_RISC_E2G); + } else + mov = risc_find_OpCode(SCF_RISC_MOVSD, size, size, SCF_RISC_G2E); + + if (src->dag_node->color < 0) + src->dag_node->color = rabi->color; + } + + if (!rs) { + assert(src->dag_node->color > 0); + + if (rd && RISC_COLOR_CONFLICT(rd->color, src->dag_node->color)) { + + ret = risc_overflow_reg2(rd, src->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + rs = risc_find_register_color_bytes(rs->color, 8); + } + + if (movx) { + if (SCF_RISC_MOVSX == movx->type) { + + inst = ctx->iops->MOVSX(c, rs, rs, size); + + } else if (SCF_RISC_MOVZX == movx->type) { + + inst = ctx->iops->MOVZX(c, rs, rs, size); + + } else { + assert(SCF_RISC_CVTSS2SD == movx->type); + + inst = ctx->iops->CVTSS2SD(c, rs, rs); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + if (!rd) { + ret = ctx->iops->G2P(c, f, rs, sp, v->sp_offset, size); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + continue; + } + + ret = risc_overflow_reg2(rd, src->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (!RISC_COLOR_CONFLICT(rd->color, rs->color)) { + rd = risc_find_register_color_bytes(rd->color, rs->bytes); + + if (!is_float) + inst = ctx->iops->MOV_G(c, rd, rs); + else + inst = ctx->iops->FMOV_G(c, rd, rs); + + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + ret = risc_rcg_make(c, c->rcg, NULL, rd); + if (ret < 0) + return ret; + } + + return nb_floats; +} + +static int _risc_call_save_ret_regs(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf) +{ + scf_register_t* r; + scf_variable_t* v; + + int i; + for (i = 0; i < pf->rets->size; i++) { + v = pf->rets->data[i]; + + int is_float = scf_variable_float(v); + + if (is_float) { + + if (i > 0) { + scf_loge("\n"); + return -1; + } + + r = risc_find_register_type_id_bytes(is_float, 0, 8); + } else + r = risc_find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], 8); + + int ret = risc_overflow_reg(r, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + return 0; +} + +static int _risc_dst_reg_valid(scf_register_t* rd, scf_register_t** updated_regs, int nb_updated, int abi_idx, int abi_total) +{ + scf_register_t* r; + + int i; + for (i = 0; i < nb_updated; i++) { + + r = updated_regs[i]; + + if (RISC_COLOR_CONFLICT(r->color, rd->color)) + return 0; + } + + for (i = abi_idx; i < abi_total; i++) { + + r = risc_find_register_type_id_bytes(RISC_COLOR_TYPE(rd->color), risc_abi_ret_regs[i], rd->bytes); + + if (RISC_COLOR_CONFLICT(r->color, rd->color)) + return 0; + } + + return 1; +} + +static int _risc_call_update_dsts(scf_native_t* ctx, scf_3ac_code_t* c, scf_function_t* f, scf_register_t** updated_regs, int max_updated) +{ + scf_3ac_operand_t* dst; + scf_dag_node_t* dn; + scf_variable_t* v; + + scf_register_t* rd; + scf_register_t* rs; + scf_risc_OpCode_t* mov; + + int nb_float = 0; + int nb_int = 0; + + int i; + for (i = 0; i < c->dsts->size; i++) { + dst = c->dsts->data[i]; + dn = dst->dag_node; + v = dn->var; + + if (SCF_VAR_VOID == v->type && 0 == v->nb_pointers) + continue; + + assert(0 != dn->color); + + int is_float = scf_variable_float(v); + + if (is_float) + nb_float++; + else + nb_int++; + } + + int nb_updated = 0; + int idx_float = 0; + int idx_int = 0; + + for (i = 0; i < c->dsts->size; i++) { + dst = c->dsts->data[i]; + dn = dst->dag_node; + v = dn->var; + + if (SCF_VAR_VOID == v->type && 0 == v->nb_pointers) + continue; + + int is_float = scf_variable_float(v); + int dst_size = risc_variable_size (v); + + if (is_float) { + if (i > 0) { + scf_loge("\n"); + return -1; + } + + scf_loge("\n"); + return -EINVAL; + + rs = risc_find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, dst_size); + + if (SCF_VAR_FLOAT == dn->var->type) + mov = risc_find_OpCode(SCF_RISC_MOVSS, dst_size, dst_size, SCF_RISC_G2E); + else + mov = risc_find_OpCode(SCF_RISC_MOVSD, dst_size, dst_size, SCF_RISC_G2E); + + idx_float++; + } else { + rs = risc_find_register_type_id_bytes(is_float, risc_abi_ret_regs[idx_int], dst_size); + + mov = risc_find_OpCode(SCF_RISC_MOV, dst_size, dst_size, SCF_RISC_G2E); + + idx_int++; + } + + scf_instruction_t* inst; + + if (dn->color > 0) { + rd = risc_find_register_color(dn->color); + + int rd_vars = risc_reg_cached_vars(rd); + + if (rd_vars > 1) { + dn->color = -1; + dn->loaded = 0; + scf_vector_del(rd->dag_nodes, dn); + + } else if (rd_vars > 0 + && !scf_vector_find(rd->dag_nodes, dn)) { + dn->color = -1; + dn->loaded = 0; + + } else { + RISC_SELECT_REG_CHECK(&rd, dn, c, f, 0); + + if (dn->color == rs->color) { + assert(nb_updated < max_updated); + + updated_regs[nb_updated++] = rs; + continue; + } + + int valid = _risc_dst_reg_valid(rd, updated_regs, nb_updated, idx_int, nb_int); + if (valid) { + inst = ctx->iops->MOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + assert(nb_updated < max_updated); + + updated_regs[nb_updated++] = rd; + continue; + } + + assert(0 == scf_vector_del(rd->dag_nodes, dn)); + dn->color = -1; + dn->loaded = 0; + } + } + + int rs_vars = risc_reg_cached_vars(rs); + + if (0 == rs_vars) { + if (scf_vector_add(rs->dag_nodes, dn) < 0) + return -ENOMEM; + + assert(nb_updated < max_updated); + + updated_regs[nb_updated++] = rs; + + dn->color = rs->color; + dn->loaded = 1; + + } else { + int ret = ctx->iops->G2M(c, f, rs, NULL, dn->var); + if (ret < 0) + return ret; + } + } + return nb_updated; +} + +static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (c->srcs->size < 1) { + scf_loge("\n"); + return -EINVAL; + } + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* src0 = c->srcs->data[0]; + scf_variable_t* var_pf = src0->dag_node->var; + scf_function_t* pf = var_pf->func_ptr; + + if (SCF_FUNCTION_PTR != var_pf->type || !pf) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* lr = risc_find_register("lr"); + scf_register_t* sp = risc_find_register("sp"); + scf_register_t* x0 = risc_find_register("x0"); + scf_instruction_t* inst; + scf_instruction_t* inst_sp = NULL; + scf_instruction_t* inst_sp2 = NULL; + + lr->used = 1; + sp->used = 1; + + int data_rela_size = f->data_relas->size; + int text_rela_size = f->text_relas->size; + scf_loge("f->data_relas->size: %d, f->text_relas->size: %d\n", f->data_relas->size, f->text_relas->size); + + uint32_t opcode; + int ret; + int i; + + if (pf->rets) { + ret = _risc_call_save_ret_regs(c, f, pf); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + ret = risc_overflow_reg(x0, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + risc_call_rabi(NULL, NULL, c); + + int32_t stack_size = _risc_inst_call_stack_size(c); + if (stack_size > 0) { + inst_sp = risc_make_inst(c, 0); + inst_sp2 = risc_make_inst(c, 0); + RISC_INST_ADD_CHECK(c->instructions, inst_sp); + RISC_INST_ADD_CHECK(c->instructions, inst_sp2); + } + + ret = _risc_inst_call_argv(ctx, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + scf_register_t* saved_regs[RISC_ABI_CALLER_SAVES_NB]; + + int save_size = risc_caller_save_regs(c, f, risc_abi_caller_saves, RISC_ABI_CALLER_SAVES_NB, stack_size, saved_regs); + if (save_size < 0) { + scf_loge("\n"); + return save_size; + } + + if (stack_size > 0) { + assert(inst_sp); + assert(inst_sp2); + + if (stack_size > 0xfff) { + stack_size += 1 << 12; + stack_size &= ~0xfff; + + if (stack_size < 0 || (stack_size >> 12) > 0xfff) { + scf_loge("\n"); + return -EINVAL; + } + } + + inst = ctx->iops->SUB_IMM(c, sp, sp, stack_size); + if (inst) { + memcpy(inst_sp->code, inst->code, 4); + free(inst); + inst = NULL; + } else + return -ENOMEM; + + if (save_size > 0xfff) { + scf_loge("\n"); + return -EINVAL; + } + + if (save_size > 0) { + inst = ctx->iops->SUB_IMM(c, sp, sp, save_size); + if (inst) { + memcpy(inst_sp2->code, inst->code, 4); + free(inst); + inst = NULL; + } else + return -ENOMEM; + } + } + + if (var_pf->const_literal_flag) { + assert(0 == src0->dag_node->color); + + inst = ctx->iops->BL(c); + RISC_INST_ADD_CHECK(c->instructions, inst); + + scf_rela_t* rela = NULL; + + RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); + rela->type = R_AARCH64_CALL26; + + } else { + assert(0 != src0->dag_node->color); + + if (src0->dag_node->color > 0) { + + scf_register_t* r_pf = NULL; + + ret = risc_select_reg(&r_pf, src0->dag_node, c, f, 1); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + inst = ctx->iops->BLR(c, r_pf); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else { + scf_loge("\n"); + return -EINVAL; + } + } + + if (stack_size > 0) { + inst = ctx->iops->ADD_IMM(c, sp, sp, stack_size); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + int nb_updated = 0; + scf_register_t* updated_regs[RISC_ABI_RET_NB * 2]; + + if (pf->rets && pf->rets->size > 0 && c->dsts) { + + nb_updated = _risc_call_update_dsts(ctx, c, f, updated_regs, RISC_ABI_RET_NB * 2); + if (nb_updated < 0) { + scf_loge("\n"); + return nb_updated; + } + } + + if (save_size > 0) { + ret = risc_pop_regs(c, f, saved_regs, save_size >> 3, updated_regs, nb_updated); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + return 0; +} + +static int _risc_inst_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* s = src->dag_node; + scf_dag_node_t* d = dst->dag_node; + + uint32_t opcode; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + uint64_t u = s->var->data.u64; + + int ret = ctx->iops->I2G(c, rd, u, 8); + if (ret < 0) + return ret; + + opcode = (0xaa << 24) | (0x1 << 21) | (rd->id << 16) | (0x1f << 10) | rd->id; + inst = ctx->iops->MVN(c, rd, rd); + + } else { + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->MVN(c, rd, rs); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_inc_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_instruction_t* inst = NULL; + scf_function_t* f = risc->f; + + if (!src || !src->dag_node) + return -EINVAL; + + if (0 == src->dag_node->color) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->ADD_IMM(c, rs, rs, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +static int _risc_inst_inc_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst = NULL; + scf_function_t* f = risc->f; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (0 == src->dag_node->color) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->MOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->ADD_IMM(c, rs, rs, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_dec_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_instruction_t* inst = NULL; + scf_function_t* f = risc->f; + + if (!src || !src->dag_node) + return -EINVAL; + + if (0 == src->dag_node->color) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->SUB_IMM(c, rs, rs, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +static int _risc_inst_dec_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst = NULL; + scf_function_t* f = risc->f; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (0 == src->dag_node->color) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->MOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->SUB_IMM(c, rs, rs, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + assert(0 != dst->dag_node->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* s = src->dag_node; + scf_dag_node_t* d = dst->dag_node; + scf_variable_t* v = d->var; + + uint32_t opcode; + + int is_float = scf_variable_float(v); + int size = risc_variable_size(v); + + if (!is_float) { + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + uint64_t u = s->var->data.u64; + + int ret = ctx->iops->I2G(c, rd, u, 8); + if (ret < 0) + return ret; + + inst = ctx->iops->NEG(c, rd, rd); + + } else { + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->NEG(c, rd, rs); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + +#if 0 + scf_risc_OpCode_t* pxor = risc_find_OpCode(SCF_RISC_PXOR, 8, 8, SCF_RISC_E2G); + scf_risc_OpCode_t* sub = risc_find_OpCode(SCF_RISC_SUBSS, 4, 4, SCF_RISC_E2G); + + if (v->size > 4) + sub = risc_find_OpCode(SCF_RISC_SUBSD, 8, 8, SCF_RISC_E2G); + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + inst = ctx->iops->E2G(pxor, rd, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (src->dag_node->color > 0) { + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->E2G(sub, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else { + scf_rela_t* rela = NULL; + + v = src->dag_node->var; + + if (0 == src->dag_node->color) { + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + } + + inst = ctx->iops->M2G(&rela, sub, rd, NULL, v); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + } +#endif + return -1; +} + +static int _risc_inst_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_select_reg(&rd, dst->dag_node, c, f, 0); + if (ret < 0) + return ret; + + ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + + return ctx->iops->ADRP2G(c, f, rd, sib.base, sib.disp); + + if (sib.index) + return ctx->iops->SIB2G(c, f, rd, &sib); + + return ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_binary_assign_pointer(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) +{ +} + +static int _risc_inst_inc_dec_post_pointer(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t u24) +{ +} + +static int _risc_inst_inc_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + uint32_t opcode; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + scf_register_t* r = NULL; + scf_sib_t sib = {0}; + + int size = risc_variable_size(vm); + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vm); + if (is_float) { + scf_loge("\n"); + return -EINVAL; + } + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, r, &sib); + else + ret = ctx->iops->P2G(c, f, r, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, r, &sib); + else + ret = ctx->iops->G2P(c, f, r, sib.base, sib.disp, sib.size); + return ret; +} + +static int _risc_inst_dec_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + uint32_t opcode; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + scf_register_t* r = NULL; + scf_sib_t sib = {0}; + + int size = risc_variable_size(vm); + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vm); + if (is_float) { + scf_loge("\n"); + return -EINVAL; + } + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, r, &sib); + else + ret = ctx->iops->P2G(c, f, r, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, r, &sib); + else + ret = ctx->iops->G2P(c, f, r, sib.base, sib.disp, sib.size); + return ret; +} + +static int _risc_inst_inc_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + uint32_t opcode; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int size = risc_variable_size(vm); + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vm); + if (is_float) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_dec_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + uint32_t opcode; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int size = risc_variable_size(vm); + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vm); + if (is_float) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + return ctx->iops->ADRP2G(c, f, rd, sib.base, sib.disp); +} + +static int _risc_inst_binary_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) +{ + return 0; +} + +static int _risc_inst_inc_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + + uint32_t opcode; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* r = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int size = vb->data_size; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + r = risc_find_register_color_bytes(r->color, size); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, r, &sib); + else + ret = ctx->iops->P2G(c, f, r, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, r, &sib); + else + ret = ctx->iops->G2P(c, f, r, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_dec_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + + uint32_t opcode; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* r = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int size = vb->data_size; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + r = risc_find_register_color_bytes(r->color, size); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, r, &sib); + else + ret = ctx->iops->P2G(c, f, r, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, r, &sib); + else + ret = ctx->iops->G2P(c, f, r, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_inc_post_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + + uint32_t opcode; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vd = dst ->dag_node->var; + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int size = vb->data_size; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_dec_post_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + + uint32_t opcode; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vd = dst ->dag_node->var; + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int size = vb->data_size; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vi = index->dag_node->var; + scf_variable_t* vs = scale->dag_node->var; + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + scf_instruction_t* inst; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (vb->nb_dimentions > 1) { + + if (sib.index) + ret = ctx->iops->ADRSIB2G(c, f, rd, &sib); + else + ret = ctx->iops->ADRP2G(c, f, rd, sib.base, sib.disp); + return ret; + } + + if (sib.index) + return ctx->iops->SIB2G(c, f, rd, &sib); + + return ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_address_of_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vd = dst ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vi = index->dag_node->var; + scf_variable_t* vs = scale->dag_node->var; + + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (sib.index) + ret = ctx->iops->ADRSIB2G(c, f, rd, &sib); + else + ret = ctx->iops->ADRP2G(c, f, rd, sib.base, sib.disp); + + return ret; +} + +static int _risc_inst_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* rd = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst; + scf_function_t* f = risc->f; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_sib_t sib = {0}; + + int size = base->dag_node->var->data_size; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + return ctx->iops->P2G(c, f, rd, sib.base, 0, size); +} + +static int _risc_inst_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rax = risc_find_register("rax"); + scf_risc_OpCode_t* push; + scf_instruction_t* inst; + +#if 0 + push = risc_find_OpCode(SCF_RISC_PUSH, 8,8, SCF_RISC_G); + inst = ctx->iops->G(push, rax); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +#endif + return -1; +} + +static int _risc_inst_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rax = risc_find_register("rax"); + scf_risc_OpCode_t* pop; + scf_instruction_t* inst; +#if 0 + pop = risc_find_OpCode(SCF_RISC_POP, 8,8, SCF_RISC_G); + inst = ctx->iops->G(pop, rax); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +#endif + return -1; +} + +/* + +struct va_list +{ + uint8_t* iptr; + uint8_t* fptr; + uint8_t* optr; + + intptr_t ireg; + intptr_t freg; +}; +*/ + +static int _risc_inst_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_loge("c->srcs->size: %d\n", c->srcs->size); + assert(3 == c->srcs->size); + + scf_register_t* rbp = risc_find_register("rbp"); + scf_register_t* rptr = NULL; + scf_register_t* rap = NULL; + scf_instruction_t* inst = NULL; + scf_3ac_operand_t* ap = c->srcs->data[0]; + scf_3ac_operand_t* ptr = c->srcs->data[2]; + scf_risc_OpCode_t* mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_G2E); + scf_risc_OpCode_t* lea = risc_find_OpCode(SCF_RISC_LEA, 8, 8, SCF_RISC_E2G); + scf_variable_t* v = ap->dag_node->var; + + int offset_int = -f->args_int * 8 - 8; + int offset_float = -f->args_float * 8 - RISC_ABI_NB * 8 - 8; + int offset_others = 16; + + if (v->bp_offset >= 0) { + scf_loge("\n"); + return -1; + } +#if 0 + RISC_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); + RISC_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); + + inst = ctx->iops->P2G(lea, rptr, rbp, offset_int); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 0, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + + inst = ctx->iops->P2G(lea, rptr, rbp, offset_float); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 8, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + + inst = ctx->iops->P2G(lea, rptr, rbp, offset_others); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 16, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + + mov = risc_find_OpCode(SCF_RISC_MOV, 4, 8, SCF_RISC_I2E); + + inst = ctx->iops->I2P(mov, rap, 24, (uint8_t*)&f->args_int, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->I2P(mov, rap, 32, (uint8_t*)&f->args_float, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +#endif + return -1; +} + +static int _risc_inst_va_end_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + assert(2 == c->srcs->size); + + scf_register_t* rbp = risc_find_register("rbp"); + scf_register_t* rptr = NULL; + scf_register_t* rap = NULL; + scf_instruction_t* inst = NULL; + scf_3ac_operand_t* ap = c->srcs->data[0]; + scf_3ac_operand_t* ptr = c->srcs->data[1]; + scf_risc_OpCode_t* mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_G2E); + scf_risc_OpCode_t* xor = risc_find_OpCode(SCF_RISC_XOR, 8, 8, SCF_RISC_G2E); + scf_variable_t* v = ap->dag_node->var; + + if (v->bp_offset >= 0) { + scf_loge("\n"); + return -1; + } + + ptr->dag_node->var->tmp_flag = 1; + ptr->dag_node->color = -1; +#if 0 + RISC_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); + RISC_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); + + inst = ctx->iops->G2E(xor, rptr, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 0, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 8, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 16, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 24, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->G2P(mov, rap, 32, rptr); + RISC_INST_ADD_CHECK(c->instructions, inst); + + ptr->dag_node->var->tmp_flag = 0; + ptr->dag_node->color = 0; + ptr->dag_node->loaded = 0; + + assert(0 == scf_vector_del(rptr->dag_nodes, ptr->dag_node)); + return 0; +#endif + return -1; +} + +static int _risc_inst_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + assert(1 == c->dsts->size && 3 == c->srcs->size); + + scf_register_t* rbp = risc_find_register("rbp"); + scf_register_t* rd = NULL; // result + scf_register_t* rap = NULL; // ap + scf_register_t* rptr = NULL; // ptr + scf_instruction_t* inst = NULL; + + scf_instruction_t* inst_jge = NULL; + scf_instruction_t* inst_jmp = NULL; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* ap = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_3ac_operand_t* ptr = c->srcs->data[2]; + scf_variable_t* v = src->dag_node->var; + +#if 0 + scf_risc_OpCode_t* inc = risc_find_OpCode(SCF_RISC_INC, 8, 8, SCF_RISC_E); + scf_risc_OpCode_t* add = risc_find_OpCode(SCF_RISC_ADD, 4, 8, SCF_RISC_I2E); + scf_risc_OpCode_t* sub = risc_find_OpCode(SCF_RISC_SUB, 4, 8, SCF_RISC_I2E); + scf_risc_OpCode_t* cmp = risc_find_OpCode(SCF_RISC_CMP, 4, 8, SCF_RISC_I2E); + scf_risc_OpCode_t* mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_E2G); + scf_risc_OpCode_t* jge = risc_find_OpCode(SCF_RISC_JGE, 4, 4, SCF_RISC_I); + scf_risc_OpCode_t* jmp = risc_find_OpCode(SCF_RISC_JMP, 4, 4, SCF_RISC_I); + scf_risc_OpCode_t* mov2 = NULL; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + RISC_SELECT_REG_CHECK(&rap, ap ->dag_node, c, f, 1); + RISC_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); + + int is_float = scf_variable_float(v); + int size = risc_variable_size(v); + + uint32_t nints = RISC_ABI_NB; + uint32_t nfloats = RISC_ABI_NB; + uint32_t offset = 0; + uint32_t incptr = 8; + + int idx_offset = 24; + int ptr_offset = 0; + + if (is_float) { + idx_offset = 32; + ptr_offset = 8; + } + + inst = ctx->iops->I2P(cmp, rap, idx_offset, (uint8_t*)&nints, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst_jge = ctx->iops->I(jge, (uint8_t*)&offset, sizeof(offset)); + RISC_INST_ADD_CHECK(c->instructions, inst_jge); + + + inst = ctx->iops->P2G(mov, rptr, rap, ptr_offset); + RISC_INST_ADD_CHECK(c->instructions, inst); + offset += inst->len; + + inst = ctx->iops->I2P(sub, rap, ptr_offset, (uint8_t*)&incptr, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + offset += inst->len; + + inst_jmp = ctx->iops->I(jmp, (uint8_t*)&offset, sizeof(offset)); + RISC_INST_ADD_CHECK(c->instructions, inst_jmp); + offset += inst_jmp->len; + + uint8_t* p = (uint8_t*)&offset; + int i; + for (i = 0; i < 4; i++) + inst_jge->code[jge->nb_OpCodes + i] = p[i]; + + offset = 0; + inst = ctx->iops->P2G(mov, rptr, rap, 16); + RISC_INST_ADD_CHECK(c->instructions, inst); + offset += inst->len; + + inst = ctx->iops->I2P(add, rap, 16, (uint8_t*)&incptr, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + offset += inst->len; + + for (i = 0; i < 4; i++) + inst_jmp->code[jmp->nb_OpCodes + i] = p[i]; + + inst = ctx->iops->P(inc, rap, idx_offset, 8); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (is_float) { + if (4 == size) + mov2 = risc_find_OpCode(SCF_RISC_MOVSS, 4, 4, SCF_RISC_E2G); + else if (8 == size) + mov2 = risc_find_OpCode(SCF_RISC_MOVSD, 8, 8, SCF_RISC_E2G); + else + assert(0); + } else + mov2 = risc_find_OpCode(SCF_RISC_MOV, size, size, SCF_RISC_E2G); + + inst = ctx->iops->P2G(mov2, rd, rptr, 0); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +#endif + return -1; +} + +static int _risc_inst_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) { + scf_loge("\n"); + return -EINVAL; + } + + if (!c->srcs || c->srcs->size != 1) { + scf_loge("\n"); + return -EINVAL; + } + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_register_t* rd = NULL; + scf_instruction_t* inst; + + if (!src || !src->dag_node) { + scf_loge("\n"); + return -EINVAL; + } + assert(dst->dag_node->var->nb_pointers > 0); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + int ret = risc_select_reg(&rd, dst->dag_node, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + assert(dst->dag_node->color > 0); + + ret = risc_overflow_reg2(rd, dst->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + return ctx->iops->ADR2G(c, f, rd, src->dag_node->var); +} + +static int _risc_inst_div_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rs0 = NULL; + scf_register_t* rs1 = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s0->var)) { + + if (0 == s0->color) { + s0->color = -1; + s0->var->global_flag = 1; + + } else if (0 == s1->color) { + s1->color = -1; + s1->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + + inst = ctx->iops->FDIV(c, rd, rs0, rs1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s1->color) { + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + + int ret = risc_select_free_reg(&rs1, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs1, s1->var->data.u64, rs1->bytes); + if (ret < 0) + return ret; + + } else if (0 == s0->color) { + + if (!scf_variable_const_interger(s0->var)) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + + int ret = risc_select_free_reg(&rs0, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs0, s0->var->data.u64, rs0->bytes); + if (ret < 0) + return ret; + + } else { + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + } + + if (scf_variable_signed(s0->var)) + inst = ctx->iops->SDIV(c, rd, rs0, rs1); + else + inst = ctx->iops->DIV(c, rd, rs0, rs1); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_mod_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rs0 = NULL; + scf_register_t* rs1 = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src0->dag_node->var)) { + + assert(scf_variable_float(src1->dag_node->var)); + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s1->color) { + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + + int ret = risc_select_free_reg(&rs1, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs1, s1->var->data.u64, rs1->bytes); + if (ret < 0) + return ret; + + } else if (0 == s0->color) { + + if (!scf_variable_const_interger(s0->var)) { + scf_loge("\n"); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + + int ret = risc_select_free_reg(&rs0, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs0, s0->var->data.u64, rs0->bytes); + if (ret < 0) + return ret; + + } else { + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + } + + if (scf_variable_signed(s0->var)) + inst = ctx->iops->SDIV(c, rd, rs0, rs1); + else + inst = ctx->iops->DIV(c, rd, rs0, rs1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->MSUB(c, rd, rs1, rd, rs0); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_mul_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rm = NULL; + scf_register_t* rn = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (0 == s0->color) + SCF_XCHG(s0, s1); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s0->var)) { + + if (0 == s0->color) { + s0->color = -1; + s0->var->global_flag = 1; + + } else if (0 == s1->color) { + s1->color = -1; + s1->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->FMUL(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + + if (0 == s1->color) { + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s1->color = -1; + s1->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->MUL(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s1->color = 0; + s1->loaded = 0; + s1->var->tmp_flag = 0; + assert(0 == scf_vector_del(rm->dag_nodes, s1)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->MUL(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_mul_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s->var)) { + + if (0 == s->color) { + s->color = -1; + s->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->FMUL(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s->color = -1; + s->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->MUL(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s->color = 0; + s->loaded = 0; + s->var->tmp_flag = 0; + assert(0 == scf_vector_del(rs->dag_nodes, s)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->MUL(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_add_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rm = NULL; + scf_register_t* rn = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (0 == s0->color) + SCF_XCHG(s0, s1); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src0->dag_node->var)) { + + if (0 == s1->color) { + s1->color = -1; + s1->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->FADD(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (0 == s1->color) { + + if (scf_variable_const_string(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + uint64_t u = s1->var->data.u64; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + + inst = ctx->iops->ADD_IMM(c, rd, rn, u); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->ADD_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_add_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s->var)) { + + if (0 == s->color) { + s->color = -1; + s->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->FADD(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (0 == s->color) { + + if (scf_variable_const_string(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + uint64_t u = s->var->data.u64; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + inst = ctx->iops->ADD_IMM(c, rd, rd, u); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->ADD_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_sub_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s->var)) { + + if (0 == s->color) { + s->color = -1; + s->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->FSUB(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (0 == s->color) { + + if (scf_variable_const_string(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + uint64_t u = s->var->data.u64; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + inst = ctx->iops->SUB_IMM(c, rd, rd, u); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->SUB_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_sub_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rm = NULL; + scf_register_t* rn = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src0->dag_node->var)) { + + if (0 == s0->color) { + s0->color = -1; + s0->var->global_flag = 1; + + } else if (0 == s1->color) { + s1->color = -1; + s1->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->FSUB(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + int neg = 0; + + if (0 == s0->color) { + neg = 1; + SCF_XCHG(s0, s1); + } + + if (0 == s1->color) { + + if (scf_variable_const_string(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + uint64_t u = s1->var->data.u64; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + + inst = ctx->iops->SUB_IMM(c, rd, rn, u); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (neg) { + inst = ctx->iops->NEG(c, rd, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, s0, c, f, 1); + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->SUB_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int risc_inst_bit_op_assign(scf_native_t* ctx, scf_3ac_code_t* c, uint32_t op) +{ +} + +static int _risc_inst_bit_and_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rm = NULL; + scf_register_t* rn = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (0 == s0->color) + SCF_XCHG(s0, s1); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src0->dag_node->var)) { + + assert(scf_variable_float(src1->dag_node->var)); + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, d, c, f, 1); + + if (0 == s1->color) { + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s1->color = -1; + s1->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->AND_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s1->color = 0; + s1->loaded = 0; + s1->var->tmp_flag = 0; + assert(0 == scf_vector_del(rm->dag_nodes, s1)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->AND_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + RISC_INST_OP3_CHECK() + + scf_register_t* rm = NULL; + scf_register_t* rn = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + assert(0 != s0->color || 0 != s1->color); + + if (0 == s0->color) + SCF_XCHG(s0, s1); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src0->dag_node->var)) { + + assert(scf_variable_float(src1->dag_node->var)); + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rn, d, c, f, 1); + + if (0 == s1->color) { + + if (!scf_variable_const_interger(s1->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s1->color = -1; + s1->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->OR_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s1->color = 0; + s1->loaded = 0; + s1->var->tmp_flag = 0; + assert(0 == scf_vector_del(rm->dag_nodes, s1)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rm, s1, c, f, 1); + + inst = ctx->iops->OR_G(c, rd, rn, rm); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_and_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src->dag_node->var)) { + + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s->color = -1; + s->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->AND_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s->color = 0; + s->loaded = 0; + s->var->tmp_flag = 0; + assert(0 == scf_vector_del(rs->dag_nodes, s)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->AND_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_or_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src->dag_node->var)) { + + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + s->color = -1; + s->var->tmp_flag = 1; + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + s->color = 0; + s->loaded = 0; + s->var->tmp_flag = 0; + assert(0 == scf_vector_del(rs->dag_nodes, s)); + return 0; + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_teq_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs; + scf_instruction_t* inst; + + uint32_t opcode; + + if (0 == src->dag_node->color) { + scf_loge("src->dag_node->var: %p\n", src->dag_node->var); + return -1; + } + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + inst = ctx->iops->TEQ(c, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_setz_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ +#define SET_INIT() \ + if (!c->dsts || c->dsts->size != 1) \ + return -EINVAL; \ + \ + scf_risc_context_t* risc = ctx->priv; \ + scf_function_t* f = risc->f; \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + if (!dst || !dst->dag_node) \ + return -EINVAL; \ + \ + if (!c->instructions) { \ + c->instructions = scf_vector_alloc(); \ + if (!c->instructions) \ + return -ENOMEM; \ + } \ + \ + scf_register_t* rd; \ + scf_instruction_t* inst; \ + \ + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + SET_INIT(); + inst = ctx->iops->SETZ(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_setnz_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + SET_INIT(); + inst = ctx->iops->SETNZ(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} +static int _risc_inst_setge_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + SET_INIT(); + inst = ctx->iops->SETGE(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} +static int _risc_inst_setgt_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + SET_INIT(); + inst = ctx->iops->SETGT(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} +static int _risc_inst_setlt_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + SET_INIT(); + inst = ctx->iops->SETLT(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} +static int _risc_inst_setle_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + SET_INIT(); + inst = ctx->iops->SETLE(c, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_logic_not_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + int ret = _risc_inst_teq_handler(ctx, c); + if (ret < 0) + return ret; + + return _risc_inst_setz_handler(ctx, c); +} + +static int _risc_inst_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* s0 = c->srcs->data[0]; + scf_3ac_operand_t* s1 = c->srcs->data[1]; + + if (!s0 || !s0->dag_node) + return -EINVAL; + + if (!s1 || !s1->dag_node) + return -EINVAL; + + scf_instruction_t* inst; + scf_register_t* rs1 = NULL; + scf_register_t* rs0 = NULL; + scf_dag_node_t* ds0 = s0->dag_node; + scf_dag_node_t* ds1 = s1->dag_node; + scf_rela_t* rela = NULL; + + uint32_t opcode; + + if (ds0->var->size != ds1->var->size) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (0 == ds0->color) { + scf_loge("src0 should be a var\n"); + if (ds0->var->w) + scf_loge("src0: '%s'\n", ds0->var->w->text->data); + else + scf_loge("src0: v_%#lx\n", 0xffff & (uintptr_t)ds0->var); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rs0, ds0, c, f, 1); + + if (scf_variable_float(ds0->var)) { + + if (0 == ds1->color) { + ds1->color = -1; + ds1->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rs0, ds0, c, f, 1); + RISC_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); + + inst = ctx->iops->FCMP(c, rs0, rs1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (0 == ds1->color) { + + uint64_t u = ds1->var->data.u64; + + if (u <= 0xfff) + inst = ctx->iops->CMP_IMM(c, rs0, u); + + else if (0 == (u & 0xfff) && (u >> 12) <= 0xfff) + inst = ctx->iops->CMP_IMM(c, rs0, u); + + else { + ds1->loaded = 0; + ds1->color = -1; + RISC_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); + + inst = ctx->iops->CMP_G(c, rs0, rs1); + + ds1->loaded = 0; + ds1->color = 0; + assert(0 == scf_vector_del(rs1->dag_nodes, ds1)); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rs1, ds1, c, f, 1); + + inst = ctx->iops->CMP_G(c, rs0, rs1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +#define RISC_INST_CMP_SET(name, cc) \ +static int _risc_inst_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c) \ +{ \ + int ret = _risc_inst_cmp_handler(ctx, c); \ + if (ret < 0) \ + return ret; \ + return _risc_inst_set##cc##_handler(ctx, c); \ +} +RISC_INST_CMP_SET(eq, z) +RISC_INST_CMP_SET(ne, nz) +RISC_INST_CMP_SET(gt, gt) +RISC_INST_CMP_SET(ge, ge) +RISC_INST_CMP_SET(lt, lt) +RISC_INST_CMP_SET(le, le) + +static int _risc_inst_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (0 == dst->dag_node->color) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + scf_variable_t* vs = s->var; + scf_variable_t* vd = d->var; + + int src_size = risc_variable_size(vs); + int dst_size = risc_variable_size(vd); + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + uint32_t opcode = 0; + + if (scf_variable_float(vs)) { + + if (0 == s->color) { + s->color = -1; + vs->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + if (scf_variable_float(vd)) { + + if (rd->bytes == rs->bytes) + inst = ctx->iops->FMOV_G(c, rd, rs); + + else if (4 == rs->bytes) + inst = ctx->iops->CVTSS2SD(c, rd, rs); + else + inst = ctx->iops->CVTSD2SS(c, rd, rs); + + } else { + if (scf_variable_signed(vd)) + inst = ctx->iops->CVTF2SI(c, rd, rs); + else + inst = ctx->iops->CVTF2UI(c, rd, rs); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + + } else if (scf_variable_float(vd)) { + + if (0 == s->color) { + + if (!scf_variable_const_interger(vs)) + return -EINVAL; + + if (src_size < dst_size) + scf_variable_extend_bytes(vs, 8); + + int ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, dst_size); + if (ret < 0) + return ret; + + } else + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + if (scf_variable_signed(vs)) + inst = ctx->iops->CVTSI2F(c, rd, rs); + else + inst = ctx->iops->CVTUI2F(c, rd, rs); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (vs->nb_dimentions > 0) + return ctx->iops->ADR2G(c, f, rd, vs); + + scf_logd("src_size: %d, dst_size: %d\n", src_size, dst_size); + + if (0 == s->color) { + + if (!scf_variable_const_interger(vs)) + return -EINVAL; + + if (src_size < dst_size) + scf_variable_extend_bytes(vs, 8); + + return ctx->iops->I2G(c, rd, vs->data.u64, dst_size); + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + if (src_size < dst_size) { + + if (scf_variable_signed(vs)) + inst = ctx->iops->MOVSX(c, rd, rs, src_size); + else + inst = ctx->iops->MOVZX(c, rd, rs, src_size); + } else + inst = ctx->iops->MOV_G(c, rd, rs); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_div_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(s->var)) { + + if (0 == s->color) { + s->color = -1; + s->var->global_flag = 1; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->FDIV(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + int ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, s->var->data.u64, rs->bytes); + if (ret < 0) + return ret; + + } else + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + if (scf_variable_signed(s->var)) + inst = ctx->iops->SDIV(c, rd, rd, rs); + else + inst = ctx->iops->DIV(c, rd, rd, rs); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (src->dag_node->var->size != dst->dag_node->var->size) + return -EINVAL; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_register_t* r = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + assert(0 != d->color); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (scf_variable_float(src->dag_node->var)) { + + assert(scf_variable_float(dst->dag_node->var)); + return -EINVAL; + } + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + if (!scf_variable_const_interger(s->var)) { + scf_loge("\n"); + return -EINVAL; + } + + int ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, s->var->data.u64, rs->bytes); + if (ret < 0) + return ret; + + } else + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + int ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + if (scf_variable_signed(s->var)) + inst = ctx->iops->SDIV(c, r, rd, rs); + else + inst = ctx->iops->DIV(c, r, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->MSUB(c, rd, rs, r, rd); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size < 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = NULL; + scf_variable_t* v = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_register_t* sp = risc_find_register("sp"); + scf_register_t* fp = risc_find_register("fp"); + + scf_risc_OpCode_t* pop; + scf_risc_OpCode_t* mov; + scf_risc_OpCode_t* ret; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + int i; + for (i = 0; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + + v = src->dag_node->var; + + int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + + if (i > 0 && is_float) { + scf_loge("\n"); + return -1; + } + + int retsize = size > 4 ? 8 : 4; + + if (is_float) { + rd = risc_find_register_type_id_bytes(is_float, 0, retsize); + + if (0 == src->dag_node->color) { + src->dag_node->color = -1; + v->global_flag = 1; + } + + scf_loge("\n"); + return -1; + + } else { + rd = risc_find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], retsize); + + if (0 == src->dag_node->color) { + if (rd->bytes > size) + scf_variable_extend_bytes(v, rd->bytes); + + int ret = ctx->iops->I2G(c, rd, v->data.u64, rd->bytes); + if (ret < 0) + return ret; + continue; + } + } + + scf_logd("rd: %s, rd->dag_nodes->size: %d\n", rd->name, rd->dag_nodes->size); + + if (src->dag_node->color > 0) { + + int start = c->instructions->size; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + if (!RISC_COLOR_CONFLICT(rd->color, rs->color)) { + + int ret = risc_save_reg(rd, c, f); + if (ret < 0) + return ret; + + uint32_t opcode; + + if (rd->bytes > size) { + + if (scf_variable_signed(v)) + inst = ctx->iops->MOVSX(c, rd, rs, size); + + else if (1 == size || 2 == size) + inst = ctx->iops->MOVZX(c, rd, rs, size); + else + inst = ctx->iops->MOV_G(c, rd, rs); + } else + inst = ctx->iops->MOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + scf_instruction_t* tmp; + int j; + int k; + for (j = start; j < c->instructions->size; j++) { + tmp = c->instructions->data[j]; + + for (k = j - 1; k >= j - start; k--) + c->instructions->data[k + 1] = c->instructions->data[k]; + + c->instructions->data[j - start] = tmp; + } + } + } else { + int ret = risc_save_reg(rd, c, f); + if (ret < 0) + return ret; + + ret = ctx->iops->M2G(c, f, rd, NULL, v); + if (ret < 0) + return ret; + } + } + return 0; +} + +static int _risc_inst_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* dst = c->srcs->data[0]; + scf_3ac_operand_t* data = c->srcs->data[1]; + scf_3ac_operand_t* count = c->srcs->data[2]; + scf_instruction_t* inst = NULL; + + scf_register_t* rax = risc_find_register("rax"); + scf_register_t* rcx = risc_find_register("rcx"); + scf_register_t* rdi = risc_find_register("rdi"); + scf_register_t* rd; + scf_risc_OpCode_t* mov; + scf_risc_OpCode_t* stos; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + int ret = risc_overflow_reg2(rdi, dst->dag_node, c, f); + if (ret < 0) + return ret; + + ret = risc_overflow_reg2(rax, data->dag_node, c, f); + if (ret < 0) + return ret; + + ret = risc_overflow_reg2(rcx, count->dag_node, c, f); + if (ret < 0) + return ret; + +#if 0 +#define RISC_MEMSET_LOAD_REG(r, dn) \ + do { \ + int size = risc_variable_size(dn->var); \ + assert(8 == size); \ + \ + if (0 == dn->color) { \ + mov = risc_find_OpCode(SCF_RISC_MOV, size, size, SCF_RISC_I2G); \ + inst = ctx->iops->I2G(mov, r, (uint8_t*)&dn->var->data, size); \ + RISC_INST_ADD_CHECK(c->instructions, inst); \ + \ + } else { \ + if (dn->color < 0) \ + dn->color = r->color; \ + RISC_SELECT_REG_CHECK(&rd, dn, c, f, 1); \ + \ + if (!RISC_COLOR_CONFLICT(rd->color, r->color)) { \ + mov = risc_find_OpCode(SCF_RISC_MOV, size, size, SCF_RISC_G2E); \ + inst = ctx->iops->G2E(mov, r, rd); \ + RISC_INST_ADD_CHECK(c->instructions, inst); \ + } \ + } \ + } while (0) + RISC_MEMSET_LOAD_REG(rdi, dst ->dag_node); + RISC_MEMSET_LOAD_REG(rax, data ->dag_node); + RISC_MEMSET_LOAD_REG(rcx, count->dag_node); + + stos = risc_find_OpCode(SCF_RISC_STOS, 1, 8, SCF_RISC_G); + inst = risc_make_inst(stos, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +#endif + return -1; +} + +static int _risc_inst_nop_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + return 0; +} + +static int _risc_inst_end_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* sp = risc_find_register("sp"); + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* r; + + + scf_instruction_t* inst = NULL; + + int i; + for (i = RISC_ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) { + + r = risc_find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8); + + if (!r->used) { + r = risc_find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4); + + if (!r->used) + continue; + } + + inst = ctx->iops->POP(c, r); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + inst = ctx->iops->MOV_SP(c, sp, fp); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->POP(c, fp); + RISC_INST_ADD_CHECK(c->instructions, inst); + + inst = ctx->iops->RET(c); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +#define RISC_INST_JMP(name, NAME) \ +static int _risc_inst_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c) \ +{ \ + if (!c->dsts || c->dsts->size != 1) \ + return -EINVAL; \ + \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + scf_instruction_t* inst = NULL; \ + \ + if (!dst->bb) \ + return -EINVAL; \ + \ + if (!c->instructions) { \ + c->instructions = scf_vector_alloc(); \ + if (!c->instructions) \ + return -ENOMEM; \ + } \ + \ + inst = ctx->iops->NAME(c); \ + RISC_INST_ADD_CHECK(c->instructions, inst); \ + return 0;\ +} + +RISC_INST_JMP(goto, JMP) +RISC_INST_JMP(jz, JZ) +RISC_INST_JMP(jnz, JNZ) +RISC_INST_JMP(jgt, JGT) +RISC_INST_JMP(jge, JGE) +RISC_INST_JMP(jlt, JLT) +RISC_INST_JMP(jle, JLE) + +RISC_INST_JMP(ja, JA) +RISC_INST_JMP(jb, JB) +RISC_INST_JMP(jae, JAE) +RISC_INST_JMP(jbe, JBE) + +static int _risc_inst_load_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* r = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_dag_node_t* dn = dst->dag_node; + + int ret; + int i; + + if (dn->color < 0) + return 0; + + scf_variable_t* v = dn->var; + + assert(dn->color > 0); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + r = risc_find_register_color(dn->color); + + if (risc_reg_used(r, dn)) { + dn->color = -1; + dn->loaded = 0; + scf_vector_del(r->dag_nodes, dn); + return 0; + } + + ret = risc_load_reg(r, dn, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = scf_vector_add_unique(r->dag_nodes, dn); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + return 0; +} + +static int _risc_inst_reload_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* r = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_dag_node_t* dn = dst->dag_node; + scf_dag_node_t* dn2 = NULL; + + int ret; + int i; + + if (dn->color < 0) + return 0; + assert(dn->color > 0); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + r = risc_find_register_color(dn->color); + + ret = risc_overflow_reg2(r, dn, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + dn->loaded = 0; + ret = risc_load_reg(r, dn, c, f); + if (ret < 0) + return ret; + + ret = scf_vector_add_unique(r->dag_nodes, dn); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + return 0; +} + +static int _risc_inst_save_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_dag_node_t* dn = src->dag_node; + + if (dn->color < 0) + return 0; + + if (!dn->loaded) + return 0; + + scf_variable_t* v = dn->var; + assert(dn->color > 0); + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + return risc_save_var(dn, c, f); +} + +static int _risc_inst_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + scf_variable_t* v = s->var; + + uint32_t opcode; + + assert(0 != d->color); + + int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (is_float) { + assert(scf_variable_float(v)); + + if (0 == s->color) { + s->color = -1; + v->global_flag = 1; + return ctx->iops->M2GF(c, f, rd, NULL, v); + } + + RISC_SELECT_REG_CHECK(&rs, d, c, f, 1); + + inst = ctx->iops->FMOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; + } + + if (0 == s->color) { + + if (scf_variable_const_string(v)) + return ctx->iops->ISTR2G(c, f, rd, v); + + if (!scf_variable_const_interger(v)) { + scf_loge("\n"); + return -EINVAL; + } + + if (rd->bytes > size) + scf_variable_extend_bytes(v, rd->bytes); + + return ctx->iops->I2G(c, rd, v->data.u64, rd->bytes); + } + + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + inst = ctx->iops->MOV_G(c, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_shift(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src0 = c->srcs->data[0]; + scf_3ac_operand_t* src1 = c->srcs->data[1]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + + if (!src0 || !src0->dag_node) + return -EINVAL; + + if (!src1 || !src1->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs0 = NULL; + scf_register_t* rs1 = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst ->dag_node; + scf_dag_node_t* s0 = src0->dag_node; + scf_dag_node_t* s1 = src1->dag_node; + + uint32_t opcode; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s0->color) { + + if (scf_variable_signed(s0->var)) + scf_variable_sign_extend(s0->var, 8); + else + scf_variable_zero_extend(s0->var, 8); + + int ret = ctx->iops->I2G(c, rd, s0->var->data.u64, rd->bytes); + if (ret < 0) + return ret; + + rs0 = rd; + } else + RISC_SELECT_REG_CHECK(&rs0, s0, c, f, 1); + + if (0 == s1->color) { + + int ret = risc_select_free_reg(&rs1, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs1, s1->var->data.u64, 1); + if (ret < 0) + return ret; + } else + RISC_SELECT_REG_CHECK(&rs1, s1, c, f, 1); + + + if (SCF_OP_SHR == c->op->type) { + + if (scf_variable_signed(s0->var)) + inst = ctx->iops->ASR(c, rd, rs0, rs1); + else + inst = ctx->iops->SHR(c, rd, rs0, rs1); + } else + inst = ctx->iops->SHL(c, rd, rs0, rs1); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_shift_assign(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!dst || !dst->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_instruction_t* inst = NULL; + scf_dag_node_t* d = dst->dag_node; + scf_dag_node_t* s = src->dag_node; + + uint32_t opcode; + + RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); + + if (0 == s->color) { + + int ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, s->var->data.u64, 1); + if (ret < 0) + return ret; + } else + RISC_SELECT_REG_CHECK(&rs, s, c, f, 1); + + if (SCF_OP_SHR == c->op->type) { + + if (scf_variable_signed(s->var)) + inst = ctx->iops->ASR(c, rd, rd, rs); + else + inst = ctx->iops->SHR(c, rd, rd, rs); + } else + inst = ctx->iops->SHL(c, rd, rd, rs); + + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_shl_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + return _risc_inst_shift(ctx, c); +} + +static int _risc_inst_shr_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + return _risc_inst_shift(ctx, c); +} + +static int _risc_inst_shl_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + return _risc_inst_shift_assign(ctx, c); +} + +static int _risc_inst_shr_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + return _risc_inst_shift_assign(ctx, c); +} + +static int _risc_inst_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + return ctx->iops->G2P(c, f, rs, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_add_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + + uint32_t opcode; + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + if (!is_float) + inst = ctx->iops->ADD_G(c, rd, rd, rs); + else + inst = ctx->iops->FADD(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_sub_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + uint32_t opcode; + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + if (!is_float) + inst = ctx->iops->SUB_G(c, rd, rd, rs); + else + inst = ctx->iops->FSUB(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_and_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + int is_float = scf_variable_float(vs); + if (is_float) + return -EINVAL; + + if (0 == src->dag_node->color) { + + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + uint32_t opcode; + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->AND_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_or_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 2) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* src = c->srcs->data[1]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + scf_sib_t sib = {0}; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + + uint32_t opcode; + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_3ac_operand_t* src = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + return ctx->iops->G2P(c, f, rs, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_add_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_3ac_operand_t* src = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_G(c, rd, rd, rs); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_sub_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_3ac_operand_t* src = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_and_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_3ac_operand_t* src = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_or_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* member = c->srcs->data[1]; + scf_3ac_operand_t* src = c->srcs->data[2]; + scf_instruction_t* inst; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!member || !member->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vs = src ->dag_node->var; + scf_variable_t* vb = base ->dag_node->var; + scf_variable_t* vm = member->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + + int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); + if (ret < 0) + return ret; + + if (scf_variable_is_struct(vm) || scf_variable_is_array(vm)) + return -EINVAL; + + int is_float = scf_variable_float(vs); + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, sib.size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, sib.size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, sib.size); +} + +static int _risc_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 4) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_3ac_operand_t* src = c->srcs->data[3]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + scf_variable_t* vs = src ->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int is_float = scf_variable_float(vs); + int size = risc_variable_size (vs); + + if (size > vscale->data.i) + size = vscale->data.i; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rs, &sib); + else + ret = ctx->iops->G2P(c, f, rs, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_add_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 4) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_3ac_operand_t* src = c->srcs->data[3]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + scf_variable_t* vs = src ->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int is_float = scf_variable_float(vs); + int size = risc_variable_size (vs); + + if (size > vscale->data.i) + size = vscale->data.i; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + if (!is_float) + inst = ctx->iops->ADD_G(c, rd, rd, rs); + else + inst = ctx->iops->FADD(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_sub_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 4) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_3ac_operand_t* src = c->srcs->data[3]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + scf_variable_t* vs = src ->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int is_float = scf_variable_float(vs); + int size = risc_variable_size (vs); + + if (size > vscale->data.i) + size = vscale->data.i; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (0 == src->dag_node->color) { + + if (is_float) { + + src->dag_node->color = -1; + vs->global_flag = 1; + + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + } else { + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, size); + } + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + if (!is_float) + inst = ctx->iops->SUB_G(c, rd, rd, rs); + else + inst = ctx->iops->FSUB(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + rs = rd; + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_and_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 4) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_3ac_operand_t* src = c->srcs->data[3]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + scf_variable_t* vs = src ->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int is_float = scf_variable_float(vs); + int size = risc_variable_size (vs); + + if (size > vscale->data.i) + size = vscale->data.i; + + if (is_float) + return -EINVAL; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (0 == src->dag_node->color) { + + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, size); + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->AND_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + ret = ctx->iops->G2SIB(c, f, rd, &sib); + else + ret = ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); + return ret; +} + +static int _risc_inst_or_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 4) + return -EINVAL; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* index = c->srcs->data[1]; + scf_3ac_operand_t* scale = c->srcs->data[2]; + scf_3ac_operand_t* src = c->srcs->data[3]; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!index || !index->dag_node) + return -EINVAL; + + if (!scale || !scale->dag_node) + return -EINVAL; + + if (!src || !src->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_variable_t* vscale = scale->dag_node->var; + scf_variable_t* vb = base->dag_node->var; + scf_variable_t* vs = src ->dag_node->var; + + scf_register_t* rd = NULL; + scf_register_t* rs = NULL; + scf_sib_t sib = {0}; + scf_instruction_t* inst; + + int is_float = scf_variable_float(vs); + int size = risc_variable_size (vs); + + if (size > vscale->data.i) + size = vscale->data.i; + + if (is_float) + return -EINVAL; + + int ret = risc_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (0 == src->dag_node->color) { + + ret = risc_select_free_reg(&rs, c, f, 0); + if (ret < 0) + return ret; + + ret = ctx->iops->I2G(c, rs, vs->data.u64, size); + if (ret < 0) + return ret; + + rs = risc_find_register_color_bytes(rs->color, size); + } else + RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + + ret = risc_select_free_reg(&rd, c, f, is_float); + if (ret < 0) + return ret; + + if (sib.index) + ret = ctx->iops->SIB2G(c, f, rd, &sib); + else + ret = ctx->iops->P2G(c, f, rd, sib.base, sib.disp, sib.size); + if (ret < 0) + return ret; + + inst = ctx->iops->OR_G(c, rd, rd, rs); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (sib.index) + return ctx->iops->G2SIB(c, f, rd, &sib); + + return ctx->iops->G2P(c, f, rd, sib.base, sib.disp, size); +} + +static int _risc_inst_dec_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) { + scf_loge("\n"); + return -EINVAL; + } + + scf_register_t* r = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_instruction_t* inst; + scf_function_t* f = risc->f; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_sib_t sib = {0}; + + int size = base->dag_node->var->data_size; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + r = risc_find_register_color_bytes(r->color, size); + + ret = ctx->iops->P2G(c, f, r, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, r, sib.base, 0, size); +} + +static int _risc_inst_inc_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) { + scf_loge("\n"); + return -EINVAL; + } + + scf_register_t* r = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_instruction_t* inst; + scf_function_t* f = risc->f; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_sib_t sib = {0}; + + int size = base->dag_node->var->data_size; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + r = risc_find_register_color_bytes(r->color, size); + + ret = ctx->iops->P2G(c, f, r, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, r, r, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return ctx->iops->G2P(c, f, r, sib.base, 0, size); +} + +static int _risc_inst_dec_post_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* rd = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst; + scf_function_t* f = risc->f; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_sib_t sib = {0}; + + int size = base->dag_node->var->data_size; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + ret = ctx->iops->P2G(c, f, rd, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + ret = ctx->iops->G2P(c, f, rd, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static int _risc_inst_inc_post_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) +{ + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_register_t* rd = NULL; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* base = c->srcs->data[0]; + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_instruction_t* inst; + scf_function_t* f = risc->f; + + if (!base || !base->dag_node) + return -EINVAL; + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + scf_sib_t sib = {0}; + + int size = base->dag_node->var->data_size; + + int ret = risc_dereference_reg(&sib, base->dag_node, NULL, c, f); + if (ret < 0) + return ret; + + RISC_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); + + ret = ctx->iops->P2G(c, f, rd, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->ADD_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + + ret = ctx->iops->G2P(c, f, rd, sib.base, 0, size); + if (ret < 0) + return ret; + + inst = ctx->iops->SUB_IMM(c, rd, rd, 1); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +static risc_inst_handler_t risc_inst_handlers[] = { + + {SCF_OP_CALL, _risc_inst_call_handler}, + {SCF_OP_ARRAY_INDEX, _risc_inst_array_index_handler}, + {SCF_OP_POINTER, _risc_inst_pointer_handler}, + + {SCF_OP_TYPE_CAST, _risc_inst_cast_handler}, + {SCF_OP_LOGIC_NOT, _risc_inst_logic_not_handler}, + {SCF_OP_BIT_NOT, _risc_inst_bit_not_handler}, + {SCF_OP_NEG, _risc_inst_neg_handler}, + + {SCF_OP_VA_START, _risc_inst_va_start_handler}, + {SCF_OP_VA_ARG, _risc_inst_va_arg_handler}, + {SCF_OP_VA_END, _risc_inst_va_end_handler}, + + {SCF_OP_INC, _risc_inst_inc_handler}, + {SCF_OP_DEC, _risc_inst_dec_handler}, + + {SCF_OP_INC_POST, _risc_inst_inc_post_handler}, + {SCF_OP_DEC_POST, _risc_inst_dec_post_handler}, + + {SCF_OP_DEREFERENCE, _risc_inst_dereference_handler}, + {SCF_OP_ADDRESS_OF, _risc_inst_address_of_handler}, + + {SCF_OP_MUL, _risc_inst_mul_handler}, + {SCF_OP_DIV, _risc_inst_div_handler}, + {SCF_OP_MOD, _risc_inst_mod_handler}, + + {SCF_OP_ADD, _risc_inst_add_handler}, + {SCF_OP_SUB, _risc_inst_sub_handler}, + + {SCF_OP_SHL, _risc_inst_shl_handler}, + {SCF_OP_SHR, _risc_inst_shr_handler}, + + {SCF_OP_BIT_AND, _risc_inst_bit_and_handler}, + {SCF_OP_BIT_OR, _risc_inst_bit_or_handler}, + + {SCF_OP_3AC_TEQ, _risc_inst_teq_handler}, + {SCF_OP_3AC_CMP, _risc_inst_cmp_handler}, + + {SCF_OP_3AC_SETZ, _risc_inst_setz_handler}, + {SCF_OP_3AC_SETNZ, _risc_inst_setnz_handler}, + {SCF_OP_3AC_SETGT, _risc_inst_setgt_handler}, + {SCF_OP_3AC_SETGE, _risc_inst_setge_handler}, + {SCF_OP_3AC_SETLT, _risc_inst_setlt_handler}, + {SCF_OP_3AC_SETLE, _risc_inst_setle_handler}, + + {SCF_OP_EQ, _risc_inst_eq_handler}, + {SCF_OP_NE, _risc_inst_ne_handler}, + {SCF_OP_GT, _risc_inst_gt_handler}, + {SCF_OP_GE, _risc_inst_ge_handler}, + {SCF_OP_LT, _risc_inst_lt_handler}, + {SCF_OP_LE, _risc_inst_le_handler}, + + {SCF_OP_ASSIGN, _risc_inst_assign_handler}, + + {SCF_OP_ADD_ASSIGN, _risc_inst_add_assign_handler}, + {SCF_OP_SUB_ASSIGN, _risc_inst_sub_assign_handler}, + + {SCF_OP_MUL_ASSIGN, _risc_inst_mul_assign_handler}, + {SCF_OP_DIV_ASSIGN, _risc_inst_div_assign_handler}, + {SCF_OP_MOD_ASSIGN, _risc_inst_mod_assign_handler}, + + {SCF_OP_SHL_ASSIGN, _risc_inst_shl_assign_handler}, + {SCF_OP_SHR_ASSIGN, _risc_inst_shr_assign_handler}, + + {SCF_OP_AND_ASSIGN, _risc_inst_and_assign_handler}, + {SCF_OP_OR_ASSIGN, _risc_inst_or_assign_handler}, + + {SCF_OP_RETURN, _risc_inst_return_handler}, + {SCF_OP_GOTO, _risc_inst_goto_handler}, + + {SCF_OP_3AC_JZ, _risc_inst_jz_handler}, + {SCF_OP_3AC_JNZ, _risc_inst_jnz_handler}, + {SCF_OP_3AC_JGT, _risc_inst_jgt_handler}, + {SCF_OP_3AC_JGE, _risc_inst_jge_handler}, + {SCF_OP_3AC_JLT, _risc_inst_jlt_handler}, + {SCF_OP_3AC_JLE, _risc_inst_jle_handler}, + + {SCF_OP_3AC_JA, _risc_inst_ja_handler}, + {SCF_OP_3AC_JB, _risc_inst_jb_handler}, + {SCF_OP_3AC_JAE, _risc_inst_jae_handler}, + {SCF_OP_3AC_JBE, _risc_inst_jbe_handler}, + + {SCF_OP_3AC_NOP, _risc_inst_nop_handler}, + {SCF_OP_3AC_END, _risc_inst_end_handler}, + + {SCF_OP_3AC_SAVE, _risc_inst_save_handler}, + {SCF_OP_3AC_LOAD, _risc_inst_load_handler}, + + {SCF_OP_3AC_RESAVE, _risc_inst_save_handler}, + {SCF_OP_3AC_RELOAD, _risc_inst_reload_handler}, + + {SCF_OP_3AC_INC, _risc_inst_inc_handler}, + {SCF_OP_3AC_DEC, _risc_inst_dec_handler}, + + {SCF_OP_3AC_PUSH_RAX, _risc_inst_push_rax_handler}, + {SCF_OP_3AC_POP_RAX, _risc_inst_pop_rax_handler}, + + {SCF_OP_3AC_MEMSET, _risc_inst_memset_handler}, + + {SCF_OP_3AC_ASSIGN_DEREFERENCE, _risc_inst_assign_dereference_handler}, + {SCF_OP_3AC_ASSIGN_ARRAY_INDEX, _risc_inst_assign_array_index_handler}, + {SCF_OP_3AC_ASSIGN_POINTER, _risc_inst_assign_pointer_handler}, + + {SCF_OP_3AC_ADD_ASSIGN_DEREFERENCE, _risc_inst_add_assign_dereference_handler}, + {SCF_OP_3AC_ADD_ASSIGN_ARRAY_INDEX, _risc_inst_add_assign_array_index_handler}, + {SCF_OP_3AC_ADD_ASSIGN_POINTER, _risc_inst_add_assign_pointer_handler}, + + {SCF_OP_3AC_SUB_ASSIGN_DEREFERENCE, _risc_inst_sub_assign_dereference_handler}, + {SCF_OP_3AC_SUB_ASSIGN_ARRAY_INDEX, _risc_inst_sub_assign_array_index_handler}, + {SCF_OP_3AC_SUB_ASSIGN_POINTER, _risc_inst_sub_assign_pointer_handler}, + + {SCF_OP_3AC_AND_ASSIGN_DEREFERENCE, _risc_inst_and_assign_dereference_handler}, + {SCF_OP_3AC_AND_ASSIGN_ARRAY_INDEX, _risc_inst_and_assign_array_index_handler}, + {SCF_OP_3AC_AND_ASSIGN_POINTER, _risc_inst_and_assign_pointer_handler}, + + {SCF_OP_3AC_OR_ASSIGN_DEREFERENCE, _risc_inst_or_assign_dereference_handler}, + {SCF_OP_3AC_OR_ASSIGN_ARRAY_INDEX, _risc_inst_or_assign_array_index_handler}, + {SCF_OP_3AC_OR_ASSIGN_POINTER, _risc_inst_or_assign_pointer_handler}, + + {SCF_OP_3AC_INC_DEREFERENCE, _risc_inst_inc_dereference_handler}, + {SCF_OP_3AC_INC_ARRAY_INDEX, _risc_inst_inc_array_index_handler}, + {SCF_OP_3AC_INC_POINTER, _risc_inst_inc_pointer_handler}, + + {SCF_OP_3AC_INC_POST_DEREFERENCE, _risc_inst_inc_post_dereference_handler}, + {SCF_OP_3AC_INC_POST_ARRAY_INDEX, _risc_inst_inc_post_array_index_handler}, + {SCF_OP_3AC_INC_POST_POINTER, _risc_inst_inc_post_pointer_handler}, + + {SCF_OP_3AC_DEC_DEREFERENCE, _risc_inst_dec_dereference_handler}, + {SCF_OP_3AC_DEC_ARRAY_INDEX, _risc_inst_dec_array_index_handler}, + {SCF_OP_3AC_DEC_POINTER, _risc_inst_dec_pointer_handler}, + + {SCF_OP_3AC_DEC_POST_DEREFERENCE, _risc_inst_dec_post_dereference_handler}, + {SCF_OP_3AC_DEC_POST_ARRAY_INDEX, _risc_inst_dec_post_array_index_handler}, + {SCF_OP_3AC_DEC_POST_POINTER, _risc_inst_dec_post_pointer_handler}, + + {SCF_OP_3AC_ADDRESS_OF_ARRAY_INDEX, _risc_inst_address_of_array_index_handler}, + {SCF_OP_3AC_ADDRESS_OF_POINTER, _risc_inst_address_of_pointer_handler}, +}; + +risc_inst_handler_t* scf_risc_find_inst_handler(const int op_type) +{ + int i; + for (i = 0; i < sizeof(risc_inst_handlers) / sizeof(risc_inst_handlers[0]); i++) { + + risc_inst_handler_t* h = &(risc_inst_handlers[i]); + + if (op_type == h->type) + return h; + } + return NULL; +} + +scf_instruction_t* risc_make_inst(scf_3ac_code_t* c, uint32_t opcode) +{ + scf_instruction_t* inst; + + inst = calloc(1, sizeof(scf_instruction_t)); + if (!inst) + return NULL; + + inst->c = c; + inst->code[0] = opcode & 0xff; + inst->code[1] = (opcode >> 8) & 0xff; + inst->code[2] = (opcode >> 16) & 0xff; + inst->code[3] = (opcode >> 24) & 0xff; + inst->len = 4; + + return inst; +} diff --git a/native/risc/scf_risc_opcode.c b/native/risc/scf_risc_opcode.c new file mode 100644 index 0000000..b12e502 --- /dev/null +++ b/native/risc/scf_risc_opcode.c @@ -0,0 +1,362 @@ +#include"scf_risc.h" + +scf_risc_OpCode_t risc_OpCodes[] = { + {SCF_RISC_PUSH, "push", 1, {0x50, 0x0, 0x0},1, 8,8, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_POP, "pop", 1, {0x58, 0x0, 0x0},1, 8,8, SCF_RISC_G, 0,0, 0,{0,0}}, + + {SCF_RISC_INC, "inc", 2, {0xfe, 0x0, 0x0},1, 1,1, SCF_RISC_E, 0,1, 0,{0,0}}, + {SCF_RISC_INC, "inc", 2, {0xff, 0x0, 0x0},1, 2,2, SCF_RISC_E, 0,1, 0,{0,0}}, + {SCF_RISC_INC, "inc", 2, {0xff, 0x0, 0x0},1, 4,4, SCF_RISC_E, 0,1, 0,{0,0}}, + {SCF_RISC_INC, "inc", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_RISC_E, 0,1, 0,{0,0}}, + + {SCF_RISC_DEC, "dec", 2, {0xfe, 0x0, 0x0},1, 1,1, SCF_RISC_E, 1,1, 0,{0,0}}, + {SCF_RISC_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 2,2, SCF_RISC_E, 1,1, 0,{0,0}}, + {SCF_RISC_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 4,4, SCF_RISC_E, 1,1, 0,{0,0}}, + {SCF_RISC_DEC, "dec", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_RISC_E, 1,1, 0,{0,0}}, + + {SCF_RISC_XOR, "xor", 2, {0x30, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x31, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x32, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x33, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, +#if 0 + {SCF_RISC_XOR, "xor", 2, {0x34, 0x0, 0x0},1, 1,1, SCF_RISC_I2G, 0,0, 1,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 2,2, SCF_RISC_I2G, 0,0, 1,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 4,4, SCF_RISC_I2G, 0,0, 1,{0,0}}, + {SCF_RISC_XOR, "xor", 2, {0x35, 0x0, 0x0},1, 4,8, SCF_RISC_I2G, 0,0, 1,{0,0}}, +#endif + {SCF_RISC_AND, "and", 2, {0x20, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x21, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x21, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x21, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x22, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x23, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x23, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x23, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_AND, "and", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 4,1, 0,{0,0}}, + + {SCF_RISC_OR, "or", 2, {0x08, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x09, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x09, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x09, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x0a, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x0b, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x0b, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x0b, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 1,1, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 1,1, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 1,1, 0,{0,0}}, + {SCF_RISC_OR, "or", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 1,1, 0,{0,0}}, + + {SCF_RISC_CALL, "call", 5, {0xe8, 0x0, 0x0},1, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_CALL, "call", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_RISC_E, 2,1, 0,{0,0}}, + + {SCF_RISC_RET, "ret", 1, {0xc3, 0x0, 0x0},1, 8,8, SCF_RISC_G, 0,0, 0,{0,0}}, + + {SCF_RISC_ADD, "add", 2, {0x00, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x01, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x01, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x01, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x02, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x03, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x03, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x03, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + // add r/m, imm + {SCF_RISC_ADD, "add", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 0,1, 0,{0,0}}, + + // add r/m, imm8 + {SCF_RISC_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_ADD, "add", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 0,1, 0,{0,0}}, + + + {SCF_RISC_SUB, "sub", 2, {0x28, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x29, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + + {SCF_RISC_SUB, "sub", 2, {0x2a, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x2b, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_SUB, "sub", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SUB, "sub", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 5,1, 0,{0,0}}, + + {SCF_RISC_MUL, "mul", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 4,1, 2,{0,2}}, + {SCF_RISC_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 4,1, 2,{0,2}}, + {SCF_RISC_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 4,1, 2,{0,2}}, + {SCF_RISC_MUL, "mul", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 4,1, 2,{0,2}}, + + {SCF_RISC_IMUL, "imul", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 5,1, 2,{0,2}}, + {SCF_RISC_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 5,1, 2,{0,2}}, + {SCF_RISC_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 5,1, 2,{0,2}}, + {SCF_RISC_IMUL, "imul", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 5,1, 2,{0,2}}, + + {SCF_RISC_DIV, "div", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 6,1, 2,{0,2}}, + {SCF_RISC_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 6,1, 2,{0,2}}, + {SCF_RISC_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 6,1, 2,{0,2}}, + {SCF_RISC_DIV, "div", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 6,1, 2,{0,2}}, + + {SCF_RISC_IDIV, "idiv", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 7,1, 2,{0,2}}, + {SCF_RISC_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 7,1, 2,{0,2}}, + {SCF_RISC_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 7,1, 2,{0,2}}, + {SCF_RISC_IDIV, "idiv", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 7,1, 2,{0,2}}, + + {SCF_RISC_CBW, "cwd", 1, {0x98, 0x0, 0x0},1, 1,2, SCF_RISC_G, 0,0, 2,{0,2}}, + {SCF_RISC_CWD, "cwd", 1, {0x98, 0x0, 0x0},1, 2,4, SCF_RISC_G, 0,0, 2,{0,2}}, + {SCF_RISC_CDQ, "cdq", 1, {0x98, 0x0, 0x0},1, 4,8, SCF_RISC_G, 0,0, 2,{0,2}}, + {SCF_RISC_CQO, "cqo", 1, {0x98, 0x0, 0x0},1, 8,16, SCF_RISC_G, 0,0, 2,{0,2}}, + + {SCF_RISC_SAR, "sar", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 7,1, 1,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_RISC_G2E, 7,1, 1,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_RISC_G2E, 7,1, 1,{0,0}}, + {SCF_RISC_SAR, "sar", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_RISC_G2E, 7,1, 1,{0,0}}, + + {SCF_RISC_SHR, "shr", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 5,1, 0,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 5,1, 1,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_RISC_G2E, 5,1, 1,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_RISC_G2E, 5,1, 1,{0,0}}, + {SCF_RISC_SHR, "shr", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_RISC_G2E, 5,1, 1,{0,0}}, + + {SCF_RISC_SHL, "shl", 2, {0xc0, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xc1, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 4,1, 0,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xd2, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 4,1, 1,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,2, SCF_RISC_G2E, 4,1, 1,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,4, SCF_RISC_G2E, 4,1, 1,{0,0}}, + {SCF_RISC_SHL, "shl", 2, {0xd3, 0x0, 0x0},1, 1,8, SCF_RISC_G2E, 4,1, 1,{0,0}}, + + {SCF_RISC_NEG, "neg", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 3,1, 0,{0,0}}, + {SCF_RISC_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 3,1, 0,{0,0}}, + {SCF_RISC_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 3,1, 0,{0,0}}, + {SCF_RISC_NEG, "neg", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 3,1, 0,{0,0}}, + + {SCF_RISC_NOT, "not", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_E, 2,1, 0,{0,0}}, + {SCF_RISC_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_E, 2,1, 0,{0,0}}, + {SCF_RISC_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_E, 2,1, 0,{0,0}}, + {SCF_RISC_NOT, "not", 2, {0xf7, 0x0, 0x0},1, 8,8, SCF_RISC_E, 2,1, 0,{0,0}}, + + {SCF_RISC_LEA, "lea", 1, {0x8d, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MOV, "mov", 2, {0x88, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x89, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x8a, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0x8b, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MOV, "mov", 2, {0xb0, 0x0, 0x0},1, 1,1, SCF_RISC_I2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 2,2, SCF_RISC_I2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 4,4, SCF_RISC_I2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xb8, 0x0, 0x0},1, 8,8, SCF_RISC_I2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xc6, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_MOV, "mov", 2, {0xc7, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 0,1, 0,{0,0}}, + + {SCF_RISC_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSX, "movsx", 2, {0x0f, 0xbe, 0x0},2, 1,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSX, "movsx", 2, {0x0f, 0xbf, 0x0},2, 2,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSX, "movsx", 2, {0x0f, 0xbf, 0x0},2, 2,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSX, "movsx", 2, {0x63, 0x0, 0x0}, 1, 4,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVZX, "movzx", 2, {0x0f, 0xb6, 0x0},2, 1,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVZX, "movzx", 2, {0x0f, 0xb7, 0x0},2, 2,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVZX, "movzx", 2, {0x0f, 0xb7, 0x0},2, 2,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MOVS, "movs", 2, {0xf3, 0xa4, 0x0},2, 1,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVS, "movs", 2, {0xf3, 0xa4, 0x0},2, 1,8, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 2,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 4,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVS, "movs", 2, {0xf3, 0xa5, 0x0},2, 8,8, SCF_RISC_G, 0,0, 0,{0,0}}, + + {SCF_RISC_STOS, "stos", 2, {0xf3, 0xaa, 0x0},2, 1,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_STOS, "stos", 2, {0xf3, 0xaa, 0x0},2, 1,8, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 2,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 4,4, SCF_RISC_G, 0,0, 0,{0,0}}, + {SCF_RISC_STOS, "stos", 2, {0xf3, 0xab, 0x0},2, 8,8, SCF_RISC_G, 0,0, 0,{0,0}}, + + {SCF_RISC_CMP, "cmp", 2, {0x38, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x39, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x3a, 0x0, 0x0},1, 1,1, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 2,2, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x3b, 0x0, 0x0},1, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CMP, "cmp", 2, {0x80, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x81, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,2, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,4, SCF_RISC_I2E, 7,1, 0,{0,0}}, + {SCF_RISC_CMP, "cmp", 2, {0x83, 0x0, 0x0},1, 1,8, SCF_RISC_I2E, 7,1, 0,{0,0}}, + + {SCF_RISC_TEST, "test", 2, {0x84, 0x0, 0x0},1, 1,1, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0x85, 0x0, 0x0},1, 2,2, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0x85, 0x0, 0x0},1, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0x85, 0x0, 0x0},1, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + + {SCF_RISC_TEST, "test", 2, {0xf6, 0x0, 0x0},1, 1,1, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 2,2, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 4,4, SCF_RISC_I2E, 0,1, 0,{0,0}}, + {SCF_RISC_TEST, "test", 2, {0xf7, 0x0, 0x0},1, 4,8, SCF_RISC_I2E, 0,1, 0,{0,0}}, + + {SCF_RISC_SETZ, "setz", 3, {0x0f, 0x94, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + {SCF_RISC_SETNZ, "setnz", 3, {0x0f, 0x95, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + + {SCF_RISC_SETG, "setg", 3, {0x0f, 0x9f, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + {SCF_RISC_SETGE, "setge", 3, {0x0f, 0x9d, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + + {SCF_RISC_SETL, "setl", 3, {0x0f, 0x9c, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + {SCF_RISC_SETLE, "setle", 3, {0x0f, 0x9e, 0x0},2, 1,1, SCF_RISC_E, 0,0, 0,{0,0}}, + + {SCF_RISC_ADDSS, "addss", 4, {0xf3, 0x0f, 0x58},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_ADDSD, "addsd", 8, {0xf2, 0x0f, 0x58},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_SUBSS, "subss", 4, {0xf3, 0x0f, 0x5c},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_SUBSD, "subsd", 8, {0xf2, 0x0f, 0x5c},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MULSS, "mulss", 4, {0xf3, 0x0f, 0x59},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MULSD, "mulsd", 8, {0xf2, 0x0f, 0x59},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_DIVSS, "divss", 4, {0xf3, 0x0f, 0x5e},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_DIVSD, "divsd", 8, {0xf2, 0x0f, 0x5e},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_MOVSS, "movss", 4, {0xf3, 0x0f, 0x10},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSS, "movss", 4, {0xf3, 0x0f, 0x11},3, 4,4, SCF_RISC_G2E, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSD, "movsd", 8, {0xf2, 0x0f, 0x10},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_MOVSD, "movsd", 8, {0xf2, 0x0f, 0x11},3, 8,8, SCF_RISC_G2E, 0,0, 0,{0,0}}, + + {SCF_RISC_PXOR, "pxor", 8, {0x0f, 0xef, 0 },2, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_PXOR, "pxor", 8, {0x66, 0x0f, 0xef},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_UCOMISS, "ucomiss", 3, {0x0f, 0x2e, 0}, 2, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_UCOMISD, "ucomisd", 4, {0x66, 0x0f, 0x2e},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CVTSS2SD, "cvtss2sd", 4, {0xf3, 0x0f, 0x5a},3, 4,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CVTSD2SS, "cvtsd2ss", 4, {0xf2, 0x0f, 0x5a},3, 8,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CVTSI2SS, "cvtsi2ss", 4, {0xf3, 0x0f, 0x2a},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CVTSI2SD, "cvtsi2sd", 4, {0xf2, 0x0f, 0x2a},3, 4,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CVTSI2SD, "cvtsi2sd", 4, {0xf2, 0x0f, 0x2a},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CVTTSS2SI, "cvttss2si", 4, {0xf3, 0x0f, 0x2c},3, 4,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_CVTTSD2SI, "cvttsd2si", 8, {0xf2, 0x0f, 0x2c},3, 8,4, SCF_RISC_E2G, 0,0, 0,{0,0}}, + {SCF_RISC_CVTTSD2SI, "cvttsd2si", 8, {0xf2, 0x0f, 0x2c},3, 8,8, SCF_RISC_E2G, 0,0, 0,{0,0}}, + + {SCF_RISC_JZ, "jz", 2, {0x74, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JZ, "jz", 6, {0x0f, 0x84, 0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JNZ, "jnz", 2, {0x75, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JNZ, "jnz", 6, {0x0f, 0x85, 0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JG, "jg", 2, {0x7f, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JG, "jg", 6, {0x0f, 0x8f,0x0},1, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JGE, "jge", 2, {0x7d, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JGE, "jge", 6, {0x0f, 0x8d,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JL, "jl", 2, {0x7c, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JL, "jl", 6, {0x0f, 0x8c,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JLE, "jle", 2, {0x7e, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JLE, "jle", 6, {0x0f, 0x8e,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JA, "ja", 2, {0x77, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JA, "ja", 6, {0x0f, 0x87,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JAE, "jae", 2, {0x73, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JAE, "jae", 6, {0x0f, 0x83,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JB, "jb", 2, {0x72, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JB, "jb", 6, {0x0f, 0x82,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JBE, "jbe", 2, {0x76, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JBE, "jbe", 6, {0x0f, 0x86,0x0},2, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + + {SCF_RISC_JMP, "jmp", 2, {0xeb, 0x0, 0x0},1, 1,1, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JMP, "jmp", 5, {0xe9, 0x0, 0x0},1, 4,4, SCF_RISC_I, 0,0, 0,{0,0}}, + {SCF_RISC_JMP, "jmp", 2, {0xff, 0x0, 0x0},1, 8,8, SCF_RISC_E, 4,1, 0,{0,0}}, +}; + +scf_risc_OpCode_t* risc_find_OpCode_by_type(const int type) +{ + int i; + for (i = 0; i < sizeof(risc_OpCodes) / sizeof(risc_OpCodes[0]); i++) { + + scf_risc_OpCode_t* OpCode = &(risc_OpCodes[i]); + if (OpCode->type == type) + return OpCode; + } + return NULL; +} + +scf_risc_OpCode_t* risc_find_OpCode(const int type, const int OpBytes, const int RegBytes, const int EG) +{ + int i; + for (i = 0; i < sizeof(risc_OpCodes) / sizeof(risc_OpCodes[0]); i++) { + + scf_risc_OpCode_t* OpCode = &(risc_OpCodes[i]); + + if (type == OpCode->type + && OpBytes == OpCode->OpBytes + && RegBytes == OpCode->RegBytes + && EG == OpCode->EG) + return OpCode; + } + return NULL; +} + +int risc_find_OpCodes(scf_vector_t* results, const int type, const int OpBytes, const int RegBytes, const int EG) +{ + int i; + for (i = 0; i < sizeof(risc_OpCodes) / sizeof(risc_OpCodes[0]); i++) { + + scf_risc_OpCode_t* OpCode = &(risc_OpCodes[i]); + + if (type == OpCode->type + && OpBytes == OpCode->OpBytes + && RegBytes == OpCode->RegBytes + && EG == OpCode->EG) { + + int ret = scf_vector_add(results, OpCode); + if (ret < 0) + return ret; + } + } + return 0; +} + diff --git a/native/risc/scf_risc_opcode.h b/native/risc/scf_risc_opcode.h new file mode 100644 index 0000000..0f7286a --- /dev/null +++ b/native/risc/scf_risc_opcode.h @@ -0,0 +1,37 @@ +#ifndef SCF_RISC_OPCODE_H +#define SCF_RISC_OPCODE_H + +#include"scf_native.h" +#include"scf_risc_util.h" + +typedef struct { + int type; + + char* name; + + int len; + + uint8_t OpCodes[3]; + int nb_OpCodes; + + // RegBytes only valid for immediate + // same to OpBytes for E2G or G2E + int OpBytes; + int RegBytes; + int EG; + + uint8_t ModRM_OpCode; + int ModRM_OpCode_used; + + int nb_regs; + uint32_t regs[2]; +} scf_risc_OpCode_t; + +scf_risc_OpCode_t* risc_find_OpCode_by_type(const int type); + +scf_risc_OpCode_t* risc_find_OpCode(const int type, const int OpBytes, const int RegBytes, const int EG); + +int risc_find_OpCodes(scf_vector_t* results, const int type, const int OpBytes, const int RegBytes, const int EG); + +#endif + diff --git a/native/risc/scf_risc_rcg.c b/native/risc/scf_risc_rcg.c new file mode 100644 index 0000000..7ad3ced --- /dev/null +++ b/native/risc/scf_risc_rcg.c @@ -0,0 +1,1297 @@ +#include"scf_risc.h" + +static int _risc_rcg_node_cmp(const void* v0, const void* v1) +{ + const scf_graph_node_t* gn1 = v1; + const risc_rcg_node_t* rn1 = gn1->data; + const risc_rcg_node_t* rn0 = v0; + + if (rn0->dag_node || rn1->dag_node) + return rn0->dag_node != rn1->dag_node; + + return rn0->reg != rn1->reg; +} + +int risc_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) +{ + risc_rcg_node_t* rn = calloc(1, sizeof(risc_rcg_node_t)); + if (!rn) + return -ENOMEM; + + rn->dag_node = dn; + rn->reg = reg; + + scf_graph_node_t* gn = scf_vector_find_cmp(g->nodes, rn, _risc_rcg_node_cmp); + free(rn); + rn = NULL; + + if (!gn) + return -1; + + *pp = gn; + return 0; +} + +int _risc_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) +{ + risc_rcg_node_t* rn = calloc(1, sizeof(risc_rcg_node_t)); + if (!rn) + return -ENOMEM; + + rn->dag_node = dn; + rn->reg = reg; + rn->OpCode = NULL; + + scf_graph_node_t* gn = scf_vector_find_cmp(g->nodes, rn, _risc_rcg_node_cmp); + if (!gn) { + + gn = scf_graph_node_alloc(); + if (!gn) { + free(rn); + return -ENOMEM; + } + + gn->data = rn; + + if (reg) + gn->color = reg->color; + + int ret = scf_graph_add_node(g, gn); + if (ret < 0) { + free(rn); + scf_graph_node_free(gn); + return ret; + } + } else { + if (reg) + gn->color = reg->color; + + free(rn); + rn = NULL; + } + + *pp = gn; + return 0; +} + +static int _risc_rcg_make_edge(scf_graph_node_t* gn0, scf_graph_node_t* gn1) +{ + if (gn0 == gn1) + return 0; + + if (!scf_vector_find(gn0->neighbors, gn1)) { + + assert(!scf_vector_find(gn1->neighbors, gn0)); + + int ret = scf_graph_make_edge(gn0, gn1); + if (ret < 0) + return ret; + + ret = scf_graph_make_edge(gn1, gn0); + if (ret < 0) + return ret; + } else + assert(scf_vector_find(gn1->neighbors, gn0)); + + return 0; +} + +static int _risc_rcg_active_vars(scf_graph_t* g, scf_vector_t* active_vars) +{ + scf_graph_node_t* gn0; + scf_graph_node_t* gn1; + + scf_dn_status_t* ds0; + scf_dn_status_t* ds1; + + scf_dag_node_t* dn0; + scf_dag_node_t* dn1; + + int ret; + int i; + int j; + + for (i = 0; i < active_vars->size; i++) { + + ds0 = active_vars->data[i]; + dn0 = ds0->dag_node; + + if (!ds0->active) + continue; + + ret = _risc_rcg_make_node(&gn0, g, dn0, NULL); + if (ret < 0) + return ret; + + for (j = 0; j < i; j++) { + + ds1 = active_vars->data[j]; + dn1 = ds1->dag_node; + + if (!ds1->active) + continue; + + ret = _risc_rcg_make_node(&gn1, g, dn1, NULL); + if (ret < 0) + return ret; + + assert(gn0 != gn1); + + ret = _risc_rcg_make_edge(gn0, gn1); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int _risc_rcg_operands(scf_graph_t* g, scf_vector_t* operands) +{ + scf_3ac_operand_t* operand0; + scf_3ac_operand_t* operand1; + + scf_graph_node_t* gn0; + scf_graph_node_t* gn1; + + scf_dag_node_t* dn0; + scf_dag_node_t* dn1; + + int i; + int j; + + for (i = 0; i < operands->size; i++) { + + operand0 = operands->data[i]; + dn0 = operand0->dag_node; + + if (scf_variable_const(dn0->var)) + continue; + + int ret = _risc_rcg_make_node(&gn0, g, dn0, NULL); + if (ret < 0) + return ret; + + for (j = 0; j < i; j++) { + + operand1 = operands->data[j]; + dn1 = operand1->dag_node; + + if (scf_variable_const(dn1->var)) + continue; + + ret = _risc_rcg_make_node(&gn1, g, dn1, NULL); + if (ret < 0) + return ret; + + if (gn1 == gn0) + continue; + + ret = _risc_rcg_make_edge(gn0, gn1); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int _risc_rcg_to_active_vars(scf_graph_t* g, scf_graph_node_t* gn0, scf_vector_t* active_vars) +{ + scf_graph_node_t* gn1; + scf_dn_status_t* ds1; + scf_dag_node_t* dn1; + + int ret; + int i; + + for (i = 0; i < active_vars->size; i++) { + + ds1 = active_vars->data[i]; + dn1 = ds1->dag_node; + + if (!ds1->active) + continue; + + ret = _risc_rcg_make_node(&gn1, g, dn1, NULL); + if (ret < 0) + return ret; + + if (gn0 == gn1) + continue; + + ret = _risc_rcg_make_edge(gn0, gn1); + if (ret < 0) + return ret; + } + + return 0; +} + +int risc_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) +{ + scf_graph_node_t* gn0 = NULL; + scf_graph_node_t* gn1; + scf_dag_node_t* dn1; + scf_dn_status_t* ds1; + + int ret; + int i; + + if (dn || reg) { + ret = _risc_rcg_make_node(&gn0, g, dn, reg); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + scf_logd("g->nodes->size: %d, active_vars: %d\n", g->nodes->size, c->active_vars->size); + + ret = _risc_rcg_active_vars(g, c->active_vars); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (gn0) + return _risc_rcg_to_active_vars(g, gn0, c->active_vars); + + return 0; +} + +static int _risc_rcg_make2(scf_3ac_code_t* c, scf_dag_node_t* dn, scf_register_t* reg) +{ + if (c->rcg) + scf_graph_free(c->rcg); + + c->rcg = scf_graph_alloc(); + if (!c->rcg) + return -ENOMEM; + + return risc_rcg_make(c, c->rcg, dn, reg); +} + +static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; + scf_dag_node_t* dn = NULL; + scf_register_t* r = NULL; + scf_3ac_operand_t* src = NULL; + scf_3ac_operand_t* dst = NULL; + scf_graph_node_t* gn = NULL; + + int i; + int ret; + + if (c->srcs->size < 1) + return -EINVAL; + + ret = _risc_rcg_active_vars(g, c->active_vars); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = _risc_rcg_operands(g, c->srcs); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (c->dsts) { + + if (c->dsts->size > RISC_ABI_RET_NB) { + scf_loge("\n"); + return -EINVAL; + } + + ret = _risc_rcg_operands(g, c->dsts); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + for (i = 0; i < c->dsts->size; i++) { + dst = c->dsts->data[i]; + dn = dst->dag_node; + + if (SCF_VAR_VOID == dn->var->type && 0 == dn->var->nb_pointers) + continue; + + int is_float = scf_variable_float(dn->var); + int size = risc_variable_size (dn->var); + + if (0 == i) + r = risc_find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size); + + else if (!is_float) + r = risc_find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size); + else + r = NULL; + + gn = NULL; + ret = _risc_rcg_make_node(&gn, g, dn, r); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = _risc_rcg_to_active_vars(g, gn, c->active_vars); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + } + + int nb_ints = 0; + int nb_floats = 0; + + risc_call_rabi(&nb_ints, &nb_floats, c); + + for (i = 1; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + dn = src->dag_node; + + if (scf_variable_const(dn->var)) + continue; + + gn = NULL; + ret = _risc_rcg_make_node(&gn, g, dn, dn->rabi2); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + scf_3ac_operand_t* src_pf = c->srcs->data[0]; + scf_graph_node_t* gn_pf = NULL; + scf_dag_node_t* dn_pf = src_pf->dag_node; + + if (!dn_pf->var->const_literal_flag) { + + ret = _risc_rcg_make_node(&gn_pf, g, dn_pf, NULL); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + for (i = 0; i < nb_ints; i++) { + + scf_register_t* rabi = NULL; + scf_graph_node_t* gn_rabi = NULL; + + rabi = risc_find_register_type_id_bytes(0, risc_abi_regs[i], dn_pf->var->size); + + ret = _risc_rcg_make_node(&gn_rabi, g, NULL, rabi); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + assert(gn_pf != gn_rabi); + + ret = _risc_rcg_make_edge(gn_pf, gn_rabi); + if (ret < 0) + return ret; + } + } + + return ret; +} + +static int _risc_rcg_call_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + if (c->rcg) + scf_graph_free(c->rcg); + + c->rcg = scf_graph_alloc(); + if (!c->rcg) + return -ENOMEM; + + int ret = _risc_rcg_call(ctx, c, c->rcg); + if (ret < 0) + return ret; + + return _risc_rcg_call(ctx, c, g); +} + +static int _risc_rcg_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_logic_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + if (!c->srcs || c->srcs->size < 1) + return -EINVAL; + + scf_dag_node_t* dn = NULL; + scf_3ac_operand_t* src = c->srcs->data[c->srcs->size - 1]; + scf_risc_context_t* risc = ctx->priv; + scf_3ac_operand_t* dst; + + if (!src || !src->dag_node) + return -EINVAL; + + if (c->dsts) { + dst = c->dsts->data[0]; + dn = dst->dag_node; + } + + return risc_rcg_make(c, g, dn, NULL); +} + +static int _risc_rcg_mul_div_mod2(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + if (c->rcg) + scf_graph_free(c->rcg); + + c->rcg = scf_graph_alloc(); + if (!c->rcg) + return -ENOMEM; + + int ret = _risc_rcg_mul_div_mod(ctx, c, c->rcg); + if (ret < 0) + return ret; + + return _risc_rcg_mul_div_mod(ctx, c, g); +} + +static int _risc_rcg_mul_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_div_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_mod_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_add_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_sub_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + if (!c->srcs || c->srcs->size < 1) + return -EINVAL; + + scf_dag_node_t* dn = NULL; + scf_3ac_operand_t* count = c->srcs->data[c->srcs->size - 1]; + scf_graph_node_t* gn = NULL; + + if (!count || !count->dag_node) + return -EINVAL; + + if (c->dsts) { + scf_3ac_operand_t* dst = c->dsts->data[0]; + + dn = dst->dag_node; + } + + return risc_rcg_make(c, g, dn, NULL); +} + +static int _risc_rcg_shift2(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + if (c->rcg) + scf_graph_free(c->rcg); + + c->rcg = scf_graph_alloc(); + if (!c->rcg) + return -ENOMEM; + + int ret = _risc_rcg_shift(ctx, c, c->rcg); + if (ret < 0) + return ret; + + return _risc_rcg_shift(ctx, c, g); +} + +static int _risc_rcg_shl_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_shift2(ctx, c, g); +} + +static int _risc_rcg_shr_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_shift2(ctx, c, g); +} + +static int _risc_rcg_bit_and_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_teq_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +#define RISC_RCG_SET(setcc) \ +static int _risc_rcg_##setcc##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, dst->dag_node, NULL); \ +} +RISC_RCG_SET(setz) +RISC_RCG_SET(setnz) +RISC_RCG_SET(setgt) +RISC_RCG_SET(setge) +RISC_RCG_SET(setlt) +RISC_RCG_SET(setle) + +static int _risc_rcg_eq_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_ne_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_gt_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_lt_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_add_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_sub_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_mul_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_div_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_mul_div_mod2(ctx, c, g); +} + +static int _risc_rcg_shl_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_shift2(ctx, c, g); +} + +static int _risc_rcg_shr_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return _risc_rcg_shift2(ctx, c, g); +} + +static int _risc_rcg_and_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_or_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int i; + + scf_register_t* r; + scf_3ac_operand_t* src; + scf_graph_node_t* gn; + scf_dag_node_t* dn; + + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + ret = risc_rcg_make(c, g, NULL, NULL); + if (ret < 0) + return ret; + + if (!c->srcs) + return 0; + + for (i = 0; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + dn = src->dag_node; + + int is_float = scf_variable_float(dn->var); + int size = risc_variable_size (dn->var); + + size = size > 4 ? 8 : 4; + + if (is_float) { + if (i > 0) { + scf_loge("\n"); + return -1; + } + + r = risc_find_register_type_id_bytes(is_float, 0, size); + } else + r = risc_find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size); + + ret = _risc_rcg_make_node(&gn, g, dn, r); + if (ret < 0) + return ret; + } + + return 0; +} + +static int _risc_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int i; + + scf_register_t* r; + scf_3ac_operand_t* src; + scf_graph_node_t* gn; + scf_dag_node_t* dn; + + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + ret = risc_rcg_make(c, g, NULL, NULL); + if (ret < 0) + return ret; + + if (!c->srcs || c->srcs->size != 3) + return -EINVAL; +#if 0 + for (i = 0; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + dn = src->dag_node; + + int size = risc_variable_size (dn->var); + size = size > 4 ? 8 : 4; + + if (0 == i) + r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_DI, size); + + else if (1 == i) + r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_AX, size); + + else if (2 == i) + r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_CX, size); + else + return -EINVAL; + + ret = _risc_rcg_make_node(&gn, g, dn, r, NULL); + if (ret < 0) + return ret; + } +#endif + return 0; +} + +static int _risc_rcg_goto_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} + +#define RISC_RCG_JCC(cc) \ +static int _risc_rcg_##cc##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + return 0; \ +} + +RISC_RCG_JCC(jz) +RISC_RCG_JCC(jnz) +RISC_RCG_JCC(jgt) +RISC_RCG_JCC(jge) +RISC_RCG_JCC(jlt) +RISC_RCG_JCC(jle) + +RISC_RCG_JCC(ja) +RISC_RCG_JCC(jae) +RISC_RCG_JCC(jb) +RISC_RCG_JCC(jbe) + +static int _risc_rcg_save_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_load_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} +static int _risc_rcg_nop_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} +static int _risc_rcg_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} + +#define RISC_RCG_BINARY_ASSIGN(name) \ +static int _risc_rcg_##name##_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} \ +static int _risc_rcg_##name##_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} \ +static int _risc_rcg_##name##_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} + +RISC_RCG_BINARY_ASSIGN(add) +RISC_RCG_BINARY_ASSIGN(sub) +RISC_RCG_BINARY_ASSIGN(and) +RISC_RCG_BINARY_ASSIGN(or) + +#define RISC_RCG_SHIFT_ASSIGN(name) \ +static int _risc_rcg_##name##_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + return _risc_rcg_shift2(ctx, c, g); \ +} \ +static int _risc_rcg_##name##_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + return _risc_rcg_shift2(ctx, c, g); \ +} \ +static int _risc_rcg_##name##_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + return _risc_rcg_shift2(ctx, c, g); \ +} +RISC_RCG_SHIFT_ASSIGN(shl) +RISC_RCG_SHIFT_ASSIGN(shr) + +#define RISC_RCG_UNARY_ASSIGN(name) \ +static int _risc_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} \ +static int _risc_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} \ +static int _risc_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} \ +static int _risc_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + int ret = _risc_rcg_make2(c, NULL, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, NULL, NULL); \ +} +RISC_RCG_UNARY_ASSIGN(inc) +RISC_RCG_UNARY_ASSIGN(dec) + +#define RISC_RCG_UNARY_POST_ASSIGN(name) \ +static int _risc_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, dst->dag_node, NULL); \ +} \ +static int _risc_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, dst->dag_node, NULL); \ +} \ +static int _risc_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, dst->dag_node, NULL); \ +} \ +static int _risc_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ +{ \ + scf_3ac_operand_t* dst = c->dsts->data[0]; \ + \ + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); \ + if (ret < 0) \ + return ret; \ + return risc_rcg_make(c, g, dst->dag_node, NULL); \ +} +RISC_RCG_UNARY_POST_ASSIGN(inc_post) +RISC_RCG_UNARY_POST_ASSIGN(dec_post) + +static int _risc_rcg_address_of_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static int _risc_rcg_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} +static int _risc_rcg_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + return 0; +} + +static int _risc_rcg_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_va_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + int ret = _risc_rcg_make2(c, NULL, NULL); + if (ret < 0) + return ret; + return risc_rcg_make(c, g, NULL, NULL); +} + +static int _risc_rcg_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) +{ + scf_3ac_operand_t* dst = c->dsts->data[0]; + + int ret = _risc_rcg_make2(c, dst->dag_node, NULL); + if (ret < 0) + return ret; + return risc_rcg_make(c, g, dst->dag_node, NULL); +} + +static risc_rcg_handler_t risc_rcg_handlers[] = { + + {SCF_OP_CALL, _risc_rcg_call_handler}, + {SCF_OP_ARRAY_INDEX, _risc_rcg_array_index_handler}, + + {SCF_OP_TYPE_CAST, _risc_rcg_cast_handler}, + {SCF_OP_LOGIC_NOT, _risc_rcg_logic_not_handler}, + {SCF_OP_BIT_NOT, _risc_rcg_bit_not_handler}, + {SCF_OP_NEG, _risc_rcg_neg_handler}, + + {SCF_OP_VA_START, _risc_rcg_va_start_handler}, + {SCF_OP_VA_ARG, _risc_rcg_va_arg_handler}, + {SCF_OP_VA_END, _risc_rcg_va_end_handler}, + + {SCF_OP_INC, _risc_rcg_inc_handler}, + {SCF_OP_DEC, _risc_rcg_dec_handler}, + + {SCF_OP_INC_POST, _risc_rcg_inc_post_handler}, + {SCF_OP_DEC_POST, _risc_rcg_dec_post_handler}, + + {SCF_OP_DEREFERENCE, _risc_rcg_dereference_handler}, + {SCF_OP_ADDRESS_OF, _risc_rcg_address_of_handler}, + {SCF_OP_POINTER, _risc_rcg_pointer_handler}, + + {SCF_OP_MUL, _risc_rcg_mul_handler}, + {SCF_OP_DIV, _risc_rcg_div_handler}, + {SCF_OP_MOD, _risc_rcg_mod_handler}, + + {SCF_OP_ADD, _risc_rcg_add_handler}, + {SCF_OP_SUB, _risc_rcg_sub_handler}, + + {SCF_OP_SHL, _risc_rcg_shl_handler}, + {SCF_OP_SHR, _risc_rcg_shr_handler}, + + {SCF_OP_BIT_AND, _risc_rcg_bit_and_handler}, + {SCF_OP_BIT_OR, _risc_rcg_bit_or_handler}, + + {SCF_OP_EQ, _risc_rcg_eq_handler}, + {SCF_OP_NE, _risc_rcg_ne_handler}, + {SCF_OP_GT, _risc_rcg_gt_handler}, + {SCF_OP_LT, _risc_rcg_lt_handler}, + + {SCF_OP_ASSIGN, _risc_rcg_assign_handler}, + {SCF_OP_ADD_ASSIGN, _risc_rcg_add_assign_handler}, + {SCF_OP_SUB_ASSIGN, _risc_rcg_sub_assign_handler}, + + {SCF_OP_MUL_ASSIGN, _risc_rcg_mul_assign_handler}, + {SCF_OP_DIV_ASSIGN, _risc_rcg_div_assign_handler}, + {SCF_OP_MOD_ASSIGN, _risc_rcg_mod_assign_handler}, + + {SCF_OP_SHL_ASSIGN, _risc_rcg_shl_assign_handler}, + {SCF_OP_SHR_ASSIGN, _risc_rcg_shr_assign_handler}, + + {SCF_OP_AND_ASSIGN, _risc_rcg_and_assign_handler}, + {SCF_OP_OR_ASSIGN, _risc_rcg_or_assign_handler}, + + {SCF_OP_RETURN, _risc_rcg_return_handler}, + + {SCF_OP_3AC_CMP, _risc_rcg_cmp_handler}, + {SCF_OP_3AC_TEQ, _risc_rcg_teq_handler}, + + {SCF_OP_3AC_SETZ, _risc_rcg_setz_handler}, + {SCF_OP_3AC_SETNZ, _risc_rcg_setnz_handler}, + {SCF_OP_3AC_SETGT, _risc_rcg_setgt_handler}, + {SCF_OP_3AC_SETGE, _risc_rcg_setge_handler}, + {SCF_OP_3AC_SETLT, _risc_rcg_setlt_handler}, + {SCF_OP_3AC_SETLE, _risc_rcg_setle_handler}, + + {SCF_OP_GOTO, _risc_rcg_goto_handler}, + {SCF_OP_3AC_JZ, _risc_rcg_jz_handler}, + {SCF_OP_3AC_JNZ, _risc_rcg_jnz_handler}, + {SCF_OP_3AC_JGT, _risc_rcg_jgt_handler}, + {SCF_OP_3AC_JGE, _risc_rcg_jge_handler}, + {SCF_OP_3AC_JLT, _risc_rcg_jlt_handler}, + {SCF_OP_3AC_JLE, _risc_rcg_jle_handler}, + + {SCF_OP_3AC_JA, _risc_rcg_ja_handler}, + {SCF_OP_3AC_JAE, _risc_rcg_jae_handler}, + {SCF_OP_3AC_JB, _risc_rcg_jb_handler}, + {SCF_OP_3AC_JBE, _risc_rcg_jbe_handler}, + + {SCF_OP_3AC_SAVE, _risc_rcg_save_handler}, + {SCF_OP_3AC_LOAD, _risc_rcg_load_handler}, + + {SCF_OP_3AC_RESAVE, _risc_rcg_save_handler}, + {SCF_OP_3AC_RELOAD, _risc_rcg_load_handler}, + + {SCF_OP_3AC_NOP, _risc_rcg_nop_handler}, + {SCF_OP_3AC_END, _risc_rcg_end_handler}, + + {SCF_OP_3AC_INC, _risc_rcg_inc_handler}, + {SCF_OP_3AC_DEC, _risc_rcg_dec_handler}, + + {SCF_OP_3AC_PUSH_RAX, _risc_rcg_push_rax_handler}, + {SCF_OP_3AC_POP_RAX, _risc_rcg_pop_rax_handler}, + + {SCF_OP_3AC_MEMSET, _risc_rcg_memset_handler}, + + + {SCF_OP_3AC_ASSIGN_DEREFERENCE, _risc_rcg_assign_dereference_handler}, + {SCF_OP_3AC_ASSIGN_ARRAY_INDEX, _risc_rcg_assign_array_index_handler}, + {SCF_OP_3AC_ASSIGN_POINTER, _risc_rcg_assign_pointer_handler}, + + {SCF_OP_3AC_ADD_ASSIGN_DEREFERENCE, _risc_rcg_add_assign_dereference_handler}, + {SCF_OP_3AC_ADD_ASSIGN_ARRAY_INDEX, _risc_rcg_add_assign_array_index_handler}, + {SCF_OP_3AC_ADD_ASSIGN_POINTER, _risc_rcg_add_assign_pointer_handler}, + + {SCF_OP_3AC_SUB_ASSIGN_DEREFERENCE, _risc_rcg_sub_assign_dereference_handler}, + {SCF_OP_3AC_SUB_ASSIGN_ARRAY_INDEX, _risc_rcg_sub_assign_array_index_handler}, + {SCF_OP_3AC_SUB_ASSIGN_POINTER, _risc_rcg_sub_assign_pointer_handler}, + + {SCF_OP_3AC_AND_ASSIGN_DEREFERENCE, _risc_rcg_and_assign_dereference_handler}, + {SCF_OP_3AC_AND_ASSIGN_ARRAY_INDEX, _risc_rcg_and_assign_array_index_handler}, + {SCF_OP_3AC_AND_ASSIGN_POINTER, _risc_rcg_and_assign_pointer_handler}, + + {SCF_OP_3AC_OR_ASSIGN_DEREFERENCE, _risc_rcg_or_assign_dereference_handler}, + {SCF_OP_3AC_OR_ASSIGN_ARRAY_INDEX, _risc_rcg_or_assign_array_index_handler}, + {SCF_OP_3AC_OR_ASSIGN_POINTER, _risc_rcg_or_assign_pointer_handler}, + + {SCF_OP_3AC_INC_DEREFERENCE, _risc_rcg_inc_dereference_handler}, + {SCF_OP_3AC_INC_ARRAY_INDEX, _risc_rcg_inc_array_index_handler}, + {SCF_OP_3AC_INC_POINTER, _risc_rcg_inc_pointer_handler}, + + {SCF_OP_3AC_INC_POST_DEREFERENCE, _risc_rcg_inc_post_dereference_handler}, + {SCF_OP_3AC_INC_POST_ARRAY_INDEX, _risc_rcg_inc_post_array_index_handler}, + {SCF_OP_3AC_INC_POST_POINTER, _risc_rcg_inc_post_pointer_handler}, + + {SCF_OP_3AC_DEC_DEREFERENCE, _risc_rcg_dec_dereference_handler}, + {SCF_OP_3AC_DEC_ARRAY_INDEX, _risc_rcg_dec_array_index_handler}, + {SCF_OP_3AC_DEC_POINTER, _risc_rcg_dec_pointer_handler}, + + {SCF_OP_3AC_DEC_POST_DEREFERENCE, _risc_rcg_dec_post_dereference_handler}, + {SCF_OP_3AC_DEC_POST_ARRAY_INDEX, _risc_rcg_dec_post_array_index_handler}, + {SCF_OP_3AC_DEC_POST_POINTER, _risc_rcg_dec_post_pointer_handler}, + + {SCF_OP_3AC_ADDRESS_OF_ARRAY_INDEX, _risc_rcg_address_of_array_index_handler}, + {SCF_OP_3AC_ADDRESS_OF_POINTER, _risc_rcg_address_of_pointer_handler}, +}; + +risc_rcg_handler_t* scf_risc_find_rcg_handler(const int op_type) +{ + int i; + for (i = 0; i < sizeof(risc_rcg_handlers) / sizeof(risc_rcg_handlers[0]); i++) { + + risc_rcg_handler_t* h = &(risc_rcg_handlers[i]); + + if (op_type == h->type) + return h; + } + return NULL; +} diff --git a/native/risc/scf_risc_reg.c b/native/risc/scf_risc_reg.c new file mode 100644 index 0000000..1f3c080 --- /dev/null +++ b/native/risc/scf_risc_reg.c @@ -0,0 +1,1462 @@ +#include"scf_risc.h" + +scf_register_t risc_registers[] = { + + {0, 4, "w0", RISC_COLOR(0, 0, 0xf), NULL, 0, 0}, + {0, 8, "x0", RISC_COLOR(0, 0, 0xff), NULL, 0, 0}, + + {1, 4, "w1", RISC_COLOR(0, 1, 0xf), NULL, 0, 0}, + {1, 8, "x1", RISC_COLOR(0, 1, 0xff), NULL, 0, 0}, + + {2, 4, "w2", RISC_COLOR(0, 2, 0xf), NULL, 0, 0}, + {2, 8, "x2", RISC_COLOR(0, 2, 0xff), NULL, 0, 0}, + + {3, 4, "w3", RISC_COLOR(0, 3, 0xf), NULL, 0, 0}, + {3, 8, "x3", RISC_COLOR(0, 3, 0xff), NULL, 0, 0}, + + {4, 4, "w4", RISC_COLOR(0, 4, 0xf), NULL, 0, 0}, + {4, 8, "x4", RISC_COLOR(0, 4, 0xff), NULL, 0, 0}, + + {5, 4, "w5", RISC_COLOR(0, 5, 0xf), NULL, 0, 0}, + {5, 8, "x5", RISC_COLOR(0, 5, 0xff), NULL, 0, 0}, + + {6, 4, "w6", RISC_COLOR(0, 6, 0xf), NULL, 0, 0}, + {6, 8, "x6", RISC_COLOR(0, 6, 0xff), NULL, 0, 0}, + + {7, 4, "w7", RISC_COLOR(0, 7, 0xf), NULL, 0, 0}, + {7, 8, "x7", RISC_COLOR(0, 7, 0xff), NULL, 0, 0}, + +// not use x8 + +// {8, 4, "w8", RISC_COLOR(0, 8, 0xf), NULL, 0}, +// {8, 8, "x8", RISC_COLOR(0, 8, 0xff), NULL, 0}, + + {9, 4, "w9", RISC_COLOR(0, 9, 0xf), NULL, 0, 0}, + {9, 8, "x9", RISC_COLOR(0, 9, 0xff), NULL, 0, 0}, + + {10, 4, "w10", RISC_COLOR(0, 10, 0xf), NULL, 0, 0}, + {10, 8, "x10", RISC_COLOR(0, 10, 0xff), NULL, 0, 0}, + + {11, 4, "w11", RISC_COLOR(0, 11, 0xf), NULL, 0, 0}, + {11, 8, "x11", RISC_COLOR(0, 11, 0xff), NULL, 0, 0}, + + {12, 4, "w12", RISC_COLOR(0, 12, 0xf), NULL, 0, 0}, + {12, 8, "x12", RISC_COLOR(0, 12, 0xff), NULL, 0, 0}, + + {13, 4, "w13", RISC_COLOR(0, 13, 0xf), NULL, 0, 0}, + {13, 8, "x13", RISC_COLOR(0, 13, 0xff), NULL, 0, 0}, + + {14, 4, "w14", RISC_COLOR(0, 14, 0xf), NULL, 0, 0}, + {14, 8, "x14", RISC_COLOR(0, 14, 0xff), NULL, 0, 0}, + + {15, 4, "w15", RISC_COLOR(0, 15, 0xf), NULL, 0, 0}, + {15, 8, "x15", RISC_COLOR(0, 15, 0xff), NULL, 0, 0}, + +// not use x16, x17, x18 + + {16, 4, "w16", RISC_COLOR(0, 16, 0xf), NULL, 0, 0}, + {16, 8, "x16", RISC_COLOR(0, 16, 0xff), NULL, 0, 0}, + + {17, 4, "w17", RISC_COLOR(0, 17, 0xf), NULL, 0, 0}, + {17, 8, "x17", RISC_COLOR(0, 17, 0xff), NULL, 0, 0}, + +// {18, 4, "w18", RISC_COLOR(0, 18, 0xf), NULL, 0, 0}, +// {18, 8, "x18", RISC_COLOR(0, 18, 0xff), NULL, 0, 0}, + + {19, 4, "w19", RISC_COLOR(0, 19, 0xf), NULL, 0, 0}, + {19, 8, "x19", RISC_COLOR(0, 19, 0xff), NULL, 0, 0}, + + {20, 4, "w20", RISC_COLOR(0, 20, 0xf), NULL, 0, 0}, + {20, 8, "x20", RISC_COLOR(0, 20, 0xff), NULL, 0, 0}, + + {21, 4, "w21", RISC_COLOR(0, 21, 0xf), NULL, 0, 0}, + {21, 8, "x21", RISC_COLOR(0, 21, 0xff), NULL, 0, 0}, + + {22, 4, "w22", RISC_COLOR(0, 22, 0xf), NULL, 0, 0}, + {22, 8, "x22", RISC_COLOR(0, 22, 0xff), NULL, 0, 0}, + + {23, 4, "w23", RISC_COLOR(0, 23, 0xf), NULL, 0, 0}, + {23, 8, "x23", RISC_COLOR(0, 23, 0xff), NULL, 0, 0}, + + {24, 4, "w24", RISC_COLOR(0, 24, 0xf), NULL, 0, 0}, + {24, 8, "x24", RISC_COLOR(0, 24, 0xff), NULL, 0, 0}, + + {25, 4, "w25", RISC_COLOR(0, 25, 0xf), NULL, 0, 0}, + {25, 8, "x25", RISC_COLOR(0, 25, 0xff), NULL, 0, 0}, + + {26, 4, "w26", RISC_COLOR(0, 26, 0xf), NULL, 0, 0}, + {26, 8, "x26", RISC_COLOR(0, 26, 0xff), NULL, 0, 0}, + + {27, 4, "w27", RISC_COLOR(0, 27, 0xf), NULL, 0, 0}, + {27, 8, "x27", RISC_COLOR(0, 27, 0xff), NULL, 0, 0}, + + {28, 4, "w28", RISC_COLOR(0, 28, 0xf), NULL, 0, 0}, + {28, 8, "x28", RISC_COLOR(0, 28, 0xff), NULL, 0, 0}, + +// fp = x29 = bp + {29, 4, "w29", RISC_COLOR(0, 29, 0xf), NULL, 0, 0}, + {29, 8, "fp", RISC_COLOR(0, 29, 0xff), NULL, 0, 0}, +// lr = x30 + {30, 4, "w30", RISC_COLOR(0, 30, 0xf), NULL, 0, 0}, + {30, 8, "lr", RISC_COLOR(0, 30, 0xff), NULL, 0, 0}, + {31, 8, "sp", RISC_COLOR(0, 31, 0xff), NULL, 0, 0}, + + + {0, 2, "h0", RISC_COLOR(1, 0, 0x3), NULL, 0, 0}, + {0, 4, "s0", RISC_COLOR(1, 0, 0xf), NULL, 0, 0}, + {0, 8, "d0", RISC_COLOR(1, 0, 0xff), NULL, 0, 0}, + + {1, 2, "h1", RISC_COLOR(1, 1, 0x3), NULL, 0, 0}, + {1, 4, "s1", RISC_COLOR(1, 1, 0xf), NULL, 0, 0}, + {1, 8, "d1", RISC_COLOR(1, 1, 0xff), NULL, 0, 0}, + + {2, 2, "h2", RISC_COLOR(1, 2, 0x3), NULL, 0, 0}, + {2, 4, "s2", RISC_COLOR(1, 2, 0xf), NULL, 0, 0}, + {2, 8, "d2", RISC_COLOR(1, 2, 0xff), NULL, 0, 0}, + + {3, 2, "h3", RISC_COLOR(1, 3, 0x3), NULL, 0, 0}, + {3, 4, "s3", RISC_COLOR(1, 3, 0xf), NULL, 0, 0}, + {3, 8, "d3", RISC_COLOR(1, 3, 0xff), NULL, 0, 0}, + + {4, 2, "h4", RISC_COLOR(1, 4, 0x3), NULL, 0, 0}, + {4, 4, "s4", RISC_COLOR(1, 4, 0xf), NULL, 0, 0}, + {4, 8, "d4", RISC_COLOR(1, 4, 0xff), NULL, 0, 0}, + + {5, 2, "h5", RISC_COLOR(1, 5, 0x3), NULL, 0, 0}, + {5, 4, "s5", RISC_COLOR(1, 5, 0xf), NULL, 0, 0}, + {5, 8, "d5", RISC_COLOR(1, 5, 0xff), NULL, 0, 0}, + + {6, 2, "h6", RISC_COLOR(1, 6, 0x3), NULL, 0, 0}, + {6, 4, "s6", RISC_COLOR(1, 6, 0xf), NULL, 0, 0}, + {6, 8, "d6", RISC_COLOR(1, 6, 0xff), NULL, 0, 0}, + + {7, 2, "h7", RISC_COLOR(1, 7, 0x3), NULL, 0, 0}, + {7, 4, "s7", RISC_COLOR(1, 7, 0xf), NULL, 0, 0}, + {7, 8, "d7", RISC_COLOR(1, 7, 0xff), NULL, 0, 0}, + + {8, 2, "h8", RISC_COLOR(1, 8, 0x3), NULL, 0, 0}, + {8, 4, "s8", RISC_COLOR(1, 8, 0xf), NULL, 0, 0}, + {8, 8, "d8", RISC_COLOR(1, 8, 0xff), NULL, 0, 0}, + + {9, 2, "h9", RISC_COLOR(1, 9, 0x3), NULL, 0, 0}, + {9, 4, "s9", RISC_COLOR(1, 9, 0xf), NULL, 0, 0}, + {9, 8, "d9", RISC_COLOR(1, 9, 0xff), NULL, 0, 0}, + + {10, 2, "h10", RISC_COLOR(1, 10, 0x3), NULL, 0, 0}, + {10, 4, "s10", RISC_COLOR(1, 10, 0xf), NULL, 0, 0}, + {10, 8, "d10", RISC_COLOR(1, 10, 0xff), NULL, 0, 0}, + + {11, 2, "h11", RISC_COLOR(1, 11, 0x3), NULL, 0, 0}, + {11, 4, "s11", RISC_COLOR(1, 11, 0xf), NULL, 0, 0}, + {11, 8, "d11", RISC_COLOR(1, 11, 0xff), NULL, 0, 0}, + + {12, 2, "h12", RISC_COLOR(1, 12, 0x3), NULL, 0, 0}, + {12, 4, "s12", RISC_COLOR(1, 12, 0xf), NULL, 0, 0}, + {12, 8, "d12", RISC_COLOR(1, 12, 0xff), NULL, 0, 0}, + + {13, 2, "h13", RISC_COLOR(1, 13, 0x3), NULL, 0, 0}, + {13, 4, "s13", RISC_COLOR(1, 13, 0xf), NULL, 0, 0}, + {13, 8, "d13", RISC_COLOR(1, 13, 0xff), NULL, 0, 0}, + + {14, 2, "h14", RISC_COLOR(1, 14, 0x3), NULL, 0, 0}, + {14, 4, "s14", RISC_COLOR(1, 14, 0xf), NULL, 0, 0}, + {14, 8, "d14", RISC_COLOR(1, 14, 0xff), NULL, 0, 0}, + + {15, 2, "h15", RISC_COLOR(1, 15, 0x3), NULL, 0, 0}, + {15, 4, "s15", RISC_COLOR(1, 15, 0xf), NULL, 0, 0}, + {15, 8, "d15", RISC_COLOR(1, 15, 0xff), NULL, 0, 0}, + + {16, 2, "h16", RISC_COLOR(1, 16, 0x3), NULL, 0, 0}, + {16, 4, "s16", RISC_COLOR(1, 16, 0xf), NULL, 0, 0}, + {16, 8, "d16", RISC_COLOR(1, 16, 0xff), NULL, 0, 0}, + + {17, 2, "h17", RISC_COLOR(1, 17, 0x3), NULL, 0, 0}, + {17, 4, "s17", RISC_COLOR(1, 17, 0xf), NULL, 0, 0}, + {17, 8, "d17", RISC_COLOR(1, 17, 0xff), NULL, 0, 0}, + + {18, 2, "h18", RISC_COLOR(1, 18, 0x3), NULL, 0, 0}, + {18, 4, "s18", RISC_COLOR(1, 18, 0xf), NULL, 0, 0}, + {18, 8, "d18", RISC_COLOR(1, 18, 0xff), NULL, 0, 0}, + + {19, 2, "h19", RISC_COLOR(1, 19, 0x3), NULL, 0, 0}, + {19, 4, "s19", RISC_COLOR(1, 19, 0xf), NULL, 0, 0}, + {19, 8, "d19", RISC_COLOR(1, 19, 0xff), NULL, 0, 0}, + + {20, 2, "h20", RISC_COLOR(1, 20, 0x3), NULL, 0, 0}, + {20, 4, "s20", RISC_COLOR(1, 20, 0xf), NULL, 0, 0}, + {20, 8, "d20", RISC_COLOR(1, 20, 0xff), NULL, 0, 0}, + + {21, 2, "h21", RISC_COLOR(1, 21, 0x3), NULL, 0, 0}, + {21, 4, "s21", RISC_COLOR(1, 21, 0xf), NULL, 0, 0}, + {21, 8, "d21", RISC_COLOR(1, 21, 0xff), NULL, 0, 0}, + + {22, 2, "h22", RISC_COLOR(1, 22, 0x3), NULL, 0, 0}, + {22, 4, "s22", RISC_COLOR(1, 22, 0xf), NULL, 0, 0}, + {22, 8, "d22", RISC_COLOR(1, 22, 0xff), NULL, 0, 0}, + + {23, 2, "h23", RISC_COLOR(1, 23, 0x3), NULL, 0, 0}, + {23, 4, "s23", RISC_COLOR(1, 23, 0xf), NULL, 0, 0}, + {23, 8, "d23", RISC_COLOR(1, 23, 0xff), NULL, 0, 0}, + + {24, 2, "h24", RISC_COLOR(1, 24, 0x3), NULL, 0, 0}, + {24, 4, "s24", RISC_COLOR(1, 24, 0xf), NULL, 0, 0}, + {24, 8, "d24", RISC_COLOR(1, 24, 0xff), NULL, 0, 0}, + + {25, 2, "h25", RISC_COLOR(1, 25, 0x3), NULL, 0, 0}, + {25, 4, "s25", RISC_COLOR(1, 25, 0xf), NULL, 0, 0}, + {25, 8, "d25", RISC_COLOR(1, 25, 0xff), NULL, 0, 0}, + + {26, 2, "h26", RISC_COLOR(1, 26, 0x3), NULL, 0, 0}, + {26, 4, "s26", RISC_COLOR(1, 26, 0xf), NULL, 0, 0}, + {26, 8, "d26", RISC_COLOR(1, 26, 0xff), NULL, 0, 0}, + + {27, 2, "h27", RISC_COLOR(1, 27, 0x3), NULL, 0, 0}, + {27, 4, "s27", RISC_COLOR(1, 27, 0xf), NULL, 0, 0}, + {27, 8, "d27", RISC_COLOR(1, 27, 0xff), NULL, 0, 0}, + + {28, 2, "h28", RISC_COLOR(1, 28, 0x3), NULL, 0, 0}, + {28, 4, "s28", RISC_COLOR(1, 28, 0xf), NULL, 0, 0}, + {28, 8, "d28", RISC_COLOR(1, 28, 0xff), NULL, 0, 0}, + + {29, 2, "h29", RISC_COLOR(1, 29, 0x3), NULL, 0, 0}, + {29, 4, "s29", RISC_COLOR(1, 29, 0xf), NULL, 0, 0}, + {29, 8, "d29", RISC_COLOR(1, 29, 0xff), NULL, 0, 0}, + + {30, 2, "h30", RISC_COLOR(1, 30, 0x3), NULL, 0, 0}, + {30, 4, "s30", RISC_COLOR(1, 30, 0xf), NULL, 0, 0}, + {30, 8, "d30", RISC_COLOR(1, 30, 0xff), NULL, 0, 0}, + + {31, 2, "h31", RISC_COLOR(1, 31, 0x3), NULL, 0, 0}, + {31, 4, "s31", RISC_COLOR(1, 31, 0xf), NULL, 0, 0}, + {31, 8, "d31", RISC_COLOR(1, 31, 0xff), NULL, 0, 0}, +}; + +int risc_reg_cached_vars(scf_register_t* r) +{ + int nb_vars = 0; + int i; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r2 = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X16 == r2->id + || SCF_RISC_REG_X17 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + nb_vars += r2->dag_nodes->size; + } + + return nb_vars; +} + +int risc_registers_init() +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + assert(!r->dag_nodes); + + r->dag_nodes = scf_vector_alloc(); + if (!r->dag_nodes) + return -ENOMEM; + + r->used = 0; + } + + return 0; +} + +void risc_registers_clear() +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (r->dag_nodes) { + scf_vector_free(r->dag_nodes); + r->dag_nodes = NULL; + } + + r->used = 0; + } +} + +int risc_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs) +{ + int i; + int j; + scf_register_t* r; + scf_register_t* r2; + scf_instruction_t* inst; + scf_register_t* sp = risc_find_register("sp"); + + uint32_t opcode; + + int ret; + int size = 0; + int k = 0; + + for (j = 0; j < nb_regs; j++) { + r2 = risc_find_register_type_id_bytes(0, regs[j], 8); + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (0 == r->dag_nodes->size) + continue; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == sizeof(risc_registers) / sizeof(risc_registers[0])) + continue; + + if (stack_size > 0) { + ret = f->iops->G2P(c, f, r2, sp, size + stack_size, 8); + if (ret < 0) + return ret; + } else { + inst = f->iops->PUSH(NULL, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + saved_regs[k++] = r2; + size += 8; + } + + if (size & 0xf) { + r2 = saved_regs[k - 1]; + + if (stack_size > 0) { + ret = f->iops->G2P(c, f, r2, sp, size + stack_size, 8); + if (ret < 0) + return ret; + } else { + inst = f->iops->PUSH(NULL, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + saved_regs[k++] = r2; + size += 8; + } + + if (stack_size > 0) { + for (j = 0; j < k / 2; j++) { + + i = k - 1 - j; + SCF_XCHG(saved_regs[i], saved_regs[j]); + } + } + + return size; +} + +int risc_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated) +{ + int i; + int j; + + scf_register_t* sp = risc_find_register("sp"); + scf_register_t* r; + scf_register_t* r2; + scf_instruction_t* inst; + + for (j = nb_regs - 1; j >= 0; j--) { + r2 = regs[j]; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (0 == r->dag_nodes->size) + continue; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == sizeof(risc_registers) / sizeof(risc_registers[0])) + continue; + + for (i = 0; i < nb_updated; i++) { + + r = updated_regs[i]; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == nb_updated) { + inst = f->iops->POP(c, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } else { + inst = f->iops->ADD_IMM(c, sp, sp, 8); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + } + return 0; +} + +int risc_registers_reset() +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (!r->dag_nodes) + continue; + + int j = 0; + while (j < r->dag_nodes->size) { + scf_dag_node_t* dn = r->dag_nodes->data[j]; + + if (dn->var->w) + scf_logw("drop: v_%d_%d/%s\n", dn->var->w->line, dn->var->w->pos, dn->var->w->text->data); + else + scf_logw("drop: v_%#lx\n", 0xffff & (uintptr_t)dn->var); + + int ret = scf_vector_del(r->dag_nodes, dn); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + dn->loaded = 0; + dn->color = 0; + } + } + + return 0; +} + +scf_register_t* risc_find_register(const char* name) +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (!strcmp(r->name, name)) + return r; + } + return NULL; +} + +scf_register_t* risc_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes) +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (RISC_COLOR_TYPE(r->color) == type && r->id == id && r->bytes == bytes) + return r; + } + return NULL; +} + +scf_register_t* risc_find_register_color(intptr_t color) +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (r->color == color) + return r; + } + return NULL; +} + +scf_register_t* risc_find_register_color_bytes(intptr_t color, int bytes) +{ + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (RISC_COLOR_CONFLICT(r->color, color) && r->bytes == bytes) + return r; + } + return NULL; +} + +scf_vector_t* risc_register_colors() +{ + scf_vector_t* colors = scf_vector_alloc(); + if (!colors) + return NULL; + + int i; + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + int ret = scf_vector_add(colors, (void*)r->color); + if (ret < 0) { + scf_vector_free(colors); + return NULL; + } + } +#if 0 + srand(time(NULL)); + for (i = 0; i < colors->size; i++) { + int j = rand() % colors->size; + + void* t = colors->data[i]; + colors->data[i] = colors->data[j]; + colors->data[j] = t; + } +#endif + return colors; +} + +int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_variable_t* v = dn->var; + scf_rela_t* rela = NULL; + scf_risc_OpCode_t* mov; + scf_instruction_t* inst; + + int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + + assert(size == r->bytes); + + if (scf_variable_const(v)) { + scf_logw("const literal var: v_%s_%d_%d not save\n", v->w->text->data, v->w->line, v->w->pos); + goto end; + } + + // if temp var in register, alloc it in stack + if (0 == v->bp_offset && !v->global_flag && !v->local_flag) { + + int tmp = f->local_vars_size; + tmp += size; + + if (tmp & 0x7) + tmp = (tmp + 7) >> 3 << 3; + + v->bp_offset = -tmp; + v->tmp_flag = 1; + + f->local_vars_size = tmp; + } + +#if 1 + if (v->w) + scf_logw("save var: v_%d_%d/%s, ", v->w->line, v->w->pos, v->w->text->data); + else + scf_logw("save var: v_%#lx, ", 0xffff & (uintptr_t)v); + printf("size: %d, bp_offset: %d, r: %s\n", size, v->bp_offset, r->name); +#endif + + int ret = f->iops->G2M(c, f, r, NULL, v); + if (ret < 0) + return ret; + +end: + // if this var is function argment, it become a normal local var + v->arg_flag = 0; + dn->color = -1; + dn->loaded = 0; + + scf_vector_del(r->dag_nodes, dn); + return 0; +} + +int risc_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + if (dn->color <= 0) + return -EINVAL; + + scf_register_t* r = risc_find_register_color(dn->color); + + return risc_save_var2(dn, r, c, f); +} + +int risc_save_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f) +{ + int i = 0; + while (i < r->dag_nodes->size) { + + scf_dag_node_t* dn = r->dag_nodes->data[i]; + + int ret = risc_save_var(dn, c, f); + if (ret < 0) { + scf_loge("i: %d, size: %d, r: %s, dn->var: %s\n", i, r->dag_nodes->size, r->name, dn->var->w->text->data); + return ret; + } + } + + return 0; +} + +int risc_overflow_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f) +{ + int i; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r2 = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X16 == r2->id + || SCF_RISC_REG_X17 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + int ret = risc_save_reg(r2, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + r->used = 1; + return 0; +} + +int risc_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* r2; + scf_dag_node_t* dn2; + + int i; + int j; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + r2 = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X16 == r2->id + || SCF_RISC_REG_X17 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; ) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 == dn) { + j++; + continue; + } + + int ret = risc_save_var(dn2, c, f); + if (ret < 0) + return ret; + } + } + + r->used = 1; + return 0; +} + +static int _risc_overflow_reg3(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* r2; + scf_dn_status_t* ds2; + scf_dag_node_t* dn2; + + int i; + int j; + int ret; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + r2 = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X16 == r2->id + || SCF_RISC_REG_X17 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; ) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 == dn) { + j++; + continue; + } + + ds2 = scf_vector_find_cmp(c->active_vars, dn2, scf_dn_status_cmp); + if (!ds2) { + j++; + continue; + } + + if (!ds2->active) { + j++; + continue; + } +#if 1 + scf_variable_t* v = dn->var; + scf_variable_t* v2 = dn2->var; + if (v->w) + scf_loge("v_%d_%d/%s, bp_offset: %d\n", v->w->line, v->w->pos, v->w->text->data, v->bp_offset); + else + scf_loge("v_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v, v->bp_offset); + + if (v2->w) + scf_loge("v2_%d_%d/%s, bp_offset: %d\n", v2->w->line, v2->w->pos, v2->w->text->data, v2->bp_offset); + else + scf_loge("v2_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v2, v2->bp_offset); +#endif + int ret = risc_save_var(dn2, c, f); + if (ret < 0) + return ret; + } + } + + r->used = 1; + return 0; +} + +int risc_reg_used(scf_register_t* r, scf_dag_node_t* dn) +{ + scf_register_t* r2; + scf_dag_node_t* dn2; + + int i; + int j; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + r2 = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X16 == r2->id + || SCF_RISC_REG_X17 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; j++) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 != dn) + return 1; + } + } + return 0; +} + +static scf_register_t* _risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs) +{ + scf_register_t* r_min = NULL; + + int min = 0; + int i; + + for (i = 0; i < nb_regs; i++) { + scf_register_t* r = regs[i]; + + int nb_vars = risc_reg_cached_vars(r); + + if (!r_min) { + r_min = r; + min = nb_vars; + continue; + } + + if (min > nb_vars) { + r_min = r; + min = nb_vars; + } + } + + return r_min; +} + +scf_register_t* risc_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float) +{ + scf_vector_t* neighbors = NULL; + scf_graph_node_t* gn = NULL; + + scf_register_t* free_regs[sizeof(risc_registers) / sizeof(risc_registers[0])]; + + int nb_free_regs = 0; + int bytes = 8; + int ret; + int i; + int j; + + assert(c->rcg); + + if (dn) { + is_float = scf_variable_float(dn->var); + bytes = risc_variable_size (dn->var); + } + + ret = risc_rcg_find_node(&gn, c->rcg, dn, NULL); + if (ret < 0) + neighbors = c->rcg->nodes; + else + neighbors = gn->neighbors; + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float) + continue; + + for (j = 0; j < neighbors->size; j++) { + + scf_graph_node_t* neighbor = neighbors->data[j]; + risc_rcg_node_t* rn = neighbor->data; + + if (rn->dag_node) { + if (rn->dag_node->color <= 0) + continue; + + if (RISC_COLOR_CONFLICT(r->color, rn->dag_node->color)) + break; + } else { + assert(rn->reg); + + if (RISC_COLOR_CONFLICT(r->color, rn->reg->color)) + break; + } + } + + if (j == neighbors->size) + free_regs[nb_free_regs++] = r; + } + + if (nb_free_regs > 0) + return _risc_reg_cached_min_vars(free_regs, nb_free_regs); + + for (i = 0; i < sizeof(risc_registers) / sizeof(risc_registers[0]); i++) { + + scf_register_t* r = &(risc_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X16 == r->id + || SCF_RISC_REG_X17 == r->id) + continue; + + if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float) + continue; + + if (c->dsts) { + scf_3ac_operand_t* dst; + + for (j = 0; j < c->dsts->size; j++) { + dst = c->dsts->data[j]; + + if (dst->dag_node && dst->dag_node->color > 0 + && RISC_COLOR_CONFLICT(r->color, dst->dag_node->color)) + break; + } + + if (j < c->dsts->size) + continue; + } + + if (c->srcs) { + scf_3ac_operand_t* src; + + for (j = 0; j < c->srcs->size; j++) { + src = c->srcs->data[j]; + + if (src->dag_node && src->dag_node->color > 0 + && RISC_COLOR_CONFLICT(r->color, src->dag_node->color)) + break; + } + + if (j < c->srcs->size) + continue; + } + + return r; + } + + return NULL; +} + +int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_instruction_t* inst; + scf_variable_t* v; + + v = dn->var; + r->used = 1; + + int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + + if (SCF_FUNCTION_PTR == v->type) { + + if (v->func_ptr) { + assert(v->const_literal_flag); + + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + + return f->iops->M2G(c, f, r, NULL, v); + + } else { + scf_loge("\n"); + return -EINVAL; + } + + } else if (scf_variable_const_string(v)) { + + return f->iops->ISTR2G(c, f, r, v); + + } else if (v->nb_dimentions > 0) { + assert(v->const_literal_flag); + + return f->iops->ADR2G(c, f, r, v); + } + + return f->iops->I2G(c, r, v->data.u64, size); +} + +int risc_load_reg(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + if (dn->loaded) + return 0; + + scf_risc_OpCode_t* mov; + scf_instruction_t* inst; + scf_rela_t* rela = NULL; + + int is_float = scf_variable_float(dn->var); + int var_size = risc_variable_size(dn->var); + + r->used = 1; + + if (!is_float) { + + if (scf_variable_const(dn->var)) { + + int ret = risc_load_const(r, dn, c, f); + if (ret < 0) + return ret; + + dn->loaded = 1; + return 0; + } + + if (!dn->var->global_flag && !dn->var->local_flag && !dn->var->tmp_flag) + return 0; + + if (scf_variable_const_string(dn->var)) { + + int ret = f->iops->ISTR2G(c, f, r, dn->var); + if (ret < 0) + return ret; + + dn->loaded = 1; + return 0; + } + + if (0 == dn->var->bp_offset && !dn->var->global_flag) { + scf_loge("\n"); + return -EINVAL; + } + + if ((dn->var->nb_dimentions > 0 && dn->var->const_literal_flag) + || (dn->var->type >= SCF_STRUCT && 0 == dn->var->nb_pointers)) { + + int ret = f->iops->ADR2G(c, f, r, dn->var); + if (ret < 0) + return ret; + + dn->loaded = 1; + return 0; + } + + int ret = f->iops->M2G(c, f, r, NULL, dn->var); + if (ret < 0) + return ret; + + dn->loaded = 1; + return 0; + } + + if (!dn->var->global_flag && !dn->var->local_flag && !dn->var->tmp_flag) + return 0; + + if (0 == dn->var->bp_offset && !dn->var->global_flag) { + scf_loge("\n"); + return -EINVAL; + } + + int ret = f->iops->M2GF(c, f, r, NULL, dn->var); + if (ret < 0) + return ret; + + dn->loaded = 1; + return 0; +} + +int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag) +{ + if (0 == dn->color) + return -EINVAL; + + scf_register_t* r; + + int ret; + int is_float = scf_variable_float(dn->var); + int var_size = risc_variable_size(dn->var); + + if (dn->color > 0) { + r = risc_find_register_color(dn->color); +#if 1 + ret = _risc_overflow_reg3(r, dn, c, f); + if (ret < 0) { + scf_loge("\n"); + return -1; + } +#endif + } else { + r = risc_select_overflowed_reg(dn, c, is_float); + if (!r) { + scf_loge("\n"); + return -1; + } + + ret = risc_overflow_reg(r, c, f); + if (ret < 0) { + scf_loge("overflow reg failed\n"); + return ret; + } + assert(0 == r->dag_nodes->size); + + r = risc_find_register_type_id_bytes(is_float, r->id, var_size); + assert(0 == r->dag_nodes->size); + + dn->color = r->color; + } + + ret = scf_vector_add_unique(r->dag_nodes, dn); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (load_flag) { + ret = risc_load_reg(r, dn, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } else + dn->loaded = 1; + + r->used = 1; + *preg = r; + return 0; +} + +int risc_select_free_reg(scf_register_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float) +{ + scf_register_t* r; + + r = risc_select_overflowed_reg(NULL, c, is_float); + if (!r) { + scf_loge("\n"); + return -1; + } + + int ret = risc_overflow_reg(r, c, f); + if (ret < 0) { + scf_loge("overflow reg failed\n"); + return ret; + } + assert(0 == r->dag_nodes->size); + + r = risc_find_register_type_id_bytes(0, r->id, 8); + assert(0 == r->dag_nodes->size); + + ret = risc_rcg_make(c, c->rcg, NULL, r); + if (ret < 0) + return ret; + + r->used = 1; + + *preg = r; + return 0; +} + +int risc_dereference_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* rb = NULL; + scf_variable_t* vb = base->var; + + scf_logw("base->color: %ld\n", base->color); + + int ret = risc_select_reg(&rb, base, c, f, 1); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + scf_logw("base->color: %ld\n", base->color); + + if (vb->nb_pointers + vb->nb_dimentions > 1 || vb->type >= SCF_STRUCT) + sib->size = 8; + else { + sib->size = vb->data_size; + assert(8 >= vb->data_size); + } + + sib->base = rb; + sib->index = NULL; + sib->scale = 0; + sib->disp = 0; + return 0; +} + +int risc_pointer_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_variable_t* vb = base ->var; + scf_variable_t* vm = member->var; + scf_register_t* rb = NULL; + scf_instruction_t* inst; + + int ret; + int32_t disp = 0; + + if (vb->nb_pointers > 0 && 0 == vb->nb_dimentions) { + + ret = risc_select_reg(&rb, base, c, f, 1); + if (ret < 0) + return ret; + + } else if (vb->local_flag) { + + rb = risc_find_register("fp"); + disp = vb->bp_offset; + + } else if (vb->global_flag) { + + ret = risc_select_reg(&rb, base, c, f, 0); + if (ret < 0) + return ret; + + ret = f->iops->ADR2G(c, f, rb, vb); + if (ret < 0) + return ret; + + } else { + ret = risc_select_reg(&rb, base, c, f, 0); + if (ret < 0) + return ret; + } + + disp += vm->offset; + + sib->base = rb; + sib->index = NULL; + sib->scale = 0; + sib->disp = disp; + sib->size = risc_variable_size(vm); + return 0; +} + +int risc_array_index_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_dag_node_t* scale, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_variable_t* vb = base ->var; + scf_variable_t* vi = index->var; + + scf_register_t* rb = NULL; + scf_register_t* ri = NULL; + scf_register_t* rs = NULL; + scf_register_t* rd = NULL; + + scf_risc_OpCode_t* xor; + scf_risc_OpCode_t* add; + scf_risc_OpCode_t* shl; + scf_risc_OpCode_t* lea; + scf_risc_OpCode_t* mov; + scf_instruction_t* inst; + + int ret; + int i; + + uint32_t opcode; + int32_t disp = 0; + + if (vb->nb_pointers > 0 && 0 == vb->nb_dimentions) { + + ret = risc_select_reg(&rb, base, c, f, 1); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } else if (vb->local_flag) { + + rb = risc_find_register("fp"); + disp = vb->bp_offset; + + } else if (vb->global_flag) { + scf_rela_t* rela = NULL; + + if (0 == base->color) + base->color = -1; + + ret = risc_select_reg(&rb, base, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = f->iops->ADR2G(c, f, rb, vb); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + } else { + ret = risc_select_reg(&rb, base, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + int32_t s = scale->var->data.i; + assert(s > 0); + + if (vb->nb_pointers + vb->nb_dimentions > 1 || vb->type >= SCF_STRUCT) + sib->size = 8; + else { + sib->size = vb->data_size; + assert(8 >= vb->data_size); + } + + if (0 == index->color) { + disp += vi->data.i * s; + + sib->base = rb; + sib->index = NULL; + sib->scale = 0; + sib->disp = disp; + return 0; + } + + ret = risc_select_reg(&ri, index, c, f, 1); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + scf_register_t* ri2 = risc_find_register_color_bytes(ri->color, 8); + + if (ri->bytes < ri2->bytes) { + + if (scf_variable_signed(index->var)) { + + inst = f->iops->MOVSX(c, ri, ri, ri->bytes); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + ri = ri2; + } + + if (1 != s + && 2 != s + && 4 != s + && 8 != s) { + + assert(8 == scale->var->size); + + ret = risc_select_reg(&rs, scale, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = f->iops->I2G(c, rs, s, sizeof(s)); + if (ret < 0) + return ret; + + inst = f->iops->MUL(c, rs, rs, ri); + RISC_INST_ADD_CHECK(c->instructions, inst); + + ri = rs; + s = 1; + } + + if (disp != 0) { + + if (!rs) { + ret = risc_select_reg(&rs, scale, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + if (disp > 0 && disp <= 0xfff) + inst = f->iops->ADD_IMM(c, rs, rb, disp); + + else if (disp < 0 && -disp <= 0xfff) + inst = f->iops->SUB_IMM(c, rs, rb, -disp); + + else { + ret = f->iops->I2G(c, rs, disp, 4); + if (ret < 0) + return ret; + + inst = f->iops->ADD_G(c, rs, rs, rb); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else { + assert(1 == s); + + if (disp > 0 && disp <= 0xfff) + inst = f->iops->ADD_IMM(c, rs, rb, disp); + + else if (disp < 0 && -disp <= 0xfff) + inst = f->iops->SUB_IMM(c, rs, rb, -disp); + + else { + ret = risc_select_free_reg(&rd, c, f, 0); + if (ret < 0) + return ret; + + ret = f->iops->I2G(c, rd, disp, 4); + if (ret < 0) + return ret; + + inst = f->iops->ADD_G(c, rs, rb, rd); + } + + RISC_INST_ADD_CHECK(c->instructions, inst); + ri = NULL; + } + + rb = rs; + } + + sib->base = rb; + sib->index = ri; + sib->scale = s; + sib->disp = 0; + return 0; +} + +void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c) +{ + scf_3ac_operand_t* src = NULL; + scf_dag_node_t* dn = NULL; + + int nfloats = 0; + int nints = 0; + int i; + + for (i = 1; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + dn = src->dag_node; + + int is_float = scf_variable_float(dn->var); + int size = risc_variable_size (dn->var); + + if (is_float) { + if (nfloats < RISC_ABI_NB) + dn->rabi2 = risc_find_register_type_id_bytes(is_float, risc_abi_float_regs[nfloats++], size); + else + dn->rabi2 = NULL; + } else { + if (nints < RISC_ABI_NB) + dn->rabi2 = risc_find_register_type_id_bytes(is_float, risc_abi_regs[nints++], size); + else + dn->rabi2 = NULL; + } + + src->rabi = dn->rabi2; + } + + if (p_nints) + *p_nints = nints; + + if (p_nfloats) + *p_nfloats = nfloats; +} + diff --git a/native/risc/scf_risc_reg.h b/native/risc/scf_risc_reg.h new file mode 100644 index 0000000..5f3514c --- /dev/null +++ b/native/risc/scf_risc_reg.h @@ -0,0 +1,203 @@ +#ifndef SCF_RISC_REG_H +#define SCF_RISC_REG_H + +#include"scf_native.h" +#include"scf_risc_util.h" + +#define RISC_COLOR(type, id, mask) ((type) << 24 | (id) << 16 | (mask)) +#define RISC_COLOR_TYPE(c) ((c) >> 24) +#define RISC_COLOR_ID(c) (((c) >> 16) & 0xff) +#define RISC_COLOR_MASK(c) ((c) & 0xffff) +#define RISC_COLOR_CONFLICT(c0, c1) ( (c0) >> 16 == (c1) >> 16 && (c0) & (c1) & 0xffff ) + +#define RISC_COLOR_BYTES(c) \ + ({ \ + int n = 0;\ + intptr_t minor = (c) & 0xffff; \ + while (minor) { \ + minor &= minor - 1; \ + n++;\ + } \ + n;\ + }) + +#define RISC_SELECT_REG_CHECK(pr, dn, c, f, load_flag) \ + do {\ + int ret = risc_select_reg(pr, dn, c, f, load_flag); \ + if (ret < 0) { \ + scf_loge("\n"); \ + return ret; \ + } \ + assert(dn->color > 0); \ + } while (0) + +static uint32_t risc_abi_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, + SCF_RISC_REG_X4, + SCF_RISC_REG_X5, + SCF_RISC_REG_X6, + SCF_RISC_REG_X7, +}; + +static uint32_t risc_abi_float_regs[] = +{ + SCF_RISC_REG_D0, + SCF_RISC_REG_D1, + SCF_RISC_REG_D2, + SCF_RISC_REG_D3, + SCF_RISC_REG_D4, + SCF_RISC_REG_D5, + SCF_RISC_REG_D6, + SCF_RISC_REG_D7, +}; +#define RISC_ABI_NB (sizeof(risc_abi_regs) / sizeof(risc_abi_regs[0])) + +static uint32_t risc_abi_ret_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, +}; +#define RISC_ABI_RET_NB (sizeof(risc_abi_ret_regs) / sizeof(risc_abi_ret_regs[0])) + +static uint32_t risc_abi_caller_saves[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, + SCF_RISC_REG_X4, + SCF_RISC_REG_X5, + SCF_RISC_REG_X6, + SCF_RISC_REG_X7, + + SCF_RISC_REG_X9, + SCF_RISC_REG_X10, + SCF_RISC_REG_X11, + SCF_RISC_REG_X12, + SCF_RISC_REG_X13, + SCF_RISC_REG_X14, + SCF_RISC_REG_X15, +}; +#define RISC_ABI_CALLER_SAVES_NB (sizeof(risc_abi_caller_saves) / sizeof(risc_abi_caller_saves[0])) + +static uint32_t risc_abi_callee_saves[] = +{ + SCF_RISC_REG_X19, + SCF_RISC_REG_X20, + SCF_RISC_REG_X21, + SCF_RISC_REG_X22, + SCF_RISC_REG_X23, + SCF_RISC_REG_X24, + SCF_RISC_REG_X25, + SCF_RISC_REG_X26, + SCF_RISC_REG_X27, + SCF_RISC_REG_X28, + SCF_RISC_REG_X29, + SCF_RISC_REG_X30, +}; +#define RISC_ABI_CALLEE_SAVES_NB (sizeof(risc_abi_callee_saves) / sizeof(risc_abi_callee_saves[0])) + +static inline int risc_variable_size(scf_variable_t* v) +{ + if (v->nb_dimentions > 0) + return 8; + + if (v->type >= SCF_STRUCT && 0 == v->nb_pointers) + return 8; + + return v->size < 4 ? 4 : v->size; +} + +typedef int (*risc_sib_fill_pt)(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_3ac_code_t* c, scf_function_t* f); + +int risc_registers_init(); +int risc_registers_reset(); +void risc_registers_clear(); +scf_vector_t* risc_register_colors(); + +scf_register_t* risc_find_register(const char* name); + +scf_register_t* risc_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes); + +scf_register_t* risc_find_register_color(intptr_t color); + +scf_register_t* risc_find_register_color_bytes(intptr_t color, int bytes); + +scf_register_t* risc_find_abi_register(int index, int bytes); + +scf_register_t* risc_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float); + +int risc_reg_cached_vars(scf_register_t* r); + +int risc_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); + +int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); + +int risc_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated); + +int risc_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs); + +int risc_save_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); + +int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); +int risc_load_reg (scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); +int risc_reg_used (scf_register_t* r, scf_dag_node_t* dn); + +int risc_overflow_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); +int risc_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); + +int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag); + +int risc_select_free_reg(scf_register_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float); + +int risc_dereference_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f); + +int risc_pointer_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f); + +int risc_array_index_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_dag_node_t* scale, scf_3ac_code_t* c, scf_function_t* f); + +void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c); + + +static inline int risc_inst_data_is_reg(scf_inst_data_t* id) +{ + scf_register_t* fp = (scf_register_t*)risc_find_register("fp"); + scf_register_t* sp = (scf_register_t*)risc_find_register("sp"); + + if (!id->flag && id->base && id->base != sp && id->base != fp && 0 == id->imm_size) + return 1; + return 0; +} + +static inline int risc_inst_data_is_local(scf_inst_data_t* id) +{ + scf_register_t* fp = (scf_register_t*)risc_find_register("fp"); + scf_register_t* sp = (scf_register_t*)risc_find_register("sp"); + + if (id->flag && (id->base == fp || id->base == sp)) + return 1; + return 0; +} + +static inline int risc_inst_data_is_global(scf_inst_data_t* id) +{ + if (id->flag && !id->base) + return 1; + return 0; +} + +static inline int risc_inst_data_is_const(scf_inst_data_t* id) +{ + if (!id->flag && id->imm_size > 0) + return 1; + return 0; +} + +#endif + diff --git a/native/risc/scf_risc_util.h b/native/risc/scf_risc_util.h new file mode 100644 index 0000000..bed67ce --- /dev/null +++ b/native/risc/scf_risc_util.h @@ -0,0 +1,244 @@ +#ifndef SCF_RISC_UTIL_H +#define SCF_RISC_UTIL_H + +#include"scf_def.h" + +enum scf_risc_OpCode_types { + SCF_RISC_MOV = 0, + + SCF_RISC_MOVSX, + SCF_RISC_MOVZX, + + SCF_RISC_MOVS, + SCF_RISC_STOS, + + SCF_RISC_LEA, + + SCF_RISC_PUSH, + SCF_RISC_POP, + + SCF_RISC_INC, + SCF_RISC_DEC, + + // 10 + SCF_RISC_XOR, + SCF_RISC_AND, + SCF_RISC_OR, + SCF_RISC_NOT, + + SCF_RISC_NEG, + + // 15 + SCF_RISC_CALL, + SCF_RISC_RET, + + SCF_RISC_ADD, + SCF_RISC_SUB, + + SCF_RISC_MUL, + SCF_RISC_DIV, + + // 21 + SCF_RISC_IMUL, + SCF_RISC_IDIV, + + // sign-extend ax to dx:ax + SCF_RISC_CBW, + SCF_RISC_CWD = SCF_RISC_CBW, + SCF_RISC_CDQ = SCF_RISC_CBW, + SCF_RISC_CQO = SCF_RISC_CBW, + + // 24 + SCF_RISC_SAR, + SCF_RISC_SHR, + SCF_RISC_SHL, + + SCF_RISC_CMP, + SCF_RISC_TEST, + + SCF_RISC_SETZ, + SCF_RISC_SETNZ, + + // 31 + SCF_RISC_SETG, + SCF_RISC_SETGE, + + SCF_RISC_SETL, + SCF_RISC_SETLE, + + SCF_RISC_ADDSS, + SCF_RISC_ADDSD, + + SCF_RISC_SUBSS, + SCF_RISC_SUBSD, + + SCF_RISC_MULSS, + SCF_RISC_MULSD, + + // 41 + SCF_RISC_DIVSS, + SCF_RISC_DIVSD, + + SCF_RISC_MOVSS, + SCF_RISC_MOVSD, + + SCF_RISC_UCOMISS, + SCF_RISC_UCOMISD, + + // 47 + SCF_RISC_CVTSI2SD, + SCF_RISC_CVTSI2SS, + + SCF_RISC_CVTSS2SD, + SCF_RISC_CVTSD2SS, + + SCF_RISC_CVTTSD2SI, + SCF_RISC_CVTTSS2SI, + + SCF_RISC_PXOR, + + SCF_RISC_JZ, + SCF_RISC_JNZ, + + SCF_RISC_JG, + SCF_RISC_JGE, + + SCF_RISC_JL, + SCF_RISC_JLE, + + SCF_RISC_JA, + SCF_RISC_JAE, + + SCF_RISC_JB, + SCF_RISC_JBE, + + SCF_RISC_JMP, + + SCF_RISC_NB +}; + +enum scf_risc_REGs { + SCF_RISC_REG_W0 = 0, + SCF_RISC_REG_X0 = 0, + SCF_RISC_REG_S0 = 0, + SCF_RISC_REG_D0 = 0, + + SCF_RISC_REG_W1 = 1, + SCF_RISC_REG_X1 = 1, + SCF_RISC_REG_S1 = 1, + SCF_RISC_REG_D1 = 1, + + SCF_RISC_REG_W2 = 2, + SCF_RISC_REG_X2 = 2, + SCF_RISC_REG_S2 = 2, + SCF_RISC_REG_D2 = 2, + + SCF_RISC_REG_W3 = 3, + SCF_RISC_REG_X3 = 3, + SCF_RISC_REG_S3 = 3, + SCF_RISC_REG_D3 = 3, + + SCF_RISC_REG_W4 = 4, + SCF_RISC_REG_X4 = 4, + SCF_RISC_REG_S4 = 4, + SCF_RISC_REG_D4 = 4, + + SCF_RISC_REG_W5 = 5, + SCF_RISC_REG_X5 = 5, + SCF_RISC_REG_S5 = 5, + SCF_RISC_REG_D5 = 5, + + SCF_RISC_REG_W6 = 6, + SCF_RISC_REG_X6 = 6, + SCF_RISC_REG_S6 = 6, + SCF_RISC_REG_D6 = 6, + + SCF_RISC_REG_W7 = 7, + SCF_RISC_REG_X7 = 7, + SCF_RISC_REG_S7 = 7, + SCF_RISC_REG_D7 = 7, + + SCF_RISC_REG_W8 = 8, + SCF_RISC_REG_X8 = 8, + + SCF_RISC_REG_W9 = 9, + SCF_RISC_REG_X9 = 9, + + SCF_RISC_REG_W10 = 10, + SCF_RISC_REG_X10 = 10, + + SCF_RISC_REG_W11 = 11, + SCF_RISC_REG_X11 = 11, + + SCF_RISC_REG_W12 = 12, + SCF_RISC_REG_X12 = 12, + + SCF_RISC_REG_W13 = 13, + SCF_RISC_REG_X13 = 13, + + SCF_RISC_REG_W14 = 14, + SCF_RISC_REG_X14 = 14, + + SCF_RISC_REG_W15 = 15, + SCF_RISC_REG_X15 = 15, + + SCF_RISC_REG_W16 = 16, + SCF_RISC_REG_X16 = 16, + + SCF_RISC_REG_W17 = 17, + SCF_RISC_REG_X17 = 17, + + SCF_RISC_REG_W18 = 18, + SCF_RISC_REG_X18 = 18, + + SCF_RISC_REG_W19 = 19, + SCF_RISC_REG_X19 = 19, + + SCF_RISC_REG_W20 = 20, + SCF_RISC_REG_X20 = 20, + + SCF_RISC_REG_W21 = 21, + SCF_RISC_REG_X21 = 21, + + SCF_RISC_REG_W22 = 22, + SCF_RISC_REG_X22 = 22, + + SCF_RISC_REG_W23 = 23, + SCF_RISC_REG_X23 = 23, + + SCF_RISC_REG_W24 = 24, + SCF_RISC_REG_X24 = 24, + + SCF_RISC_REG_W25 = 25, + SCF_RISC_REG_X25 = 25, + + SCF_RISC_REG_W26 = 26, + SCF_RISC_REG_X26 = 26, + + SCF_RISC_REG_W27 = 27, + SCF_RISC_REG_X27 = 27, + + SCF_RISC_REG_W28 = 28, + SCF_RISC_REG_X28 = 28, + + SCF_RISC_REG_X29 = 29, + SCF_RISC_REG_FP = 29, + + SCF_RISC_REG_X30 = 30, + SCF_RISC_REG_LR = 30, + + SCF_RISC_REG_SP = 31, +}; + +enum scf_risc_EG_types { + SCF_RISC_G = 0, + SCF_RISC_I = 1, + SCF_RISC_G2E = 2, + SCF_RISC_E2G = 3, + SCF_RISC_I2E = 4, + SCF_RISC_I2G = 5, + SCF_RISC_E = 6, +}; + +#endif + diff --git a/native/scf_native.c b/native/scf_native.c index 5126a22..b0eac6c 100644 --- a/native/scf_native.c +++ b/native/scf_native.c @@ -1,15 +1,7 @@ #include"scf_native.h" extern scf_native_ops_t native_ops_x64; -extern scf_native_ops_t native_ops_arm64; - -scf_native_ops_t* native_ops_array[] = -{ - &native_ops_x64, - &native_ops_arm64, - - NULL, -}; +extern scf_native_ops_t native_ops_risc; void scf_instruction_print(scf_instruction_t* inst) { @@ -56,20 +48,12 @@ int scf_native_open(scf_native_t** pctx, const char* name) scf_native_t* ctx = calloc(1, sizeof(scf_native_t)); assert(ctx); - int i; - for (i = 0; native_ops_array[i]; i++) { - if (!strcmp(native_ops_array[i]->name, name)) { - ctx->ops = native_ops_array[i]; - break; - } - } - - if (!ctx->ops) { - printf("%s(),%d, error: \n", __func__, __LINE__); - return -1; - } + if (!strcmp(name, "x64")) + ctx->ops = &native_ops_x64; + else + ctx->ops = &native_ops_risc; - if (ctx->ops->open && ctx->ops->open(ctx) == 0) { + if (ctx->ops->open && ctx->ops->open(ctx, name) == 0) { *pctx = ctx; return 0; } diff --git a/native/scf_native.h b/native/scf_native.h index 665ef0d..9bc8648 100644 --- a/native/scf_native.h +++ b/native/scf_native.h @@ -4,14 +4,19 @@ #include"scf_3ac.h" #include"scf_parse.h" -typedef struct scf_register_s scf_register_t; -typedef struct scf_OpCode_s scf_OpCode_t; -typedef struct scf_native_ops_s scf_native_ops_t; +typedef struct scf_native_ops_s scf_native_ops_t; struct scf_register_s { uint32_t id; int bytes; char* name; + + intptr_t color; + + scf_vector_t* dag_nodes; + + uint32_t updated; + uint32_t used; }; struct scf_OpCode_s { @@ -19,6 +24,15 @@ struct scf_OpCode_s { char* name; }; +typedef struct { + scf_register_t* base; + scf_register_t* index; + + int32_t scale; + int32_t disp; + int32_t size; +} scf_sib_t; + typedef struct { scf_register_t* base; @@ -63,17 +77,106 @@ typedef struct { typedef struct { scf_native_ops_t* ops; + + scf_inst_ops_t* iops; + void* priv; } scf_native_t; -struct scf_native_ops_s { - const char* name; +struct scf_native_ops_s +{ + const char* name; - int (*open )(scf_native_t* ctx); - int (*close)(scf_native_t* ctx); + int (*open )(scf_native_t* ctx, const char* arch); + int (*close)(scf_native_t* ctx); - int (*select_inst)(scf_native_t* ctx, scf_function_t* f); + int (*select_inst)(scf_native_t* ctx, scf_function_t* f); +}; + +struct scf_inst_ops_s +{ + const char* name; + + scf_instruction_t* (*BL )(scf_3ac_code_t* c); + scf_instruction_t* (*BLR )(scf_3ac_code_t* c, scf_register_t* r); + scf_instruction_t* (*PUSH )(scf_3ac_code_t* c, scf_register_t* r); + scf_instruction_t* (*POP )(scf_3ac_code_t* c, scf_register_t* r); + scf_instruction_t* (*TEQ )(scf_3ac_code_t* c, scf_register_t* rs); + scf_instruction_t* (*NEG )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*MOVZX )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size); + scf_instruction_t* (*MOVSX )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size); + scf_instruction_t* (*MVN )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*MOV_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*MOV_SP )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*ADD_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*ADD_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); + scf_instruction_t* (*SUB_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*SUB_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); + scf_instruction_t* (*CMP_G)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*CMP_IMM)(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm); + scf_instruction_t* (*AND_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*OR_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + + scf_instruction_t* (*MUL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*DIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*SDIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*MSUB )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra); + + scf_instruction_t* (*SHL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*SHR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*ASR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + + scf_instruction_t* (*CVTSS2SD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTSD2SS)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTF2SI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTF2UI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTSI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTUI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*FCMP)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FADD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FSUB)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FMUL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FDIV)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FMOV_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*JA )(scf_3ac_code_t* c); + scf_instruction_t* (*JB )(scf_3ac_code_t* c); + scf_instruction_t* (*JZ )(scf_3ac_code_t* c); + scf_instruction_t* (*JNZ)(scf_3ac_code_t* c); + scf_instruction_t* (*JGT)(scf_3ac_code_t* c); + scf_instruction_t* (*JGE)(scf_3ac_code_t* c); + scf_instruction_t* (*JLT)(scf_3ac_code_t* c); + scf_instruction_t* (*JLE)(scf_3ac_code_t* c); + scf_instruction_t* (*JMP)(scf_3ac_code_t* c); + scf_instruction_t* (*JAE)(scf_3ac_code_t* c); + scf_instruction_t* (*JBE)(scf_3ac_code_t* c); + scf_instruction_t* (*RET)(scf_3ac_code_t* c); + + scf_instruction_t* (*SETZ )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETNZ)(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETGT)(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETGE)(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETLT)(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETLE)(scf_3ac_code_t* c, scf_register_t* rd); + + int (*I2G )(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes); + int (*M2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); + int (*M2GF )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); + int (*G2M )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs); + int (*G2P )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size); + int (*P2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size); + int (*ISTR2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); + int (*SIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + int (*G2SIB )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + int (*ADR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); + int (*ADRP2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset); + int (*ADRSIB2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + + void (*set_jmp_offset)(scf_instruction_t* inst, int32_t bytes); }; static inline int scf_inst_data_same(scf_inst_data_t* id0, scf_inst_data_t* id1) diff --git a/native/x64/scf_x64.c b/native/x64/scf_x64.c index bf30b29..bc211b9 100644 --- a/native/x64/scf_x64.c +++ b/native/x64/scf_x64.c @@ -5,7 +5,7 @@ extern scf_native_ops_t native_ops_x64; -int scf_x64_open(scf_native_t* ctx) +int scf_x64_open(scf_native_t* ctx, const char* arch) { scf_x64_context_t* x64 = calloc(1, sizeof(scf_x64_context_t)); if (!x64) diff --git a/native/x64/scf_x64.h b/native/x64/scf_x64.h index d6d18ac..da18199 100644 --- a/native/x64/scf_x64.h +++ b/native/x64/scf_x64.h @@ -74,8 +74,8 @@ x64_inst_handler_t* scf_x64_find_inst_handler(const int op_type); int x64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_x64_t* reg); int _x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_x64_t* reg, scf_x64_OpCode_t* OpCode); -int scf_x64_open(scf_native_t* ctx); -int scf_x64_close(scf_native_t* ctx); +int scf_x64_open (scf_native_t* ctx, const char* arch); +int scf_x64_close (scf_native_t* ctx); int scf_x64_select(scf_native_t* ctx); int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f); diff --git a/parse/Makefile b/parse/Makefile index 3bc6b71..0cb8dce 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -29,14 +29,14 @@ CFILES += ../native/x64/scf_x64_opcode.c CFILES += ../native/x64/scf_x64_peephole.c CFILES += ../native/x64/scf_x64_bb_color.c -CFILES += ../native/arm64/scf_arm64_bb_color.c -CFILES += ../native/arm64/scf_arm64.c -CFILES += ../native/arm64/scf_arm64_graph.c -CFILES += ../native/arm64/scf_arm64_inst.c -CFILES += ../native/arm64/scf_arm64_opcode.c -CFILES += ../native/arm64/scf_arm64_rcg.c -CFILES += ../native/arm64/scf_arm64_reg.c -CFILES += ../native/arm64/scf_arm64_util.c +CFILES += ../native/risc/scf_risc_bb_color.c +CFILES += ../native/risc/scf_risc.c +CFILES += ../native/risc/scf_risc_graph.c +CFILES += ../native/risc/scf_risc_inst.c +CFILES += ../native/risc/scf_risc_opcode.c +CFILES += ../native/risc/scf_risc_rcg.c +CFILES += ../native/risc/scf_risc_reg.c +CFILES += ../native/risc/scf_arm64.c CFILES += ../elf/scf_elf.c CFILES += ../elf/scf_elf_link.c @@ -154,7 +154,7 @@ CFLAGS += -I../parse CFLAGS += -I../elf CFLAGS += -I../native CFLAGS += -I../native/x64 -CFLAGS += -I../native/arm64 +CFLAGS += -I../native/risc LDFLAGS += -- 2.25.1