From 7c038a99a8b16343d3a32ee291307a8acd3be36b Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Sat, 25 Feb 2023 13:03:58 +0800 Subject: [PATCH] support arm64: 'qsort' test ok in ../examples/qsort.c --- core/scf_3ac.c | 6 + core/scf_optimizer_generate_loads_saves.c | 8 +- native/arm64/scf_arm64.c | 19 +- native/arm64/scf_arm64.h | 7 +- native/arm64/scf_arm64_bb_color.c | 70 ++++++- native/arm64/scf_arm64_inst.c | 109 ++++------- native/arm64/scf_arm64_reg.c | 153 ++++++++------- native/arm64/scf_arm64_util.c | 228 +++++++++++++++++++++- parse/scf_parse2.c | 2 +- 9 files changed, 432 insertions(+), 170 deletions(-) diff --git a/core/scf_3ac.c b/core/scf_3ac.c index d9f0e4a..e62d8e0 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -1310,6 +1310,9 @@ static int _3ac_find_basic_block_start(scf_list_t* h) if (scf_type_is_setcc(c2->op->type)) continue; + if (SCF_OP_3AC_TEQ == c2->op->type) + continue; + if (scf_type_is_jmp(c2->op->type)) c->basic_block_start = 1; break; @@ -1442,6 +1445,9 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f) if (scf_type_is_setcc(c2->op->type)) continue; + if (SCF_OP_3AC_TEQ == c2->op->type) + continue; + if (scf_type_is_jmp(c2->op->type)) { bb->cmp_flag = 1; diff --git a/core/scf_optimizer_generate_loads_saves.c b/core/scf_optimizer_generate_loads_saves.c index e55c50c..ce60ac9 100644 --- a/core/scf_optimizer_generate_loads_saves.c +++ b/core/scf_optimizer_generate_loads_saves.c @@ -81,8 +81,14 @@ static int _optimize_generate_loads_saves(scf_ast_t* ast, scf_function_t* f, scf if (bb->loop_flag) SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->save_list_head); - else + else { SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->code_list_head); + + if (bb->cmp_flag) { + scf_list_del(&save->list); + scf_list_add_front(&bb->code_list_head, &save->list); + } + } } } diff --git a/native/arm64/scf_arm64.c b/native/arm64/scf_arm64.c index e928850..0b28292 100644 --- a/native/arm64/scf_arm64.c +++ b/native/arm64/scf_arm64.c @@ -612,13 +612,6 @@ 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); - if (bb->cmp_flag - && (SCF_OP_3AC_CMP == c->op->type - || SCF_OP_3AC_TEQ == c->op->type)) { - assert(!cmp); - cmp = c; - } - arm64_inst_handler_t* h = scf_arm64_find_inst_handler(c->op->type); if (!h) { scf_loge("3ac operator '%s' not supported\n", c->op->name); @@ -639,14 +632,6 @@ static int _arm64_make_insts_for_list(scf_native_t* ctx, scf_basic_block_t* bb, _arm64_inst_printf(c); } - if (bb->cmp_flag) { - - assert(cmp); - - scf_list_del(&cmp->list); - scf_list_add_tail(&bb->code_list_head, &cmp->list); - } - return bb_offset; } @@ -676,7 +661,7 @@ static void _arm64_set_offset_for_jmps(scf_native_t* ctx, scf_function_t* f) bytes += bb->code_bytes; } } else { - for (l = &cur_bb->list; l != &dst_bb->list; l = scf_list_prev(l)) { + for (l = &dst_bb->list; l != &cur_bb->list; l = scf_list_next(l)) { bb = scf_list_data(l, scf_basic_block_t, list); @@ -1082,8 +1067,6 @@ int _scf_arm64_select_inst(scf_native_t* ctx) 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); if (ret < 0) return ret; diff --git a/native/arm64/scf_arm64.h b/native/arm64/scf_arm64.h index 2790e11..ec6eb1f 100644 --- a/native/arm64/scf_arm64.h +++ b/native/arm64/scf_arm64.h @@ -112,11 +112,8 @@ scf_instruction_t* arm64_make_inst_I2M(scf_rela_t** prela, scf_arm64_OpCode_t* O 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_P2G(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_dst, scf_register_arm64_t* r_base, int32_t offset); 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_SIB2G(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_dst, scf_register_arm64_t* r_base, scf_register_arm64_t* r_index, int32_t scale, int32_t disp); -scf_instruction_t* arm64_make_inst_G2SIB(scf_arm64_OpCode_t* OpCode, scf_register_arm64_t* r_base, scf_register_arm64_t* r_index, int32_t scale, int32_t disp, scf_register_arm64_t* r_src); 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); @@ -172,7 +169,11 @@ int arm64_make_inst_I2G (scf_3ac_code_t* c, scf_register_arm64_t* rd, uint64_t 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_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); #endif diff --git a/native/arm64/scf_arm64_bb_color.c b/native/arm64/scf_arm64_bb_color.c index c9d1913..e160a54 100644 --- a/native/arm64/scf_arm64_bb_color.c +++ b/native/arm64/scf_arm64_bb_color.c @@ -167,6 +167,8 @@ int arm64_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ int arm64_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; @@ -174,10 +176,76 @@ int arm64_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, if (v->w) scf_logd("bb: %d, v: %d/%s, bp_offset: -%#x\n", bb->index, v->w->line, v->w->text->data, -v->bp_offset); + uint32_t opcode; + uint32_t mov; + uint32_t r0; + uint32_t r1; + l = scf_list_tail(&bb->code_list_head); c = scf_list_data(l, scf_3ac_code_t, list); - return arm64_bb_load_dn(color, dn, c, bb, f); + if (bb->cmp_flag) { + + cmp = c->instructions->data[c->instructions->size - 1]; + + c->instructions->size--; + + opcode = cmp->code[0]; + opcode |= cmp->code[1] << 8; + opcode |= cmp->code[2] << 16; + opcode |= cmp->code[3] << 24; + + 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); + + opcode &= ~(0x1f << 5); + opcode |= (0x10 << 5); + break; + + case 0x6b: // register + r0 = (opcode >> 5) & 0x1f; + r1 = (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); + + 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); + + opcode &= ~(0x1f << 5); + opcode |= (0x10 << 5); + + opcode &= ~(0x1f << 16); + opcode |= (0x11 << 16); + break; + + default: + scf_loge("%#x\n", opcode); + return -EINVAL; + break; + }; + + cmp->code[0] = 0xff & opcode; + cmp->code[1] = 0xff & (opcode >> 8); + cmp->code[2] = 0xff & (opcode >> 16); + cmp->code[3] = 0xff & (opcode >> 24); + } + + int ret = arm64_bb_load_dn(color, dn, c, bb, f); + if (ret < 0) + return ret; + + if (cmp) + ARM64_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) diff --git a/native/arm64/scf_arm64_inst.c b/native/arm64/scf_arm64_inst.c index cc88022..a843b89 100644 --- a/native/arm64/scf_arm64_inst.c +++ b/native/arm64/scf_arm64_inst.c @@ -459,16 +459,11 @@ static int _arm64_call_update_dsts(scf_3ac_code_t* c, scf_function_t* f, scf_reg dn->color = rs->color; dn->loaded = 1; - } else { -#if 0 - scf_rela_t* rela = NULL; - inst = arm64_make_inst_G2M(&rela, mov, dn->var, NULL, rs); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL); -#endif - scf_loge("\n"); - return -EINVAL; + } else { + int ret = arm64_make_inst_G2M(c, f, rs, NULL, dn->var); + if (ret < 0) + return ret; } } return nb_updated; @@ -960,7 +955,7 @@ static int _arm64_inst_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) return -1; } -static int _arm64_inst_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type) +static int _arm64_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) { if (!c->srcs || c->srcs->size != 4) return -EINVAL; @@ -991,22 +986,21 @@ static int _arm64_inst_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, 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_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* rs = NULL; arm64_sib_t sib = {0}; - scf_arm64_OpCode_t* OpCode; - scf_instruction_t* inst; + 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; -#if 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"); @@ -1014,40 +1008,22 @@ static int _arm64_inst_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, } if (vb->nb_dimentions > 1) { - OpCode = arm64_find_OpCode(SCF_ARM64_LEA, 8, 8, SCF_ARM64_E2G); + } else { if (is_float) { - OpCode_type = arm64_float_OpCode_type(OpCode_type, vs->type); - if (0 == src->dag_node->color) { src->dag_node->color = -1; vs->global_flag = 1; } - } else if (0 == src->dag_node->color) { - OpCode = arm64_find_OpCode(OpCode_type, size, size, SCF_ARM64_I2E); - - if (OpCode) { - if (sib.index) - inst = arm64_make_inst_I2SIB(OpCode, sib.base, sib.index, sib.scale, sib.disp, (uint8_t*)&vs->data, size); - else - inst = arm64_make_inst_I2P(OpCode, sib.base, sib.disp, (uint8_t*)&vs->data, size); - - ARM64_INST_ADD_CHECK(c->instructions, inst); - return 0; - } + scf_loge("\n"); + return -EINVAL; - if (0 == src->dag_node->color) - src->dag_node->color = -1; } - OpCode = arm64_find_OpCode(OpCode_type, size, size, SCF_ARM64_G2E); - } - - if (!OpCode) { - scf_loge("\n"); - return -EINVAL; + if (0 == src->dag_node->color) + src->dag_node->color = -1; } ret = arm64_select_reg(&rs, src->dag_node, c, f, 1); @@ -1058,16 +1034,17 @@ static int _arm64_inst_assign_array_index(scf_native_t* ctx, scf_3ac_code_t* c, rs = arm64_find_register_color_bytes(rs->color, size); - if (sib.index) { - inst = arm64_make_inst_G2SIB(OpCode, sib.base, sib.index, sib.scale, sib.disp, rs); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } else { - inst = arm64_make_inst_G2P(OpCode, sib.base, sib.disp, rs); - ARM64_INST_ADD_CHECK(c->instructions, inst); + 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) { + scf_loge("\n"); + return ret; } + return 0; -#endif - return -1; } static int _arm64_inst_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int lea_flag) @@ -1109,7 +1086,6 @@ static int _arm64_inst_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int lea scf_register_arm64_t* rd = NULL; arm64_sib_t sib = {0}; - scf_arm64_OpCode_t* OpCode; scf_instruction_t* inst; int ret = arm64_select_reg(&rd, dst->dag_node, c, f, 0); @@ -1117,7 +1093,7 @@ static int _arm64_inst_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int lea scf_loge("\n"); return ret; } -#if 0 + ret = arm64_array_index_reg(&sib, base->dag_node, index->dag_node, scale->dag_node, c, f); if (ret < 0) { scf_loge("\n"); @@ -1125,34 +1101,26 @@ static int _arm64_inst_array_index(scf_native_t* ctx, scf_3ac_code_t* c, int lea } if (vb->nb_dimentions > 1 || lea_flag) { - OpCode = arm64_find_OpCode(SCF_ARM64_LEA, rd->bytes, rd->bytes, SCF_ARM64_E2G); } else { int is_float = scf_variable_float(vd); + if (is_float) { - if (SCF_VAR_FLOAT == vd->type) - OpCode = arm64_find_OpCode(SCF_ARM64_MOVSS, rd->bytes, rd->bytes, SCF_ARM64_E2G); - else if (SCF_VAR_DOUBLE == vd->type) - OpCode = arm64_find_OpCode(SCF_ARM64_MOVSD, rd->bytes, rd->bytes, SCF_ARM64_E2G); - } else - OpCode = arm64_find_OpCode(SCF_ARM64_MOV, rd->bytes, rd->bytes, SCF_ARM64_E2G); + scf_loge("\n"); + return -EINVAL; + } } - if (!OpCode) { - scf_loge("\n"); - return -EINVAL; - } + 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 (sib.index) { - inst = arm64_make_inst_SIB2G(OpCode, rd, sib.base, sib.index, sib.scale, sib.disp); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } else { - inst = arm64_make_inst_P2G(OpCode, rd, sib.base, sib.disp); - ARM64_INST_ADD_CHECK(c->instructions, inst); + if (ret < 0) { + scf_loge("\n"); + return ret; } return 0; -#endif - return -1; } static int _arm64_inst_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) @@ -2444,10 +2412,7 @@ static int _arm64_inst_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* { return -1; } -static int _arm64_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return -1; -} + static int _arm64_inst_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c) { return -1; diff --git a/native/arm64/scf_arm64_reg.c b/native/arm64/scf_arm64_reg.c index a5a39d5..4c66269 100644 --- a/native/arm64/scf_arm64_reg.c +++ b/native/arm64/scf_arm64_reg.c @@ -897,30 +897,12 @@ static int _arm64_load_reg_const(scf_register_arm64_t* r, scf_dag_node_t* dn, sc v->local_flag = 0; v->tmp_flag = 0; - scf_rela_t* rela = NULL; -#if 0 - lea = arm64_find_OpCode(SCF_ARM64_LEA, size, size, SCF_ARM64_E2G); - inst = arm64_make_inst_M2G(&rela, lea, r, NULL, v); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, v->func_ptr); -#endif - scf_loge("\n"); - return -EINVAL; + return arm64_make_inst_ADR2G(c, f, r, v); } else if (v->nb_dimentions > 0) { assert(v->const_literal_flag); - scf_rela_t* rela = NULL; - -#if 0 - lea = arm64_find_OpCode(SCF_ARM64_LEA, size, size, SCF_ARM64_E2G); - inst = arm64_make_inst_M2G(&rela, lea, r, NULL, v); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); -#endif - scf_loge("\n"); - return -EINVAL; - + return arm64_make_inst_ADR2G(c, f, r, v); } return arm64_make_inst_I2G(c, r, v->data.u64, size); @@ -1175,11 +1157,13 @@ int arm64_pointer_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* me 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_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* 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; @@ -1191,8 +1175,9 @@ int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t int ret; int i; - int32_t disp = 0; -#if 0 + 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); @@ -1217,10 +1202,17 @@ int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t return ret; } - lea = arm64_find_OpCode(SCF_ARM64_LEA, 8, 8, SCF_ARM64_E2G); - inst = arm64_make_inst_M2G(&rela, lea, rb, NULL, vb); + 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); @@ -1261,24 +1253,12 @@ int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t if (ri->bytes < ri2->bytes) { if (scf_variable_signed(index->var)) { - mov = arm64_find_OpCode(SCF_ARM64_MOVSX, ri->bytes, ri2->bytes, SCF_ARM64_E2G); - } else if (ri->bytes <= 2) { - mov = arm64_find_OpCode(SCF_ARM64_MOVZX, ri->bytes, ri2->bytes, SCF_ARM64_E2G); - - } else { - assert(4 == ri->bytes); - - xor = arm64_find_OpCode(SCF_ARM64_XOR, 8, 8, SCF_ARM64_G2E); - inst = arm64_make_inst_G2E(xor, ri2, ri2); + 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); - - mov = arm64_find_OpCode(SCF_ARM64_MOV, 4, 4, SCF_ARM64_E2G); } - inst = arm64_make_inst_E2G(mov, ri2, ri); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ri = ri2; } @@ -1289,63 +1269,94 @@ int arm64_array_index_reg(arm64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t assert(8 == scale->var->size); - scf_register_arm64_t* rs = NULL; - ret = arm64_select_reg(&rs, scale, c, f, 0); if (ret < 0) { scf_loge("\n"); return ret; } - mov = arm64_find_OpCode(SCF_ARM64_MOV, 8, 8, SCF_ARM64_G2E); - inst = arm64_make_inst_G2E(mov, rs, ri2); + opcode = (0xd2 << 24) | (0x1 << 23) | ((s & 0xffff) << 5) | rs->id; + inst = arm64_make_inst(c, opcode); ARM64_INST_ADD_CHECK(c->instructions, inst); - shl = arm64_find_OpCode(SCF_ARM64_SHL, 1, 8, SCF_ARM64_I2E); - add = arm64_find_OpCode(SCF_ARM64_ADD, 8, 8, SCF_ARM64_G2E); + 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); - int32_t count = 0; - int i; - for (i = 30; i >= 0; i--) { - if (0 == (s & 1 << i)) - continue; - scf_logw("s: %d, i: %d\n", s, i); + 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); - if (0 == count) { - scf_logw("s: %d, i: %d\n", s, i); - count = i; - continue; + 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; } - count -= i; + if (disp > 0 && disp <= 0xfff) + opcode = (0x91 << 24) | (disp << 10) | (rb->id << 5) | rs->id; - inst = arm64_make_inst_I2E(shl, rs, (uint8_t*)&count, 1); - ARM64_INST_ADD_CHECK(c->instructions, inst); + 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_G2E(add, rs, ri2); + inst = arm64_make_inst(c, opcode); ARM64_INST_ADD_CHECK(c->instructions, inst); - count = i; - } + } 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); + 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); + } - if (count > 0) { - inst = arm64_make_inst_I2E(shl, rs, (uint8_t*)&count, 1); + 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; } - ri = rs; - s = 1; + rb = rs; } sib->base = rb; sib->index = ri; sib->scale = s; - sib->disp = disp; + sib->disp = 0; return 0; -#endif - return -1; } void arm64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c) diff --git a/native/arm64/scf_arm64_util.c b/native/arm64/scf_arm64_util.c index 68ccd4e..02bc241 100644 --- a/native/arm64/scf_arm64_util.c +++ b/native/arm64/scf_arm64_util.c @@ -59,6 +59,65 @@ int arm64_make_inst_I2G(scf_3ac_code_t* c, scf_register_arm64_t* rd, uint64_t im 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"); @@ -342,10 +401,8 @@ int arm64_make_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 uint32_t SIZE = 0; uint32_t S = 1; - if (!rb) { - // ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + if (!rb) return -EINVAL; - } if (1 == size) { S = 0; @@ -418,3 +475,168 @@ int arm64_make_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 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 { + opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | rd->id; + inst = arm64_make_inst(c, opcode); + ARM64_INST_ADD_CHECK(c->instructions, inst); + + if (offset >> 16) { + opcode = (0x72 << 24) | (0x1 << 23) | (((offset >> 16) & 0xffff) << 5) | rd->id; + inst = arm64_make_inst(c, opcode); + ARM64_INST_ADD_CHECK(c->instructions, inst); + } + + opcode = (SIZE << 30) | (0x38 << 24) | (0x1 << 22) | (0x1 << 21) | (rd->id << 16) | (0x3 << 13) | (S << 12) | (0x2 << 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) + 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; + + 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) + 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; + + inst = arm64_make_inst(c, opcode); + ARM64_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + diff --git a/parse/scf_parse2.c b/parse/scf_parse2.c index 8df2fda..b1db283 100644 --- a/parse/scf_parse2.c +++ b/parse/scf_parse2.c @@ -1473,7 +1473,7 @@ static int _fill_function_inst(scf_string_t* code, scf_function_t* f, int64_t of f->code_bytes += bb->code_bytes; } -#if 0 +#if 1 if (f->code_bytes & 0x7) { size_t n = 8 - (f->code_bytes & 0x7); -- 2.25.1