support arm64: 'qsort' test ok in ../examples/qsort.c
authoryu.dongliang <18588496441@163.com>
Sat, 25 Feb 2023 05:03:58 +0000 (13:03 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 25 Feb 2023 05:03:58 +0000 (13:03 +0800)
core/scf_3ac.c
core/scf_optimizer_generate_loads_saves.c
native/arm64/scf_arm64.c
native/arm64/scf_arm64.h
native/arm64/scf_arm64_bb_color.c
native/arm64/scf_arm64_inst.c
native/arm64/scf_arm64_reg.c
native/arm64/scf_arm64_util.c
parse/scf_parse2.c

index d9f0e4a5b3c5b9f8f6b30c20de28835365108945..e62d8e0167411ff20719e18a2c4a95d33b29c4ce 100644 (file)
@@ -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;
 
index e55c50c7183195d4c75d3d40efeade17fb754663..ce60ac9ff49e8ea19a762972bf57e73cef2ce975 100644 (file)
@@ -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);
+                                       }
+                               }
                        }
                }
 
index e9288505e0bde264fccf69724f80f591bd613b78..0b28292c2b45ea2ea603d8b13a11b02ca98016fd 100644 (file)
@@ -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;
index 2790e112ff0fba9c7a01c28e24dc60ee603d7577..ec6eb1fa1b465977a09a30d8160a6f71d0ff3ec4 100644 (file)
@@ -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
 
index c9d1913f9b3f680acd86bcb3f97e5790192a257b..e160a5456c2991722d689ba5e29ac00528aca026 100644 (file)
@@ -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)
index cc88022851a8c99167c84246d55952aed9f49fc9..a843b89a9511ad732f3f3260d1fb45266f9af253 100644 (file)
@@ -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;
index a5a39d5a64ebcf8e1f6b67acc62319b08a33bad1..4c66269112e7161c8d9d944e905ab0c522dd4dee 100644 (file)
@@ -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)
index 68ccd4e5b01ec575d4a8e35399b3d7718f41e64f..02bc24173abb970acbb8e9ceb2bd12808b221301 100644 (file)
@@ -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;
+}
+
index 8df2fda75ca8f0c3e971ea3e00fdea9ee673fec7..b1db2839c7b88c3c5ebc45f03a5b34bb4f9d95ef 100644 (file)
@@ -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);