From b776f81080609cb85c31058c772c6f83ef039194 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 2 Mar 2023 14:47:54 +0800 Subject: [PATCH] support ARM64: float / double args for function call --- native/arm64/scf_arm64_inst.c | 67 ++++++++++++++---------------- native/arm64/scf_arm64_reg.c | 48 +++++++-------------- native/arm64/scf_arm64_reg.h | 8 ++++ native/arm64/scf_arm64_util.c | 78 +++++++++++++++-------------------- native/arm64/scf_arm64_util.h | 16 +++++++ native/x64/scf_x64_reg.c | 2 +- 6 files changed, 104 insertions(+), 115 deletions(-) diff --git a/native/arm64/scf_arm64_inst.c b/native/arm64/scf_arm64_inst.c index fb099b1..bd94ad7 100644 --- a/native/arm64/scf_arm64_inst.c +++ b/native/arm64/scf_arm64_inst.c @@ -77,45 +77,30 @@ static int _arm64_load_const_arg(scf_register_arm64_t* rabi, scf_dag_node_t* dn, v->local_flag = 0; v->tmp_flag = 0; - int ret = arm64_make_inst_M2G(c, f, rabi, NULL, v); - if (ret < 0) - return -EINVAL; + return arm64_make_inst_M2G(c, f, rabi, NULL, v); + } else { -#if 0 - scf_arm64_OpCode_t* xor; + uint32_t opcode; - xor = arm64_find_OpCode(SCF_ARM64_XOR, size, size, SCF_ARM64_G2E); - inst = arm64_make_inst_G2E(xor, rabi, rabi); + opcode = (0xcb << 24) | (rabi->id << 16) | (rabi->id << 5) | rabi->id; + inst = arm64_make_inst(c, opcode); ARM64_INST_ADD_CHECK(c->instructions, inst); -#endif + + scf_loge("\n"); return -EINVAL; } } else if (scf_variable_const_string(v)) { - int ret = arm64_make_inst_ISTR2G(c, f, rabi, v); - if (ret < 0) - return -EINVAL; + return arm64_make_inst_ISTR2G(c, f, rabi, v); } else if (v->nb_dimentions > 0) { assert(v->const_literal_flag); -#if 0 - scf_rela_t* rela = NULL; - - lea = arm64_find_OpCode(SCF_ARM64_LEA, size, size, SCF_ARM64_E2G); - inst = arm64_make_inst_M2G(&rela, lea, rabi, NULL, v); - ARM64_INST_ADD_CHECK(c->instructions, inst); - ARM64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); -#endif - return -EINVAL; - } else { - int ret = arm64_make_inst_I2G(c, rabi, v->data.u64, size); - if (ret < 0) - return -EINVAL; + return arm64_make_inst_ADR2G(c, f, rabi, v); } - return 0; + 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) @@ -125,7 +110,7 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) scf_arm64_OpCode_t* lea; scf_arm64_OpCode_t* mov; scf_arm64_OpCode_t* movx; - scf_instruction_t* inst; + scf_instruction_t* inst; uint32_t opcode; @@ -143,12 +128,9 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) int is_float = scf_variable_float(v); if (!rabi) { - if (!is_float) - rabi = arm64_find_register_type_id_bytes(0, SCF_ARM64_REG_X0, size); - else - rabi = arm64_find_register_type_id_bytes(1, SCF_ARM64_REG_X0, size); + rabi = arm64_find_register_type_id_bytes(is_float, SCF_ARM64_REG_X0, size); - ret = arm64_overflow_reg(rabi, c, f); + ret = arm64_overflow_reg(rabi, c, f); if (ret < 0) { scf_loge("\n"); return ret; @@ -189,7 +171,7 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) } } else { nb_floats++; -#if 0 + if (0 == src->dag_node->color) { src->dag_node->color = -1; v->global_flag = 1; @@ -203,9 +185,6 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) if (src->dag_node->color < 0) src->dag_node->color = rabi->color; -#endif - scf_loge("\n"); - return -EINVAL; } if (!rs) { @@ -235,13 +214,19 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) else return -EINVAL; - } else { + } 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); @@ -266,10 +251,18 @@ static int _arm64_inst_call_argv(scf_3ac_code_t* c, scf_function_t* f) if (!ARM64_COLOR_CONFLICT(rd->color, rs->color)) { rd = arm64_find_register_color_bytes(rd->color, rs->bytes); - opcode = (0xaa << 24) | (rs->id << 16) | (0x1f << 5) | rd->id; + 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; diff --git a/native/arm64/scf_arm64_reg.c b/native/arm64/scf_arm64_reg.c index a6a717f..dfc0755 100644 --- a/native/arm64/scf_arm64_reg.c +++ b/native/arm64/scf_arm64_reg.c @@ -601,12 +601,12 @@ int arm64_save_var2(scf_dag_node_t* dn, scf_register_arm64_t* r, scf_3ac_code_t* scf_arm64_OpCode_t* mov; scf_instruction_t* inst; - int var_size = arm64_variable_size(v); + int size = arm64_variable_size(v); int is_float = scf_variable_float(v); - assert(var_size == r->bytes); + assert(size == r->bytes); - if (v->const_literal_flag) { + 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; } @@ -614,45 +614,29 @@ int arm64_save_var2(scf_dag_node_t* dn, scf_register_arm64_t* r, scf_3ac_code_t* // if temp var in register, alloc it in stack if (0 == v->bp_offset && !v->global_flag && !v->local_flag) { - int local_vars_size = f->local_vars_size; - local_vars_size += var_size; + int tmp = f->local_vars_size; + tmp += size; - if (local_vars_size & 0x7) - local_vars_size = (local_vars_size + 7) >> 3 << 3; + if (tmp & 0x7) + tmp = (tmp + 7) >> 3 << 3; - v->bp_offset = -local_vars_size; + v->bp_offset = -tmp; v->tmp_flag = 1; - f->local_vars_size = local_vars_size; - - scf_logw("r: %s, temp var, ", r->name); - if (v->w) - printf("v_%d_%d/%s, bp_offset: %d\n", v->w->line, v->w->pos, v->w->text->data, v->bp_offset); - else - printf("v_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v, v->bp_offset); + f->local_vars_size = tmp; + } - } else { #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", var_size, v->bp_offset, r->name); + 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 - } - - if (is_float) { - scf_loge("\n"); - return -EINVAL; - } - - scf_loge("v->size: %d\n", v->size); int ret = arm64_make_inst_G2M(c, f, r, NULL, v); - if (ret < 0) { - scf_loge("\n"); + if (ret < 0) return ret; - } end: // if this var is function argment, it become a normal local var diff --git a/native/arm64/scf_arm64_reg.h b/native/arm64/scf_arm64_reg.h index fb26abf..d23872d 100644 --- a/native/arm64/scf_arm64_reg.h +++ b/native/arm64/scf_arm64_reg.h @@ -46,6 +46,14 @@ static uint32_t arm64_abi_regs[] = 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])) diff --git a/native/arm64/scf_arm64_util.c b/native/arm64/scf_arm64_util.c index 3de05ef..b52b974 100644 --- a/native/arm64/scf_arm64_util.c +++ b/native/arm64/scf_arm64_util.c @@ -22,8 +22,26 @@ int arm64_make_inst_I2G(scf_3ac_code_t* c, scf_register_arm64_t* rd, uint64_t im { 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); @@ -217,15 +235,9 @@ int arm64_make_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 return -EINVAL; } - opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | ri->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) | ri->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } + 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); } @@ -350,15 +362,9 @@ int arm64_make_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 return -EINVAL; } - opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | ri->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) | ri->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } + 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; } @@ -466,15 +472,9 @@ int arm64_make_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 return -EINVAL; } - opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | ri->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) | ri->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } + 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; } @@ -551,15 +551,9 @@ int arm64_make_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm64 return -EINVAL; } - opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | ri->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) | ri->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } + 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; } @@ -835,15 +829,9 @@ int arm64_make_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_arm6 if (ret < 0) return ret; - opcode = (0x52 << 24) | (0x1 << 23) | ((offset & 0xffff) << 5) | ro->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) | ro->id; - inst = arm64_make_inst(c, opcode); - ARM64_INST_ADD_CHECK(c->instructions, inst); - } + 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); } diff --git a/native/arm64/scf_arm64_util.h b/native/arm64/scf_arm64_util.h index 0f454db..b1809cf 100644 --- a/native/arm64/scf_arm64_util.h +++ b/native/arm64/scf_arm64_util.h @@ -120,27 +120,43 @@ enum scf_arm64_OpCode_types { 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, diff --git a/native/x64/scf_x64_reg.c b/native/x64/scf_x64_reg.c index 0cf8314..d113bb2 100644 --- a/native/x64/scf_x64_reg.c +++ b/native/x64/scf_x64_reg.c @@ -464,7 +464,7 @@ int x64_save_var2(scf_dag_node_t* dn, scf_register_x64_t* r, scf_3ac_code_t* c, assert(var_size == r->bytes); - if (v->const_literal_flag) { + 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; } -- 2.25.1