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;
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;
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);
+ }
+ }
}
}
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);
_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;
}
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);
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;
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);
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
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;
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)
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;
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;
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");
}
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);
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)
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);
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");
}
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)
{
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;
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);
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;
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);
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);
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;
}
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)
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");
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;
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;
+}
+
f->code_bytes += bb->code_bytes;
}
-#if 0
+#if 1
if (f->code_bytes & 0x7) {
size_t n = 8 - (f->code_bytes & 0x7);