support ARM64: float / double args for function call
authoryu.dongliang <18588496441@163.com>
Thu, 2 Mar 2023 06:47:54 +0000 (14:47 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 2 Mar 2023 06:47:54 +0000 (14:47 +0800)
native/arm64/scf_arm64_inst.c
native/arm64/scf_arm64_reg.c
native/arm64/scf_arm64_reg.h
native/arm64/scf_arm64_util.c
native/arm64/scf_arm64_util.h
native/x64/scf_x64_reg.c

index fb099b1118e39512aadcfdb4043980226c212ecf..bd94ad708ae1e054beb0d69ea0c4234a436bec83 100644 (file)
@@ -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;
index a6a717fdf9c29ecdd1808a5e499e5c78be41d7dd..dfc0755e19135622e009d50320a352ab79f582b2 100644 (file)
@@ -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
index fb26abf32bc0c598c986a5571da6fe7a4e8b98bd..d23872dcebe484d796c5b3ddcd5fd024dd612582 100644 (file)
@@ -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]))
 
index 3de05ef56d67d8f4fa643fafe6c1244ef1ac9783..b52b974abcdc261c481c2c2ee5d67ee7e48d15f1 100644 (file)
@@ -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);
        }
index 0f454db07881b2c9f7a7c7be2c40e733d4caf739..b1809cf2f07c22695a395f1049a0112282fcf515 100644 (file)
@@ -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,
index 0cf83149154accbc554346c69fff07c4e40aa12e..d113bb265f7ed6d3518b42a6f3630ec09a600081 100644 (file)
@@ -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;
        }