return -EINVAL;
break;
};
+
+ } else if (!strcmp(debug->arch, "arm32")) {
+
+ switch (type) {
+
+ case R_X86_64_32:
+ case R_X86_64_64:
+ rela->type = R_ARM_ABS32;
+ break;
+
+ default:
+ scf_loge("\n");
+ return -EINVAL;
+ break;
+ };
}
return 0;
if (!strcmp(debug->arch, "arm64") || !strcmp(debug->arch, "naja"))
rela->type = R_AARCH64_ABS64;
+ else if (!strcmp(debug->arch, "arm32"))
+ rela->type = R_ARM_ABS32;
DWARF_DEBUG_LINE_FILL (lm->address);
}
extern scf_elf_ops_t elf_ops_x64;
extern scf_elf_ops_t elf_ops_arm64;
+extern scf_elf_ops_t elf_ops_arm32;
extern scf_elf_ops_t elf_ops_naja;
scf_elf_ops_t* elf_ops_array[] =
{
&elf_ops_x64,
&elf_ops_arm64,
+ &elf_ops_arm32,
&elf_ops_naja,
NULL,
--- /dev/null
+#include"scf_elf_arm32.h"
+#include"scf_elf_link.h"
+
+static int _arm32_elf_write_rel(scf_elf_context_t* elf)
+{
+ return elf32_write_rel(elf, EM_ARM);
+}
+
+static int _arm32_elf_link_cs(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs, uint64_t cs_base)
+{
+ elf_sym_t* sym;
+ Elf32_Rela* rela;
+
+ assert(rs->data_len % sizeof(Elf32_Rela) == 0);
+
+ int i;
+ for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) {
+
+ rela = (Elf32_Rela* )(rs->data + i);
+ sym = NULL;
+
+ int sym_idx = ELF32_R_SYM(rela->r_info);
+
+ scf_loge("i: %d, sym_idx '%d'\n", i, sym_idx);
+
+ assert(sym_idx >= 1);
+ assert(sym_idx - 1 < arm32->symbols->size);
+
+ sym = arm32->symbols->data[sym_idx - 1];
+ if (sym->dyn_flag) {
+ scf_loge("sym '%s' in dynamic so\n", sym->name->data);
+ continue;
+ }
+
+ int j = elf32_find_sym(&sym, rela, arm32->symbols);
+ if (j < 0)
+ return -1;
+
+ int32_t offset = sym->sym.st_value - (cs_base + rela->r_offset) + rela->r_addend;
+
+ rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info));
+
+ switch (ELF32_R_TYPE(rela->r_info)) {
+
+ case R_ARM_CALL:
+
+ offset -= 8; // 'pc' is 'current + 8'.
+ assert(0 == (offset & 0x3));
+
+ scf_loge("sym: %s, offset: %#x, %#x\n", sym->name->data, offset, rela->r_offset);
+ offset >>= 2;
+
+ if (offset > 0x7fffff || offset < -0x7fffff) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ scf_loge("sym: %s, offset: %#x, %#x\n", sym->name->data, offset, rela->r_offset);
+
+ *(uint32_t*)(s->data + rela->r_offset) &= 0xff000000;
+ *(uint32_t*)(s->data + rela->r_offset) |= 0x00ffffff & offset;
+ break;
+
+ case R_ARM_REL32:
+ scf_loge("sym: %s, offset: %#x, %#x, st_value: %#x, cs: %#lx\n", sym->name->data, offset, rela->r_offset,
+ sym->sym.st_value, cs_base + rela->r_offset);
+
+ *(uint32_t*)(s->data + rela->r_offset) += offset;
+ break;
+ default:
+ scf_loge("ELF32_R_TYPE(rela->r_info): %d\n", ELF32_R_TYPE(rela->r_info));
+ return -EINVAL;
+ break;
+ };
+ }
+
+ return 0;
+}
+
+static int _arm32_elf_link_ds(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs)
+{
+ elf_sym_t* sym;
+ Elf32_Rela* rela;
+
+ assert(rs->data_len % sizeof(Elf32_Rela) == 0);
+
+ int i;
+ for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) {
+
+ rela = (Elf32_Rela* )(rs->data + i);
+ sym = NULL;
+
+ int j = elf32_find_sym(&sym, rela, arm32->symbols);
+ if (j < 0)
+ return -1;
+
+ assert(ELF32_R_TYPE(rela->r_info) == R_ARM_ABS32);
+
+ uint64_t offset = sym->sym.st_value + rela->r_addend;
+
+ rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info));
+
+ switch (ELF32_R_TYPE(rela->r_info)) {
+
+ case R_ARM_ABS32:
+ memcpy(s->data + rela->r_offset, &offset, 4);
+ break;
+ default:
+ scf_loge("\n");
+ return -EINVAL;
+ break;
+ };
+ }
+
+ return 0;
+}
+
+static int _arm32_elf_link_debug(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs)
+{
+ elf_sym_t* sym;
+ elf_sym_t* sym2;
+ Elf32_Rela* rela;
+
+ assert(rs->data_len % sizeof(Elf32_Rela) == 0);
+
+ int i;
+ for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) {
+
+ rela = (Elf32_Rela* )(rs->data + i);
+ sym = NULL;
+
+ int j = elf32_find_sym(&sym, rela, arm32->symbols);
+ if (j < 0)
+ return -1;
+
+ uint64_t offset = sym->sym.st_value + rela->r_addend;
+
+ if (!strncmp(sym->name->data, ".debug_", 7)) {
+
+ int k = ELF32_R_SYM(rela->r_info);
+
+ sym2 = arm32->symbols->data[k - 1];
+
+ offset = sym2->sym.st_value + rela->r_addend;
+ rela->r_addend = offset;
+
+ } else if (!strcmp(sym->name->data, ".text")) {
+
+ int k = ELF32_R_SYM(rela->r_info);
+
+ sym2 = arm32->symbols->data[k - 1];
+
+ offset = sym2->sym.st_value;
+ rela->r_addend = sym2->sym.st_value - sym->sym.st_value;
+ }
+
+ rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info));
+
+ switch (ELF32_R_TYPE(rela->r_info)) {
+
+ case R_ARM_ABS32:
+ memcpy(s->data + rela->r_offset, &offset, 4);
+ break;
+ default:
+ scf_loge("\n");
+ return -EINVAL;
+ break;
+ };
+ }
+
+ return 0;
+}
+
+static int _arm32_elf_link_sections(elf_native_t* arm32, uint32_t cs_index, uint32_t ds_index)
+{
+ elf_section_t* s;
+ elf_section_t* rs;
+
+ int i;
+ for (i = 0; i < arm32->sections->size; i++) {
+ rs = arm32->sections->data[i];
+
+ if (SHT_RELA != rs->sh.sh_type)
+ continue;
+
+ assert(rs->sh.sh_info < arm32->sections->size);
+
+ if (cs_index == rs->sh.sh_info
+ || ds_index == rs->sh.sh_info)
+ continue;
+
+ if (!strcmp(rs->name->data, ".rela.plt"))
+ continue;
+
+ s = arm32->sections->data[rs->sh.sh_info - 1];
+
+ scf_loge("s: %s, rs: %s, rs->sh.sh_info: %u\n", s->name->data, rs->name->data, rs->sh.sh_info);
+
+ assert(!strcmp(s->name->data, rs->name->data + 5));
+
+ if (_arm32_elf_link_debug(arm32, s, rs) < 0) {
+ scf_loge("\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int _arm32_elf_write_exec(scf_elf_context_t* elf)
+{
+ elf_native_t* arm32 = elf->priv;
+ int nb_phdrs = 3;
+
+ if (arm32->dynsyms && arm32->dynsyms->size) {
+ __arm32_elf_add_dyn(arm32);
+ nb_phdrs = 6;
+ }
+
+ int nb_sections = 1 + arm32->sections->size + 1 + 1 + 1;
+ uint64_t shstrtab_offset = 1;
+ uint64_t strtab_offset = 1;
+ uint64_t dynstr_offset = 1;
+ Elf32_Off phdr_offset = sizeof(arm32->eh) + sizeof(Elf32_Shdr) * nb_sections;
+ Elf32_Off section_offset = phdr_offset + sizeof(Elf32_Phdr) * nb_phdrs;
+
+ elf_section_t* s;
+ elf_section_t* cs = NULL;
+ elf_section_t* ros = NULL;
+ elf_section_t* ds = NULL;
+ elf_section_t* crela = NULL;
+ elf_section_t* drela = NULL;
+ elf_sym_t* sym;
+
+ int i;
+ for (i = 0; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ scf_logw("i: %d, section: %s\n", i, s->name->data);
+
+ if (!strcmp(".text", s->name->data)) {
+
+ assert(s->data_len > 0);
+ assert(!cs);
+ cs = s;
+
+ } else if (!strcmp(".rodata", s->name->data)) {
+
+ assert(s->data_len >= 0);
+ assert(!ros);
+ ros = s;
+
+ } else if (!strcmp(".data", s->name->data)) {
+
+ assert(s->data_len >= 0);
+ assert(!ds);
+ ds = s;
+
+ } else if (!strcmp(".rela.text", s->name->data)) {
+
+ assert(!crela);
+ crela = s;
+ scf_loge("i: %d, section: %s\n", i, s->name->data);
+
+ } else if (!strcmp(".rela.data", s->name->data)) {
+
+ assert(!drela);
+ drela = s;
+ }
+
+ s->offset = section_offset;
+ section_offset += s->data_len;
+ }
+ assert(crela);
+
+ uint64_t cs_align = (cs ->offset + cs ->data_len + 0x200000 - 1) >> 21 << 21;
+ uint64_t ro_align = (ros->offset + ros->data_len + 0x200000 - 1) >> 21 << 21;
+
+ uint64_t rx_base = 0x400000;
+ uint64_t r_base = 0x400000 + cs_align;
+ uint64_t rw_base = 0x400000 + cs_align + ro_align;
+
+ uint64_t cs_base = cs->offset + rx_base;
+ uint64_t ro_base = ros->offset + r_base;
+ uint64_t ds_base = ds->offset + rw_base;
+ uint64_t _start = 0;
+
+ for (i = 0; i < arm32->symbols->size; i++) {
+ sym = arm32->symbols->data[i];
+
+ uint32_t shndx = sym->sym.st_shndx;
+
+ if (shndx == cs->index)
+ sym->sym.st_value += cs_base;
+
+ else if (shndx == ros->index)
+ sym->sym.st_value += ro_base;
+
+ else if (shndx == ds->index)
+ sym->sym.st_value += ds_base;
+
+ scf_logd("sym: %s, %#lx, st_shndx: %d\n", sym->name->data, sym->sym.st_value, sym->sym.st_shndx);
+ }
+
+ int ret = _arm32_elf_link_cs(arm32, cs, crela, cs_base);
+ if (ret < 0) {
+ scf_loge("ret: %d\n", ret);
+ return ret;
+ }
+
+ if (drela) {
+ ret = _arm32_elf_link_ds(arm32, ds, drela);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = _arm32_elf_link_sections(arm32, cs->index, ds->index);
+ if (ret < 0)
+ return ret;
+
+ elf32_process_syms(arm32, cs->index);
+
+ cs ->sh.sh_addr = cs_base;
+ ds ->sh.sh_addr = ds_base;
+ ros->sh.sh_addr = ro_base;
+
+ if (6 == nb_phdrs)
+ __arm32_elf_post_dyn(arm32, rx_base, rw_base, cs);
+
+ for (i = 0; i < arm32->symbols->size; i++) {
+ sym = arm32->symbols->data[i];
+
+ if (!strcmp(sym->name->data, "_start")) {
+
+ if (0 != _start) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ _start = sym->sym.st_value;
+ break;
+ }
+ }
+
+ // write elf header
+ elf_header(&arm32->eh, ET_EXEC, EM_ARM, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1);
+ fwrite(&arm32->eh, sizeof(arm32->eh), 1, elf->fp);
+
+ // write null section header
+ fwrite(&arm32->sh_null, sizeof(arm32->sh_null), 1, elf->fp);
+
+ // write user's section header
+ section_offset = phdr_offset + sizeof(Elf32_Phdr) * nb_phdrs;
+
+ for (i = 0; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ if (SHT_RELA == s->sh.sh_type && 0 == s->sh.sh_link)
+ s->sh.sh_link = nb_sections - 3;
+
+ section_header(&s->sh, shstrtab_offset, s->sh.sh_addr,
+ section_offset, s->data_len,
+ s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize);
+
+ if (SHT_STRTAB != s->sh.sh_type)
+ s->sh.sh_addralign = 4;
+
+ section_offset += s->data_len;
+ shstrtab_offset += s->name->len + 1;
+
+ fwrite(&s->sh, sizeof(s->sh), 1, elf->fp);
+ }
+
+ // set user's symbols' name
+ int nb_local_syms = 1;
+
+ for (i = 0; i < arm32->symbols->size; i++) {
+ sym = arm32->symbols->data[i];
+
+ if (sym->name) {
+ sym->sym.st_name = strtab_offset;
+ strtab_offset += sym->name->len + 1;
+ } else
+ sym->sym.st_name = 0;
+
+ if (STB_LOCAL == ELF32_ST_BIND(sym->sym.st_info))
+ nb_local_syms++;
+ }
+
+ // write symtab section header
+ section_header(&arm32->sh_symtab, shstrtab_offset, 0,
+ section_offset, (arm32->symbols->size + 1) * sizeof(Elf32_Sym),
+ nb_sections - 2, nb_local_syms, sizeof(Elf32_Sym));
+
+ fwrite(&arm32->sh_symtab, sizeof(arm32->sh_symtab), 1, elf->fp);
+
+ section_offset += (arm32->symbols->size + 1) * sizeof(Elf32_Sym);
+ shstrtab_offset += strlen(".symtab") + 1;
+
+ // write strtab section header
+ section_header(&arm32->sh_strtab, shstrtab_offset, 0,
+ section_offset, strtab_offset,
+ 0, 0, 0);
+ fwrite(&arm32->sh_strtab, sizeof(arm32->sh_strtab), 1, elf->fp);
+ section_offset += strtab_offset;
+ shstrtab_offset += strlen(".strtab") + 1;
+
+ // write shstrtab section header
+ uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1;
+ section_header(&arm32->sh_shstrtab, shstrtab_offset, 0,
+ section_offset, shstrtab_len, 0, 0, 0);
+ fwrite(&arm32->sh_shstrtab, sizeof(arm32->sh_shstrtab), 1, elf->fp);
+
+#if 1
+ if (6 == nb_phdrs) {
+ __arm32_elf_write_phdr(elf, rx_base, phdr_offset, nb_phdrs);
+
+ __arm32_elf_write_interp(elf, rx_base, arm32->interp->offset, arm32->interp->data_len);
+ }
+
+ __arm32_elf_write_text (elf, rx_base, 0, cs->offset + cs->data_len);
+ __arm32_elf_write_rodata(elf, r_base, ros->offset, ros->data_len);
+
+ if (6 == nb_phdrs) {
+ __arm32_elf_write_data(elf, rw_base, arm32->dynamic->offset,
+ arm32->dynamic->data_len + arm32->got_plt->data_len + ds->data_len);
+
+ __arm32_elf_write_dynamic(elf, rw_base, arm32->dynamic->offset, arm32->dynamic->data_len);
+ } else {
+ __arm32_elf_write_data(elf, rw_base, ds->offset, ds->data_len);
+ }
+#endif
+
+ elf32_write_sections(elf);
+ elf32_write_symtab (elf);
+ elf32_write_strtab (elf);
+ elf32_write_shstrtab(elf);
+ return 0;
+}
+
+scf_elf_ops_t elf_ops_arm32 =
+{
+ .machine = "arm32",
+
+ .open = elf32_open,
+ .close = elf32_close,
+
+ .add_sym = elf32_add_sym,
+ .add_section = elf32_add_section,
+
+ .add_rela_section = elf32_add_rela_section,
+
+ .add_dyn_need = elf32_add_dyn_need,
+ .add_dyn_rela = elf32_add_dyn_rela,
+
+ .read_syms = elf32_read_syms,
+ .read_relas = elf32_read_relas,
+ .read_section = elf32_read_section,
+
+ .write_rel = _arm32_elf_write_rel,
+ .write_exec = _arm32_elf_write_exec,
+};
+
--- /dev/null
+#ifndef SCF_ELF_ARM32_H
+#define SCF_ELF_ARM32_H
+
+#include"scf_elf.h"
+#include"scf_elf_native32.h"
+#include"scf_vector.h"
+#include"scf_string.h"
+
+int __arm32_elf_add_dyn (elf_native_t* arm32);
+int __arm32_elf_post_dyn(elf_native_t* arm32, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs);
+
+int __arm32_elf_write_phdr (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs);
+int __arm32_elf_write_interp (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len);
+int __arm32_elf_write_text (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len);
+int __arm32_elf_write_rodata (scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len);
+int __arm32_elf_write_data (scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len);
+int __arm32_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len);
+
+#endif
+
--- /dev/null
+#include"scf_elf_arm32.h"
+#include"scf_elf_link.h"
+
+static uint32_t arm32_plt_lazy[5] = {
+ 0xe52de004, // push {lr}
+ 0xe59fe004, // ldr lr, [pc, #4]
+ 0xe08fe00e, // add lr, pc, lr
+ 0xe5bef008, // ldr pc, [lr, #8]!
+
+ 0x00000000, //
+};
+
+static uint32_t arm32_plt[3] = {
+ 0xe28fc600, // add r12, pc, #0, 12
+ 0xe28cca00, // add r12, r12, #16, 20
+ 0xe5bcf000, // ldr pc, [r12, #0]!
+};
+
+
+static uint32_t _arm32_elf_hash(const uint8_t* p)
+{
+ uint32_t k = 0;
+ uint32_t u = 0;
+
+ while (*p) {
+ k = (k << 4) + *p++;
+ u = k & 0xf0000000;
+
+ if (u)
+ k ^= u >> 24;
+ k &= ~u;
+ }
+ return k;
+}
+
+static int _arm32_elf_add_interp(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".interp");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ char* interp = "/lib/ld-linux-armhf.so.3";
+ size_t len = strlen(interp);
+ size_t align = (len + 1 + 7) & ~0x7;
+
+ s->data = calloc(1, align);
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ memcpy(s->data, interp, len);
+ s->data_len = align;
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_PROGBITS;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_addralign = 1;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_gnu_version(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".gnu.version");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = calloc(arm32->dynsyms->size, sizeof(Elf32_Versym));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = arm32->dynsyms->size * sizeof(Elf32_Versym);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_GNU_versym;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_addralign = 4;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_gnu_version_r(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".gnu.version_r");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = calloc(1, sizeof(Elf32_Verneed) + sizeof(Elf32_Vernaux));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = sizeof(Elf32_Verneed) + sizeof(Elf32_Vernaux);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_GNU_verneed;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_addralign = 4;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_dynsym(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".dynsym");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = calloc(arm32->dynsyms->size + 1, sizeof(Elf32_Sym));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = (arm32->dynsyms->size + 1) * sizeof(Elf32_Sym);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_DYNSYM;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_info = 1;
+ s->sh.sh_addralign = 4;
+ s->sh.sh_entsize = sizeof(Elf32_Sym);
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_dynstr(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".dynstr");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_STRTAB;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_addralign = 1;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_dynamic(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".dynamic");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ int nb_tags = arm32->dyn_needs->size + 11 + 1;
+
+ s->data = calloc(nb_tags, sizeof(Elf32_Dyn));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = nb_tags * sizeof(Elf32_Dyn);
+
+ scf_logw("nb_tags: %d\n", nb_tags);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_PROGBITS;
+ s->sh.sh_flags = SHF_ALLOC | SHF_WRITE;
+ s->sh.sh_addralign = 4;
+ s->sh.sh_entsize = sizeof(Elf32_Dyn);
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_got_plt(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".got.plt");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = calloc(arm32->dynsyms->size + 4, sizeof(uint32_t));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = (arm32->dynsyms->size + 4) * sizeof(uint32_t);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_PROGBITS;
+ s->sh.sh_flags = SHF_ALLOC | SHF_WRITE;
+ s->sh.sh_addralign = 4;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_rela_plt(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".rela.plt");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = calloc(arm32->dynsyms->size, sizeof(Elf32_Rela));
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ s->data_len = arm32->dynsyms->size * sizeof(Elf32_Rela);
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_RELA;
+ s->sh.sh_flags = SHF_ALLOC | SHF_INFO_LINK;
+ s->sh.sh_addralign = 4;
+ s->sh.sh_entsize = sizeof(Elf32_Rela);
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _arm32_elf_add_plt(elf_native_t* arm32, elf_section_t** ps)
+{
+ elf_section_t* s;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(".plt");
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->data = malloc(sizeof(arm32_plt_lazy) + sizeof(arm32_plt) * arm32->dynsyms->size);
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+
+ memcpy(s->data, arm32_plt_lazy, sizeof(arm32_plt_lazy));
+ s->data_len = sizeof(arm32_plt_lazy);
+
+ int i;
+ for (i = 0; i < arm32->dynsyms->size; i++) {
+
+ memcpy(s->data + s->data_len, arm32_plt, sizeof(arm32_plt));
+
+ s->data_len += sizeof(arm32_plt);
+ }
+
+ s->index = 1;
+
+ s->sh.sh_type = SHT_PROGBITS;
+ s->sh.sh_flags = SHF_ALLOC;
+ s->sh.sh_addralign = 1;
+
+ int ret = scf_vector_add(arm32->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s->data);
+ free(s);
+ return -ENOMEM;
+ }
+
+ *ps = s;
+ return 0;
+}
+
+static int _section_cmp(const void* v0, const void* v1)
+{
+ const elf_section_t* s0 = *(const elf_section_t**)v0;
+ const elf_section_t* s1 = *(const elf_section_t**)v1;
+
+ if (s0->index < s1->index)
+ return -1;
+ else if (s0->index > s1->index)
+ return 1;
+ return 0;
+}
+
+int __arm32_elf_add_dyn (elf_native_t* arm32)
+{
+ elf_section_t* s;
+ elf_sym_t* sym;
+ Elf32_Rela* rela;
+
+ int i;
+ for (i = arm32->symbols->size - 1; i >= 0; i--) {
+ sym = arm32->symbols->data[i];
+
+ uint16_t shndx = sym->sym.st_shndx;
+
+ if (STT_SECTION == ELF32_ST_TYPE(sym->sym.st_info)) {
+ if (shndx > 0) {
+ assert(shndx - 1 < arm32->sections->size);
+ sym->section = arm32->sections->data[shndx - 1];
+ }
+ } else if (0 != shndx) {
+ if (shndx - 1 < arm32->sections->size)
+ sym->section = arm32->sections->data[shndx - 1];
+ }
+ }
+
+ char* sh_names[] = {
+ ".interp",
+ ".dynsym",
+ ".dynstr",
+// ".gnu.version_r",
+ ".rela.plt",
+ ".plt",
+
+ ".text",
+ ".rodata",
+
+ ".dynamic",
+ ".got.plt",
+ ".data",
+ };
+
+ for (i = 0; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ s->index = arm32->sections->size + 1 + sizeof(sh_names) / sizeof(sh_names[0]);
+
+ scf_logw("s: %s, link: %d, info: %d\n", s->name->data, s->sh.sh_link, s->sh.sh_info);
+
+ if (s->sh.sh_link > 0) {
+ assert(s->sh.sh_link - 1 < arm32->sections->size);
+
+ s->link = arm32->sections->data[s->sh.sh_link - 1];
+ }
+
+ if (s->sh.sh_info > 0) {
+ assert(s->sh.sh_info - 1 < arm32->sections->size);
+
+ s->info = arm32->sections->data[s->sh.sh_info - 1];
+ }
+ }
+
+ _arm32_elf_add_interp(arm32, &arm32->interp);
+ _arm32_elf_add_dynsym(arm32, &arm32->dynsym);
+ _arm32_elf_add_dynstr(arm32, &arm32->dynstr);
+
+// _arm32_elf_add_gnu_version_r(arm32, &arm32->gnu_version_r);
+
+ _arm32_elf_add_rela_plt(arm32, &arm32->rela_plt);
+ _arm32_elf_add_plt(arm32, &arm32->plt);
+
+ _arm32_elf_add_dynamic(arm32, &arm32->dynamic);
+ _arm32_elf_add_got_plt(arm32, &arm32->got_plt);
+
+ scf_string_t* str = scf_string_alloc();
+
+ char c = '\0';
+ scf_string_cat_cstr_len(str, &c, 1);
+
+ Elf32_Sym* syms = (Elf32_Sym* )arm32->dynsym->data;
+ Elf32_Sym sym0 = {0};
+
+ sym0.st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE);
+ memcpy(&syms[0], &sym0, sizeof(Elf32_Sym));
+
+ for (i = 0; i < arm32->dynsyms->size; i++) {
+ elf_sym_t* xsym = arm32->dynsyms->data[i];
+
+ memcpy(&syms[i + 1], &xsym->sym, sizeof(Elf32_Sym));
+
+ syms[i + 1].st_name = str->len;
+
+ scf_loge("i: %d, st_value: %#x\n", i, syms[i + 1].st_value);
+
+ scf_string_cat_cstr_len(str, xsym->name->data, xsym->name->len + 1);
+ }
+
+#if 0
+ Elf32_Verneed* verneeds = (Elf32_Verneed*) arm32->gnu_version_r->data;
+ Elf32_Vernaux* vernauxs = (Elf32_Vernaux*)(arm32->gnu_version_r->data +sizeof(Elf32_Verneed));
+
+ verneeds[0].vn_version = VER_NEED_CURRENT;
+ verneeds[0].vn_file = str->len;
+ verneeds[0].vn_cnt = 1;
+ verneeds[0].vn_aux = sizeof(Elf32_Verneed);
+ verneeds[0].vn_next = 0;
+
+ scf_string_cat_cstr_len(str, "libc.so.6", strlen("libc.so.6") + 1);
+
+ vernauxs[0].vna_hash = _arm32_elf_hash("GLIBC_2.4");
+ vernauxs[0].vna_flags = 0;
+ vernauxs[0].vna_other = 2;
+ vernauxs[0].vna_name = str->len;
+ vernauxs[0].vna_next = 0;
+
+ scf_string_cat_cstr_len(str, "GLIBC_2.4", strlen("GLIBC_2.4") + 1);
+#endif
+
+ Elf32_Dyn* dyns = (Elf32_Dyn*)arm32->dynamic->data;
+
+ size_t prefix = strlen("../lib/arm32/");
+
+ for (i = 0; i < arm32->dyn_needs->size; i++) {
+ scf_string_t* needed = arm32->dyn_needs->data[i];
+
+ dyns[i].d_tag = DT_NEEDED;
+ dyns[i].d_un.d_val = str->len;
+
+ scf_logw("i: %d, %s, %s\n", i, needed->data, needed->data + prefix);
+
+ scf_string_cat_cstr_len(str, needed->data + prefix, needed->len - prefix + 1);
+ }
+
+ dyns[i].d_tag = DT_STRTAB;
+ dyns[i + 1].d_tag = DT_SYMTAB;
+ dyns[i + 2].d_tag = DT_STRSZ;
+ dyns[i + 3].d_tag = DT_SYMENT;
+ dyns[i + 4].d_tag = DT_PLTGOT;
+ dyns[i + 5].d_tag = DT_PLTRELSZ;
+ dyns[i + 6].d_tag = DT_PLTREL;
+ dyns[i + 7].d_tag = DT_JMPREL;
+// dyns[i + 8].d_tag = DT_VERNEED;
+// dyns[i + 9].d_tag = DT_VERNEEDNUM;
+// dyns[i +10].d_tag = DT_VERSYM;
+ dyns[i +8].d_tag = DT_NULL;
+
+ dyns[i].d_un.d_ptr = (uintptr_t)arm32->dynstr;
+ dyns[i + 1].d_un.d_ptr = (uintptr_t)arm32->dynsym;
+ dyns[i + 2].d_un.d_val = str->len;
+ dyns[i + 3].d_un.d_val = sizeof(Elf32_Sym);
+ dyns[i + 4].d_un.d_ptr = (uintptr_t)arm32->got_plt;
+ dyns[i + 5].d_un.d_ptr = sizeof(Elf32_Rela);
+ dyns[i + 6].d_un.d_ptr = DT_RELA;
+ dyns[i + 7].d_un.d_ptr = (uintptr_t)arm32->rela_plt;
+// dyns[i + 8].d_un.d_ptr = (uintptr_t)arm32->gnu_version_r;
+// dyns[i + 9].d_un.d_ptr = 1;
+// dyns[i +10].d_un.d_ptr = (uintptr_t)arm32->gnu_version;
+ dyns[i +8].d_un.d_ptr = 0;
+
+
+ int fill = 8 - (str->len & 0x7);
+ if (fill > 0)
+ scf_string_fill_zero(str, fill);
+
+ arm32->dynstr->data = str->data;
+ arm32->dynstr->data_len = str->len;
+
+ str->data = NULL;
+ str->len = 0;
+ str->capacity = 0;
+ scf_string_free(str);
+ str = NULL;
+
+ arm32->rela_plt->link = arm32->dynsym;
+ arm32->rela_plt->info = arm32->got_plt;
+ arm32->dynsym ->link = arm32->dynstr;
+#if 0
+ arm32->gnu_version_r->link = arm32->dynstr;
+ arm32->gnu_version_r->info = arm32->interp;
+#endif
+
+ for (i = 0; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ int j;
+ for (j = 0; j < sizeof(sh_names) / sizeof(sh_names[0]); j++) {
+ if (!strcmp(s->name->data, sh_names[j]))
+ break;
+ }
+
+ if (j < sizeof(sh_names) / sizeof(sh_names[0]))
+ s->index = j + 1;
+
+ scf_logd("i: %d, s: %s, index: %d\n", i, s->name->data, s->index);
+ }
+
+ qsort(arm32->sections->data, arm32->sections->size, sizeof(void*), _section_cmp);
+
+ int j = sizeof(sh_names) / sizeof(sh_names[0]);
+
+ for (i = j; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ s->index = i + 1;
+ }
+
+ for (i = 0; i < arm32->sections->size; i++) {
+ s = arm32->sections->data[i];
+
+ scf_loge("i: %d, s: %s, index: %d\n", i, s->name->data, s->index);
+
+ if (s->link) {
+ scf_logd("link: %s, index: %d\n", s->link->name->data, s->link->index);
+ s->sh.sh_link = s->link->index;
+ }
+
+ if (s->info) {
+ scf_logd("info: %s, index: %d\n", s->info->name->data, s->info->index);
+ s->sh.sh_info = s->info->index;
+ }
+
+ if (s == arm32->dynstr)
+ dyns[arm32->dyn_needs->size].d_un.d_ptr = i;
+
+ else if (arm32->dynsym == s)
+ dyns[arm32->dyn_needs->size + 1].d_un.d_ptr = i;
+
+ else if (arm32->got_plt == s)
+ dyns[arm32->dyn_needs->size + 4].d_un.d_ptr = i;
+
+ else if (arm32->rela_plt == s)
+ dyns[arm32->dyn_needs->size + 7].d_un.d_ptr = i;
+ }
+
+ for (i = 0; i < arm32->symbols->size; i++) {
+ sym = arm32->symbols->data[i];
+
+ if (sym->section) {
+ scf_logw("sym: %s, index: %d->%d\n", sym->name->data, sym->sym.st_shndx, sym->section->index);
+ sym->sym.st_shndx = sym->section->index;
+ }
+ }
+
+ return 0;
+}
+
+int __arm32_elf_post_dyn(elf_native_t* arm32, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs)
+{
+ uint64_t cs_base = rx_base + cs->offset;
+
+// arm32->gnu_version_r->sh.sh_addr = rx_base + arm32->gnu_version_r->offset;
+
+ arm32->rela_plt->sh.sh_addr = rx_base + arm32->rela_plt->offset;
+ arm32->dynamic->sh.sh_addr = rw_base + arm32->dynamic->offset;
+ arm32->got_plt->sh.sh_addr = rw_base + arm32->got_plt->offset;
+ arm32->interp->sh.sh_addr = rx_base + arm32->interp->offset;
+ arm32->plt->sh.sh_addr = rx_base + arm32->plt->offset;
+
+ scf_loge("rw_base: %#lx, offset: %#lx\n", rw_base, arm32->got_plt->offset);
+ scf_loge("got_addr: %#x\n", arm32->got_plt->sh.sh_addr);
+
+ Elf32_Rela* r;
+ Elf32_Rela* rela_plt = (Elf32_Rela*)arm32->rela_plt->data;
+ Elf32_Dyn* dtags = (Elf32_Dyn* )arm32->dynamic->data;
+ Elf32_Sym* dynsym = (Elf32_Sym* )arm32->dynsym->data;
+ uint32_t* got_plt = (uint32_t* )arm32->got_plt->data;
+ uint32_t* plt = (uint32_t* )arm32->plt->data;
+
+ uint64_t got_addr = arm32->got_plt->sh.sh_addr;
+ uint64_t plt_addr = arm32->plt->sh.sh_addr;
+ int32_t offset = got_addr - plt_addr;
+
+ got_plt[0] = arm32->dynamic->sh.sh_addr;
+ got_plt[1] = 0;
+ got_plt[2] = 0;
+ got_plt[3] = arm32->plt->sh.sh_addr;
+ got_plt += 4;
+ got_addr +=16;
+
+ scf_loge("got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", got_addr, plt_addr, offset, offset);
+
+ plt[4] = offset - 16;
+
+ plt_addr += sizeof(arm32_plt_lazy);
+ plt += sizeof(arm32_plt_lazy) / sizeof(arm32_plt_lazy[0]);
+
+ int i;
+ for (i = 0; i < arm32->dynsyms->size; i++) {
+ rela_plt[i].r_offset = got_addr;
+ rela_plt[i].r_addend = 0;
+ rela_plt[i].r_info = ELF32_R_INFO(i + 1, R_ARM_JUMP_SLOT);
+
+ *got_plt = arm32->plt->sh.sh_addr;
+
+ offset = got_addr - plt_addr - 8; // 'pc = current + 8'
+
+ scf_loge("i: %d, got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", i, got_addr, plt_addr, offset, offset);
+
+ scf_logw("got_plt[%d]: %#x\n", i, *got_plt);
+
+ if (offset > 0xfffffff) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ plt[0] |= (offset >> 20) & 0xff;
+ plt[1] |= (offset >> 12) & 0xff;
+ plt[2] |= offset & 0xfff;
+
+ plt += sizeof(arm32_plt) / sizeof(arm32_plt[0]);
+ plt_addr += sizeof(arm32_plt);
+ got_addr += 4;
+ got_plt++;
+ }
+
+ for (i = 0; i < arm32->dyn_relas->size; i++) {
+ r = arm32->dyn_relas->data[i];
+
+ int sym_idx = ELF32_R_SYM(r->r_info);
+ assert(sym_idx > 0);
+
+ assert(ELF32_R_TYPE(r->r_info) == R_ARM_CALL);
+
+ uint64_t plt_addr = arm32->plt->sh.sh_addr + sizeof(arm32_plt_lazy) + (sym_idx - 1) * sizeof(arm32_plt);
+
+ int32_t offset = plt_addr - (cs_base + r->r_offset) + r->r_addend - 8; // 'pc' is 'current + 8'
+
+ assert(0 == (offset & 0x3));
+
+ offset >>= 2;
+
+ if (offset > 0x7fffff || offset < -0x7fffff) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ offset &= 0xffffff;
+ offset |= (0xeb << 24);
+
+ *(uint32_t*)(cs->data + r->r_offset) = offset;
+ }
+
+ for (i = arm32->dyn_needs->size; i < arm32->dynamic->data_len / sizeof(Elf32_Dyn); i++) {
+
+ elf_section_t* s;
+
+ switch (dtags[i].d_tag) {
+
+ case DT_SYMTAB:
+ case DT_STRTAB:
+ case DT_JMPREL:
+ s = arm32->sections->data[dtags[i].d_un.d_ptr];
+
+ dtags[i].d_un.d_ptr = s->offset + rx_base;
+ s->sh.sh_addr = s->offset + rx_base;
+ break;
+
+ case DT_PLTGOT:
+ s = arm32->sections->data[dtags[i].d_un.d_ptr];
+
+ dtags[i].d_un.d_ptr = s->offset + rw_base;
+ s->sh.sh_addr = s->offset + rw_base;
+ break;
+ default:
+ break;
+ };
+ }
+
+ return 0;
+}
+
+int __arm32_elf_write_phdr(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs)
+{
+ // write program header
+
+ Elf32_Phdr ph_phdr = {0};
+
+ ph_phdr.p_type = PT_PHDR;
+ ph_phdr.p_flags = PF_R;
+ ph_phdr.p_offset = offset;
+ ph_phdr.p_vaddr = rx_base + offset;
+ ph_phdr.p_paddr = ph_phdr.p_vaddr;
+ ph_phdr.p_filesz = sizeof(Elf32_Phdr) * nb_phdrs;
+ ph_phdr.p_memsz = ph_phdr.p_filesz;
+ ph_phdr.p_align = 0x8;
+
+ fwrite(&ph_phdr, sizeof(ph_phdr), 1, elf->fp);
+ return 0;
+}
+
+int __arm32_elf_write_interp(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len)
+{
+ Elf32_Phdr ph_interp = {0};
+
+ ph_interp.p_type = PT_INTERP;
+ ph_interp.p_flags = PF_R;
+ ph_interp.p_offset = offset;
+ ph_interp.p_vaddr = rx_base + offset;
+ ph_interp.p_paddr = ph_interp.p_vaddr;
+ ph_interp.p_filesz = len;
+ ph_interp.p_memsz = ph_interp.p_filesz;
+ ph_interp.p_align = 0x1;
+
+ fwrite(&ph_interp, sizeof(ph_interp), 1, elf->fp);
+ return 0;
+}
+
+int __arm32_elf_write_text(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len)
+{
+ Elf32_Phdr ph_text = {0};
+
+ ph_text.p_type = PT_LOAD;
+ ph_text.p_flags = PF_R | PF_X;
+ ph_text.p_offset = 0;
+ ph_text.p_vaddr = rx_base + offset;
+ ph_text.p_paddr = ph_text.p_vaddr;
+ ph_text.p_filesz = len;
+ ph_text.p_memsz = ph_text.p_filesz;
+ ph_text.p_align = 0x200000;
+
+ fwrite(&ph_text, sizeof(ph_text), 1, elf->fp);
+ return 0;
+}
+
+int __arm32_elf_write_rodata(scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len)
+{
+ Elf32_Phdr ph_rodata = {0};
+
+ ph_rodata.p_type = PT_LOAD;
+ ph_rodata.p_flags = PF_R;
+ ph_rodata.p_offset = offset;
+ ph_rodata.p_vaddr = r_base + offset;
+ ph_rodata.p_paddr = ph_rodata.p_vaddr;
+ ph_rodata.p_filesz = len;
+ ph_rodata.p_memsz = ph_rodata.p_filesz;
+ ph_rodata.p_align = 0x200000;
+
+ fwrite(&ph_rodata, sizeof(ph_rodata), 1, elf->fp);
+ return 0;
+}
+
+int __arm32_elf_write_data(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len)
+{
+ Elf32_Phdr ph_data = {0};
+
+ ph_data.p_type = PT_LOAD;
+ ph_data.p_flags = PF_R | PF_W;
+ ph_data.p_offset = offset;
+ ph_data.p_vaddr = rw_base + offset;
+ ph_data.p_paddr = ph_data.p_vaddr;
+ ph_data.p_filesz = len;
+ ph_data.p_memsz = ph_data.p_filesz;
+ ph_data.p_align = 0x200000;
+
+ fwrite(&ph_data, sizeof(ph_data), 1, elf->fp);
+ return 0;
+}
+
+int __arm32_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len)
+{
+ Elf32_Phdr ph_dynamic = {0};
+
+ ph_dynamic.p_type = PT_DYNAMIC;
+ ph_dynamic.p_flags = PF_R | PF_W;
+ ph_dynamic.p_offset = offset;
+ ph_dynamic.p_vaddr = rw_base + offset;
+ ph_dynamic.p_paddr = ph_dynamic.p_vaddr;
+ ph_dynamic.p_filesz = len;
+ ph_dynamic.p_memsz = ph_dynamic.p_filesz;
+ ph_dynamic.p_align = 0x8;
+
+ fwrite(&ph_dynamic, sizeof(Elf32_Phdr), 1, elf->fp);
+ return 0;
+}
+
#define ELF_READ_RELAS(sname) \
do { \
int ret = scf_elf_read_relas(ef->elf, ef->sname##_relas, ".rela."#sname); \
- if (ret < 0 && ret != -404) { \
- scf_loge("\n"); \
- return ret; \
+ if (ret < 0) { \
+ if (ret != -404) { \
+ scf_loge("\n"); \
+ return ret; \
+ } \
+ \
+ ret = scf_elf_read_relas(ef->elf, ef->sname##_relas, ".rel."#sname); \
+ if (ret < 0 && ret != -404) { \
+ scf_loge("\n"); \
+ return ret; \
+ } \
} \
} while(0);
return ret;
}
-static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int nb_syms)
+static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int nb_syms, const int bits)
{
scf_elf_rela_t* rela;
scf_elf_rela_t* rela2;
rela2 = src->data[j];
rela2->r_offset += offset;
- rela2->r_info = ELF64_R_INFO(ELF64_R_SYM(rela2->r_info) + nb_syms, ELF64_R_TYPE(rela2->r_info));
+
+ if (64 == bits)
+ rela2->r_info = ELF64_R_INFO(ELF64_R_SYM(rela2->r_info) + nb_syms, ELF64_R_TYPE(rela2->r_info));
+ else
+ rela2->r_info = ELF32_R_INFO(ELF32_R_SYM(rela2->r_info) + nb_syms, ELF32_R_TYPE(rela2->r_info));
rela = calloc(1, sizeof(scf_elf_rela_t));
if (!rela)
return -ENOMEM;
}
+ scf_logw("j: %d, nb_syms: %d:%ld, sym: %s\n", j, nb_syms, ELF32_R_SYM(rela2->r_info), rela2->name);
+
rela->r_offset = rela2->r_offset;
rela->r_info = rela2->r_info;
rela->r_addend = rela2->r_addend;
return -ENOMEM;
}
+ scf_loge("sym: %d, %s\n", exec->syms->size, sym->name);
+
if (scf_vector_add(exec->syms, sym) < 0) {
scf_loge("\n");
return -ENOMEM;
return 0;
}
-static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj)
+static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj, const int bits)
{
int nb_syms = exec->syms->size;
#define MERGE_RELAS(dst, src, offset) \
do { \
- int ret = merge_relas(dst, src, offset, nb_syms); \
+ int ret = merge_relas(dst, src, offset, nb_syms, bits); \
if (ret < 0) { \
scf_loge("\n"); \
return ret; \
static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const char* arch)
{
int nb_syms = 0;
+ int bits;
int i;
+
+ if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja"))
+ bits = 64;
+ else
+ bits = 32;
+
for (i = 0; i < nb_inputs; i++) {
scf_elf_sym_t* sym;
return -1;
}
- int ret = merge_obj(exec, obj);
+ scf_loge("i: %d, input: %s\n", i, inputs[i]);
+
+ int ret = merge_obj(exec, obj, bits);
if (ret < 0) {
scf_loge("\n");
return -1;
return 0;
}
-static int _find_sym(scf_elf_sym_t** psym, scf_elf_rela_t* rela, scf_vector_t* symbols)
+static int _find_sym(scf_elf_sym_t** psym, scf_elf_rela_t* rela, scf_vector_t* symbols, const int bits)
{
scf_elf_sym_t* sym;
scf_elf_sym_t* sym2;
- int sym_idx = ELF64_R_SYM(rela->r_info);
+ int sym_idx;
int j;
+ if (64 == bits)
+ sym_idx = ELF64_R_SYM(rela->r_info);
+ else
+ sym_idx = ELF32_R_SYM(rela->r_info);
+
assert(sym_idx >= 1);
assert(sym_idx - 1 < symbols->size);
{
scf_elf_file_t* obj = NULL;
+ int bits;
+ if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja"))
+ bits = 64;
+ else
+ bits = 32;
+
int ret = __scf_elf_file_open(&obj);
if (ret < 0) {
scf_loge("\n");
return -1;
}
- ret = merge_obj(exec, obj);
+ ret = merge_obj(exec, obj, bits);
if (ret < 0) {
scf_loge("\n");
return -1;
scf_vector_t* dlls = scf_vector_alloc();
int i;
+ int bits;
+ if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja"))
+ bits = 64;
+ else
+ bits = 32;
+
for (i = 0; i < nb_afiles; i++) {
if (scf_ar_file_open(&ar, afiles[i]) < 0) {
rela = exec->text_relas->data[i];
sym = NULL;
- int sym_idx = _find_sym(&sym, rela, exec->syms);
+ int sym_idx = _find_sym(&sym, rela, exec->syms, bits);
if (sym_idx >= 0) {
i++;
continue;
}
- sym_idx = ELF64_R_SYM(rela->r_info);
- sym = exec->syms->data[sym_idx - 1];
+ if (64 == bits)
+ sym_idx = ELF64_R_SYM(rela->r_info);
+ else
+ sym_idx = ELF32_R_SYM(rela->r_info);
+
+ sym = exec->syms->data[sym_idx - 1];
uint32_t offset = 0;
uint32_t size = 0;
scf_vector_del(exec->text_relas, rela);
scf_vector_add(exec->rela_plt, rela);
- rela->r_info = ELF64_R_INFO(j + 1, ELF64_R_TYPE(rela->r_info));
+ if (64 == bits)
+ rela->r_info = ELF64_R_INFO(j + 1, ELF64_R_TYPE(rela->r_info));
+ else
+ rela->r_info = ELF32_R_INFO(j + 1, ELF32_R_TYPE(rela->r_info));
scf_loge("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld\n", j,
sym->name, rela->r_offset, rela->r_addend);
rela = exec->data_relas->data[i];
sym = NULL;
- int sym_idx = _find_sym(&sym, rela, exec->syms);
+ int sym_idx = _find_sym(&sym, rela, exec->syms, bits);
if (sym_idx >= 0)
continue;
- sym_idx = ELF64_R_SYM(rela->r_info);
- sym = exec->syms->data[sym_idx - 1];
+ if (64 == bits)
+ sym_idx = ELF64_R_SYM(rela->r_info);
+ else
+ sym_idx = ELF32_R_SYM(rela->r_info);
+
+ sym = exec->syms->data[sym_idx - 1];
uint32_t offset = 0;
uint32_t size = 0;
for (j = 0; j < so->rela_plt->size; j++) {
rela = so->rela_plt->data[j];
- sym_idx = ELF64_R_SYM(rela->r_info);
+ if (64 == bits)
+ sym_idx = ELF64_R_SYM(rela->r_info);
+ else
+ sym_idx = ELF32_R_SYM(rela->r_info);
if (sym_idx <= 0)
continue;
int elf_find_sym (elf_sym_t** psym, Elf64_Rela* rela, scf_vector_t* symbols);
void elf_process_syms(elf_native_t* native, uint32_t cs_index);
+int elf32_find_sym (elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols);
+void elf32_process_syms(elf_native_t* native, uint32_t cs_index);
+
int elf_write_sections(scf_elf_context_t* elf);
int elf_write_shstrtab(scf_elf_context_t* elf);
int elf_write_symtab (scf_elf_context_t* elf);
--- /dev/null
+#include"scf_elf_native32.h"
+#include"scf_elf_link.h"
+
+int elf32_open(scf_elf_context_t* elf)
+{
+ if (!elf)
+ return -EINVAL;
+
+ elf_native_t* e = calloc(1, sizeof(elf_native_t));
+ if (!e)
+ return -ENOMEM;
+
+ e->sh_null.sh_type = SHT_NULL;
+
+ e->sh_symtab.sh_type = SHT_SYMTAB;
+ e->sh_symtab.sh_flags = 0;
+ e->sh_symtab.sh_addralign = 4;
+
+ e->sh_strtab.sh_type = SHT_STRTAB;
+ e->sh_strtab.sh_flags = 0;
+ e->sh_strtab.sh_addralign = 1;
+
+ e->sh_shstrtab.sh_type = SHT_STRTAB;
+ e->sh_shstrtab.sh_flags = 0;
+ e->sh_shstrtab.sh_addralign = 1;
+
+ e->sections = scf_vector_alloc();
+ e->symbols = scf_vector_alloc();
+
+ elf->priv = e;
+ return 0;
+}
+
+int elf32_close(scf_elf_context_t* elf)
+{
+ elf_native_t* e = elf->priv;
+
+ if (e) {
+ free(e);
+ e = NULL;
+ }
+ return 0;
+}
+
+int elf32_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name)
+{
+ elf_sym_t* xsym;
+ elf_native_t* e = elf->priv;
+ scf_vector_t* vec = NULL;
+
+ if (!strcmp(sh_name, ".symtab"))
+ vec = e->symbols;
+
+ else if (!strcmp(sh_name, ".dynsym")) {
+
+ if (!e->dynsyms) {
+ e->dynsyms = scf_vector_alloc();
+ if (!e->dynsyms)
+ return -ENOMEM;
+ }
+
+ vec = e->dynsyms;
+ } else
+ return -EINVAL;
+
+ xsym = calloc(1, sizeof(elf_sym_t));
+ if (!xsym)
+ return -ENOMEM;
+
+ if (sym->name)
+ xsym->name = scf_string_cstr(sym->name);
+ else
+ xsym->name = NULL;
+
+ xsym->sym.st_size = sym->st_size;
+ xsym->sym.st_value = sym->st_value;
+ xsym->sym.st_shndx = sym->st_shndx;
+ xsym->sym.st_info = sym->st_info;
+
+ xsym->dyn_flag = sym->dyn_flag;
+
+ int ret = scf_vector_add(vec, xsym);
+ if (ret < 0) {
+ scf_string_free(xsym->name);
+ free(xsym);
+ return ret;
+ }
+
+ xsym->index = vec->size;
+ return 0;
+}
+
+int elf32_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section)
+{
+ elf_native_t* e = elf->priv;
+
+ elf_section_t* s;
+ elf_section_t* s2;
+ int i;
+
+ if (section->index > 0) {
+
+ for (i = e->sections->size - 1; i >= 0; i--) {
+ s = e->sections->data[i];
+
+ if (s->index == section->index) {
+ scf_loge("s->index: %d\n", s->index);
+ return -1;
+ }
+ }
+ }
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(section->name);
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->sh.sh_type = section->sh_type;
+ s->sh.sh_flags = section->sh_flags;
+ s->sh.sh_addralign = section->sh_addralign;
+
+ if (section->data && section->data_len > 0) {
+ s->data = malloc(section->data_len);
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+
+ memcpy(s->data, section->data, section->data_len);
+ s->data_len = section->data_len;
+ }
+
+ if (scf_vector_add(e->sections, s) < 0) {
+ if (s->data)
+ free(s->data);
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+
+ if (0 == section->index)
+ s->index = e->sections->size;
+ else {
+ s->index = section->index;
+
+ for (i = e->sections->size - 2; i >= 0; i--) {
+ s2 = e->sections->data[i];
+
+ if (s2->index < s->index)
+ break;
+
+ e->sections->data[i + 1] = s2;
+ }
+
+ e->sections->data[i + 1] = s;
+ }
+
+ return s->index;
+}
+
+int elf32_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas)
+{
+ if (relas->size <= 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ elf_native_t* e = elf->priv;
+
+ elf_section_t* s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ s->name = scf_string_cstr(section->name);
+ if (!s->name) {
+ free(s);
+ return -ENOMEM;
+ }
+
+ s->index = e->sections->size + 1;
+ s->sh.sh_type = SHT_RELA;
+ s->sh.sh_flags = SHF_INFO_LINK;
+ s->sh.sh_addralign = section->sh_addralign;
+ s->sh.sh_link = section->sh_link;
+ s->sh.sh_info = section->sh_info;
+ s->sh.sh_entsize = sizeof(Elf32_Rela);
+
+ s->data_len = sizeof(Elf32_Rela) * relas->size;
+
+ s->data = malloc(s->data_len);
+ if (!s->data) {
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+
+ Elf32_Rela* pr = (Elf32_Rela*) s->data;
+
+ int i;
+ for (i = 0; i < relas->size; i++) {
+
+ scf_elf_rela_t* r = relas->data[i];
+
+ pr[i].r_offset = r->r_offset;
+ pr[i].r_info = r->r_info;
+ pr[i].r_addend = r->r_addend;
+ }
+
+ if (scf_vector_add(e->sections, s) < 0) {
+ free(s->data);
+ scf_string_free(s->name);
+ free(s);
+ return -ENOMEM;
+ }
+ return s->index;
+}
+
+int elf32_read_shstrtab(scf_elf_context_t* elf)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!elf->fp)
+ return -EINVAL;
+
+ int ret = fseek(elf->fp, elf->start, SEEK_SET);
+ if (ret < 0)
+ return ret;
+
+ ret = fread(&e->eh, sizeof(Elf32_Ehdr), 1, elf->fp);
+ if (ret != 1)
+ return -1;
+
+ if (ELFMAG0 != e->eh.e_ident[EI_MAG0]
+ || ELFMAG1 != e->eh.e_ident[EI_MAG1]
+ || ELFMAG2 != e->eh.e_ident[EI_MAG2]
+ || ELFMAG3 != e->eh.e_ident[EI_MAG3]) {
+
+ scf_loge("not elf file\n");
+ return -1;
+ }
+
+ long offset = e->eh.e_shoff + e->eh.e_shentsize * e->eh.e_shstrndx;
+ fseek(elf->fp, elf->start + offset, SEEK_SET);
+
+ ret = fread(&e->sh_shstrtab, sizeof(Elf32_Shdr), 1, elf->fp);
+ if (ret != 1)
+ return -1;
+
+ if (!e->sh_shstrtab_data) {
+ e->sh_shstrtab_data = scf_string_alloc();
+ if (!e->sh_shstrtab_data)
+ return -ENOMEM;
+ }
+
+ void* p = realloc(e->sh_shstrtab_data->data, e->sh_shstrtab.sh_size);
+ if (!p)
+ return -ENOMEM;
+ e->sh_shstrtab_data->data = p;
+ e->sh_shstrtab_data->len = e->sh_shstrtab.sh_size;
+ e->sh_shstrtab_data->capacity = e->sh_shstrtab.sh_size;
+
+ fseek(elf->fp, elf->start + e->sh_shstrtab.sh_offset, SEEK_SET);
+
+ ret = fread(e->sh_shstrtab_data->data, e->sh_shstrtab.sh_size, 1, elf->fp);
+ if (ret != 1)
+ return -1;
+#if 0
+ int i;
+ for (i = 0; i < e->sh_shstrtab.sh_size; i++) {
+
+ unsigned char c = e->sh_shstrtab_data->data[i];
+ if (c)
+ printf("%c", c);
+ else
+ printf("\n");
+ }
+ printf("\n");
+#endif
+ return 0;
+}
+
+static int __elf_read_section_data(scf_elf_context_t* elf, elf_section_t* s)
+{
+ s->data_len = s->sh.sh_size;
+
+ if (s->sh.sh_size > 0) {
+
+ s->data = malloc(s->sh.sh_size);
+ if (!s->data)
+ return -1;
+
+ fseek(elf->fp, elf->start + s->sh.sh_offset, SEEK_SET);
+
+ int ret = fread(s->data, s->data_len, 1, elf->fp);
+ if (ret != 1) {
+ free(s->data);
+ s->data = NULL;
+ s->data_len = 0;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int __elf_read_section_by_index(scf_elf_context_t* elf, elf_section_t** psection, const int index)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ if (!e->sh_shstrtab_data) {
+
+ int ret = elf32_read_shstrtab(elf);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (index >= e->eh.e_shnum)
+ return -EINVAL;
+
+ elf_section_t* s;
+ int i;
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ if (index == s->index) {
+
+ if (s->data || __elf_read_section_data(elf, s) == 0) {
+ *psection = s;
+ return 0;
+ }
+ return -1;
+ }
+ }
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ long offset = e->eh.e_shoff + e->eh.e_shentsize * index;
+ fseek(elf->fp, elf->start + offset, SEEK_SET);
+
+ int ret = fread(&s->sh, sizeof(Elf32_Shdr), 1, elf->fp);
+ if (ret != 1) {
+ free(s);
+ return -1;
+ }
+
+ s->index = index;
+ s->name = scf_string_cstr(e->sh_shstrtab_data->data + s->sh.sh_name);
+ if (!s->name) {
+ free(s);
+ return -1;
+ }
+
+ ret = scf_vector_add(e->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s);
+ return -1;
+ }
+
+ if (__elf_read_section_data(elf, s) == 0) {
+ *psection = s;
+ return 0;
+ }
+ return -1;
+}
+
+int elf32_read_phdrs(scf_elf_context_t* elf, scf_vector_t* phdrs)
+{
+ elf_native_t* e = elf->priv;
+ scf_elf_phdr_t* ph;
+ Elf32_Ehdr eh;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ if (!elf->fp)
+ return -EINVAL;
+
+ int ret = fseek(elf->fp, elf->start, SEEK_SET);
+ if (ret < 0)
+ return ret;
+
+ ret = fread(&eh, sizeof(Elf32_Ehdr), 1, elf->fp);
+ if (ret != 1)
+ return -1;
+
+ if (ELFMAG0 != eh.e_ident[EI_MAG0]
+ || ELFMAG1 != eh.e_ident[EI_MAG1]
+ || ELFMAG2 != eh.e_ident[EI_MAG2]
+ || ELFMAG3 != eh.e_ident[EI_MAG3]) {
+
+ scf_loge("not elf file\n");
+ return -1;
+ }
+
+ fseek(elf->fp, elf->start + eh.e_phoff, SEEK_SET);
+
+ int i;
+ for (i = 0; i < eh.e_phnum; i++) {
+
+ ph = calloc(1, sizeof(scf_elf_phdr_t));
+ if (!ph)
+ return -ENOMEM;
+
+ ret = fread(&ph->ph, sizeof(Elf32_Phdr), 1, elf->fp);
+
+ if (ret != 1) {
+ free(ph);
+ return -1;
+ }
+
+ if (scf_vector_add(phdrs, ph) < 0) {
+ free(ph);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static int __elf_read_section(scf_elf_context_t* elf, elf_section_t** psection, const char* name)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ if (!e->sh_shstrtab_data) {
+
+ int ret = elf32_read_shstrtab(elf);
+ if (ret < 0)
+ return ret;
+ }
+
+ elf_section_t* s;
+ int i;
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ if (!scf_string_cmp_cstr(s->name, name)) {
+
+ if (s->data || __elf_read_section_data(elf, s) == 0) {
+ *psection = s;
+ return 0;
+ }
+ return -1;
+ }
+ }
+
+ int j;
+ for (j = 1; j < e->eh.e_shnum; j++) {
+
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ if (j == s->index)
+ break;
+ }
+
+ if (i < e->sections->size)
+ continue;
+
+ s = calloc(1, sizeof(elf_section_t));
+ if (!s)
+ return -ENOMEM;
+
+ long offset = e->eh.e_shoff + e->eh.e_shentsize * j;
+ fseek(elf->fp, elf->start + offset, SEEK_SET);
+
+ int ret = fread(&s->sh, sizeof(Elf32_Shdr), 1, elf->fp);
+ if (ret != 1) {
+ free(s);
+ return -1;
+ }
+
+ s->index = j;
+ s->name = scf_string_cstr(e->sh_shstrtab_data->data + s->sh.sh_name);
+ if (!s->name) {
+ free(s);
+ return -1;
+ }
+
+ ret = scf_vector_add(e->sections, s);
+ if (ret < 0) {
+ scf_string_free(s->name);
+ free(s);
+ return -1;
+ }
+
+ if (!scf_string_cmp_cstr(s->name, name))
+ break;
+ }
+
+ if (j < e->eh.e_shnum) {
+
+ if (!s->data) {
+ if (__elf_read_section_data(elf, s) == 0) {
+ *psection = s;
+ return 0;
+ }
+
+ return -1;
+ } else
+ assert(s->data_len == s->sh.sh_size);
+
+ *psection = s;
+ return 0;
+ }
+
+ return -404;
+}
+
+int elf32_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ elf_section_t* symtab = NULL;
+ elf_section_t* strtab = NULL;
+
+ char* sh_strtab_name = NULL;
+
+ if (!strcmp(sh_name, ".symtab"))
+ sh_strtab_name = ".strtab";
+
+ else if (!strcmp(sh_name, ".dynsym"))
+ sh_strtab_name = ".dynstr";
+ else
+ return -EINVAL;
+
+ int ret = __elf_read_section(elf, &symtab, sh_name);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -1;
+ }
+
+ ret = __elf_read_section(elf, &strtab, sh_strtab_name);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -1;
+ }
+
+ assert(symtab->data_len % sizeof(Elf32_Sym) == 0);
+
+ scf_loge("0: syms->size: %d, %ld\n", syms->size, symtab->data_len / sizeof(Elf32_Sym));
+
+ scf_elf_sym_t* esym;
+ Elf32_Sym* sym;
+ int i;
+ int j = 0;
+ for (i = 0; i < symtab->data_len; i += sizeof(Elf32_Sym)) {
+
+ sym = (Elf32_Sym*)(symtab->data + i);
+
+ assert(sym->st_name < strtab->data_len);
+
+ if (STT_NOTYPE == sym->st_info && 0 == i) {
+ j++;
+ continue;
+ }
+
+ esym = calloc(1, sizeof(scf_elf_sym_t));
+ if (!esym)
+ return -ENOMEM;
+
+ esym->name = strtab->data + sym->st_name;
+ esym->st_size = sym->st_size;
+ esym->st_value = sym->st_value;
+ esym->st_shndx = sym->st_shndx;
+ esym->st_info = sym->st_info;
+
+ if (scf_vector_add(syms, esym) < 0) {
+ free(esym);
+ return -ENOMEM;
+ }
+ }
+
+ scf_loge("1: j: %d, syms->size: %d, %ld\n", j, syms->size, symtab->data_len / sizeof(Elf32_Sym));
+
+ return 0;
+}
+
+int elf32_add_dyn_need(scf_elf_context_t* elf, const char* soname)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ if (!e->dyn_needs) {
+ e->dyn_needs = scf_vector_alloc();
+ if (!e->dyn_needs)
+ return -ENOMEM;
+ }
+
+ scf_string_t* s = scf_string_cstr(soname);
+ if (!s)
+ return -ENOMEM;
+
+ if (scf_vector_add(e->dyn_needs, s) < 0) {
+ scf_string_free(s);
+ return -ENOMEM;
+ }
+
+ scf_loge("soname: %s\n", soname);
+ return 0;
+}
+
+int elf32_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ if (!e->dyn_relas) {
+ e->dyn_relas = scf_vector_alloc();
+ if (!e->dyn_relas)
+ return -ENOMEM;
+ }
+
+ Elf32_Rela* r = calloc(1, sizeof(Elf32_Rela));
+ if (!r)
+ return -ENOMEM;
+
+ if (scf_vector_add(e->dyn_relas, r) < 0) {
+ free(r);
+ return -ENOMEM;
+ }
+
+ r->r_offset = rela->r_offset;
+ r->r_addend = rela->r_addend;
+ r->r_info = rela->r_info;
+
+ return 0;
+}
+
+int elf32_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name)
+{
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ scf_elf_rela_t* erela;
+ elf_section_t* sh_rela = NULL;
+ elf_section_t* symtab = NULL;
+ elf_section_t* strtab = NULL;
+ Elf32_Rela* rela;
+ Elf32_Rel* rel;
+ Elf32_Sym* sym;
+
+ char* symtab_name = NULL;
+ char* strtab_name = NULL;
+ int i;
+
+ int ret = __elf_read_section(elf, &sh_rela, sh_name);
+ if (ret < 0)
+ return ret;
+
+ scf_loge("sh_rela: %u\n", sh_rela->sh.sh_link);
+
+ ret = __elf_read_section_by_index(elf, &symtab, sh_rela->sh.sh_link);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
+
+ ret = __elf_read_section_by_index(elf, &strtab, symtab->sh.sh_link);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
+
+
+ if (SHT_RELA == sh_rela->sh.sh_type) {
+
+ assert(sh_rela->data_len % sizeof(Elf32_Rela) == 0);
+
+ for (i = 0; i < sh_rela->data_len; i += sizeof(Elf32_Rela)) {
+
+ rela = (Elf32_Rela*)(sh_rela->data + i);
+
+ int sym_idx = ELF32_R_SYM(rela->r_info);
+
+ assert(sym_idx < symtab->data_len / sizeof(Elf32_Sym));
+
+ sym = (Elf32_Sym*)(symtab->data + sym_idx * sizeof(Elf32_Sym));
+
+ assert(sym->st_name < strtab->data_len);
+
+ erela = calloc(1, sizeof(scf_elf_rela_t));
+ if (!erela)
+ return -ENOMEM;
+
+ erela->name = strtab->data + sym->st_name;
+ erela->r_offset = rela->r_offset;
+ erela->r_info = rela->r_info;
+ erela->r_addend = rela->r_addend;
+
+ if (scf_vector_add(relas, erela) < 0) {
+ scf_loge("\n");
+ free(erela);
+ return -ENOMEM;
+ }
+ }
+
+ } else {
+ assert(sh_rela->data_len % sizeof(Elf32_Rel) == 0);
+
+ for (i = 0; i < sh_rela->data_len; i += sizeof(Elf32_Rel)) {
+
+ rel = (Elf32_Rel*)(sh_rela->data + i);
+
+ int sym_idx = ELF32_R_SYM(rel->r_info);
+
+ assert(sym_idx < symtab->data_len / sizeof(Elf32_Sym));
+
+ sym = (Elf32_Sym*)(symtab->data + sym_idx * sizeof(Elf32_Sym));
+
+ assert(sym->st_name < strtab->data_len);
+
+ erela = calloc(1, sizeof(scf_elf_rela_t));
+ if (!erela)
+ return -ENOMEM;
+
+ erela->name = strtab->data + sym->st_name;
+ erela->r_offset = rel->r_offset;
+ erela->r_info = rel->r_info;
+
+ if (scf_vector_add(relas, erela) < 0) {
+ scf_loge("\n");
+ free(erela);
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int elf32_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name)
+{
+ elf_section_t* s = NULL;
+ scf_elf_section_t* s2;
+ elf_native_t* e = elf->priv;
+
+ if (!e || !elf->fp)
+ return -1;
+
+ int ret = __elf_read_section(elf, &s, name);
+ if (ret < 0)
+ return ret;
+
+ s2 = calloc(1, sizeof(scf_elf_section_t));
+ if (!s2)
+ return -ENOMEM;
+
+ s2->index = s->index;
+ s2->name = s->name->data;
+ s2->data = s->data;
+ s2->data_len = s->data_len;
+ s2->sh_type = s->sh.sh_type;
+ s2->sh_flags = s->sh.sh_flags;
+ s2->sh_addralign = s->sh.sh_addralign;
+
+ *psection = s2;
+ return 0;
+}
+
+int elf32_write_symtab(scf_elf_context_t* elf)
+{
+ elf_native_t* e = elf->priv;
+ Elf32_Sym s0 = {0};
+ elf_sym_t* s;
+
+ s0.st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE);
+
+ fwrite(&s0, sizeof(s0), 1, elf->fp); // entry index 0 in symtab is NOTYPE
+
+ int i;
+ for (i = 0; i < e->symbols->size; i++) {
+ s = e->symbols->data[i];
+
+ fwrite(&s->sym, sizeof(s->sym), 1, elf->fp);
+ }
+
+ return 0;
+}
+
+int elf32_write_strtab(scf_elf_context_t* elf)
+{
+ elf_sym_t* s;
+ elf_native_t* e = elf->priv;
+ uint8_t c = 0;
+
+ fwrite(&c, sizeof(c), 1, elf->fp);
+
+ int i;
+ for (i = 0; i < e->symbols->size; i++) {
+ s = e->symbols->data[i];
+
+ if (s->name)
+ fwrite(s->name->data, s->name->len + 1, 1, elf->fp);
+ }
+
+ return 0;
+}
+
+int elf32_write_shstrtab(scf_elf_context_t* elf)
+{
+ elf_section_t* s;
+ elf_native_t* e = elf->priv;
+ uint8_t c = 0;
+ char* str = ".symtab\0.strtab\0.shstrtab\0";
+ int len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3;
+
+ fwrite(&c, sizeof(c), 1, elf->fp);
+
+ int i;
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ fwrite(s->name->data, s->name->len + 1, 1, elf->fp);
+ }
+
+ fwrite(str, len, 1, elf->fp);
+ return 0;
+}
+
+int elf32_write_sections(scf_elf_context_t* elf)
+{
+ elf_section_t* s;
+ elf_native_t* e = elf->priv;
+
+ int i;
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ scf_loge("sh->name: %s, data: %p, len: %d\n", s->name->data, s->data, s->data_len);
+
+ if (s->data && s->data_len > 0)
+ fwrite(s->data, s->data_len, 1, elf->fp);
+ }
+
+ return 0;
+}
+
+int elf32_write_rel(scf_elf_context_t* elf, uint16_t e_machine)
+{
+ elf_native_t* e = elf->priv;
+ elf_section_t* s;
+ elf_sym_t* sym;
+
+ int nb_sections = 1 + e->sections->size + 1 + 1 + 1;
+ uint64_t shstrtab = 1;
+ uint64_t strtab = 1;
+ uint64_t symtab = sizeof(Elf32_Sym ) * (e->symbols->size + 1);
+ Elf32_Off offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Shdr) * nb_sections;
+
+ // write elf header
+ elf_header(&e->eh, ET_REL, e_machine, 0, 0, 0, nb_sections, nb_sections - 1);
+ fwrite (&e->eh, sizeof(e->eh), 1, elf->fp);
+
+ // write null section header
+ fwrite(&e->sh_null, sizeof(e->sh_null), 1, elf->fp);
+
+ // write user's section header
+ int i;
+ for (i = 0; i < e->sections->size; i++) {
+ s = e->sections->data[i];
+
+ if (SHT_RELA == s->sh.sh_type)
+ s->sh.sh_link = nb_sections - 3;
+
+ section_header(&s->sh, shstrtab, 0, offset,
+ s->data_len,
+ s->sh.sh_link,
+ s->sh.sh_info,
+ s->sh.sh_entsize);
+
+ s->sh.sh_addralign = 4;
+
+ offset += s->data_len;
+ shstrtab += s->name->len + 1;
+
+ fwrite(&s->sh, sizeof(s->sh), 1, elf->fp);
+ }
+
+ // set user's symbols' name
+ int local_syms = 1;
+
+ for (i = 0; i < e->symbols->size; i++) {
+ sym = e->symbols->data[i];
+
+ if (sym->name) {
+ sym->sym.st_name = strtab;
+ strtab += sym->name->len + 1;
+ } else
+ sym->sym.st_name = 0;
+
+ if (STB_LOCAL == ELF32_ST_BIND(sym->sym.st_info))
+ local_syms++;
+ }
+
+ scf_loge("e->symbols->size: %d\n", e->symbols->size);
+ // .symtab header
+ section_header(&e->sh_symtab, shstrtab, 0, offset, symtab, nb_sections - 2, local_syms, sizeof(Elf32_Sym));
+
+ offset += symtab;
+ shstrtab += strlen(".symtab") + 1;
+
+ // .strtab header
+ section_header(&e->sh_strtab, shstrtab, 0, offset, strtab, 0, 0, 0);
+
+ offset += strtab;
+ shstrtab += strlen(".strtab") + 1;
+
+ // .shstrtab header
+ uint64_t shstrtab_len = shstrtab + strlen(".shstrtab") + 1;
+
+ section_header(&e->sh_shstrtab, shstrtab, 0, offset, shstrtab_len, 0, 0, 0);
+
+ fwrite(&e->sh_symtab, sizeof(e->sh_symtab), 1, elf->fp);
+ fwrite(&e->sh_strtab, sizeof(e->sh_strtab), 1, elf->fp);
+ fwrite(&e->sh_shstrtab, sizeof(e->sh_shstrtab), 1, elf->fp);
+
+ elf32_write_sections(elf); // write user's section data
+
+ elf32_write_symtab (elf); // write .symtab data (user's symbols)
+ elf32_write_strtab (elf); // write .strtab data (symbol names of symtab)
+ elf32_write_shstrtab(elf); // write .shstrtab data (section names of all sections)
+ return 0;
+}
+
+int elf32_sym_cmp(const void* v0, const void* v1)
+{
+ const elf_sym_t* sym0 = *(const elf_sym_t**)v0;
+ const elf_sym_t* sym1 = *(const elf_sym_t**)v1;
+
+ if (STB_LOCAL == ELF32_ST_BIND(sym0->sym.st_info)) {
+
+ if (STB_GLOBAL == ELF32_ST_BIND(sym1->sym.st_info))
+ return -1;
+
+ } else if (STB_LOCAL == ELF32_ST_BIND(sym1->sym.st_info))
+ return 1;
+
+ return 0;
+}
+
+int elf32_find_sym(elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols)
+{
+ elf_sym_t* sym;
+ elf_sym_t* sym2;
+
+ int sym_idx = ELF32_R_SYM(rela->r_info);
+ int j;
+
+ assert(sym_idx >= 1);
+ assert(sym_idx - 1 < symbols->size);
+
+ sym = symbols->data[sym_idx - 1];
+
+ if (0 == sym->sym.st_shndx) {
+
+ int n = 0;
+
+ for (j = 0; j < symbols->size; j++) {
+ sym2 = symbols->data[j];
+
+ if (0 == sym2->sym.st_shndx)
+ continue;
+
+ if (STB_LOCAL == ELF32_ST_BIND(sym2->sym.st_info))
+ continue;
+
+ if (!strcmp(sym2->name->data, sym->name->data)) {
+ sym = sym2;
+ sym_idx = j + 1;
+ n++;
+ }
+ }
+
+ if (0 == n) {
+ scf_loge("global symbol: %s not found\n", sym->name->data);
+ return -1;
+
+ } else if (n > 1) {
+ scf_loge("tow global symbol: %s\n", sym->name->data);
+ return -1;
+ }
+ } else if (ELF32_ST_TYPE(sym->sym.st_info) == STT_SECTION) {
+
+ for (j = symbols->size - 1; j >= 0; j--) {
+ sym2 = symbols->data[j];
+
+ if (ELF32_ST_TYPE(sym2->sym.st_info) != STT_SECTION)
+ continue;
+
+ if (sym2->sym.st_shndx == sym->sym.st_shndx) {
+ sym = sym2;
+ sym_idx = j + 1;
+ break;
+ }
+ }
+
+ assert(j >= 0);
+ }
+
+ *psym = sym;
+ return sym_idx;
+}
+
+void elf32_process_syms(elf_native_t* e, uint32_t cs_index)
+{
+ elf_section_t* s;
+ Elf32_Rela* rela;
+ elf_sym_t* sym;
+
+ int i;
+ int j;
+ int k;
+ int shndx = 20;
+#if 1
+ for (i = e->symbols->size - 1; i >= 0; i--) {
+ sym = e->symbols->data[i];
+
+ if (STT_SECTION == ELF32_ST_TYPE(sym->sym.st_info)) {
+ if (shndx > cs_index) {
+
+ shndx = sym->sym.st_shndx;
+
+ assert(sym->sym.st_shndx - 1 < e->sections->size);
+
+ sym->section = e->sections->data[sym->sym.st_shndx - 1];
+ continue;
+ }
+ } else if (0 != sym->sym.st_shndx) {
+
+ if (sym->sym.st_shndx - 1 < e->sections->size)
+ sym->section = e->sections->data[sym->sym.st_shndx - 1];
+ continue;
+ }
+
+ assert(0 == scf_vector_del(e->symbols, sym));
+
+ scf_string_free(sym->name);
+ free(sym);
+ }
+#endif
+ qsort(e->symbols->data, e->symbols->size, sizeof(void*), elf32_sym_cmp);
+
+ for (j = 0; j < e->sections->size; j++) {
+ s = e->sections->data[j];
+
+ if (SHT_RELA != s->sh.sh_type)
+ continue;
+
+ if (!strcmp(s->name->data, ".rela.plt"))
+ continue;
+
+ assert(s->data_len % sizeof(Elf32_Rela) == 0);
+
+ int sym_idx;
+ for (k = 0; k < s->data_len; k += sizeof(Elf32_Rela)) {
+
+ rela = (Elf32_Rela*)(s->data + k);
+
+ sym_idx = ELF32_R_SYM(rela->r_info);
+
+ for (i = 0; i < e->symbols->size; i++) {
+ sym = e->symbols->data[i];
+
+ if (sym_idx == sym->index)
+ break;
+ }
+
+ assert(i < e->symbols->size);
+
+ rela->r_info = ELF32_R_INFO(i + 1, ELF32_R_TYPE(rela->r_info));
+ }
+ }
+}
+
--- /dev/null
+#ifndef SCF_ELF_NATIVE32_H
+#define SCF_ELF_NATIVE32_H
+
+#include"scf_elf.h"
+#include"scf_vector.h"
+#include"scf_string.h"
+
+typedef struct elf_section_s elf_section_t;
+
+struct elf_section_s
+{
+ elf_section_t* link;
+ elf_section_t* info;
+
+ scf_string_t* name;
+
+ Elf32_Shdr sh;
+
+ uint64_t offset;
+
+ uint16_t index;
+ uint8_t* data;
+ int data_len;
+};
+
+typedef struct {
+ elf_section_t* section;
+
+ scf_string_t* name;
+
+ Elf32_Sym sym;
+
+ int index;
+ uint8_t dyn_flag:1;
+
+} elf_sym_t;
+
+typedef struct {
+ Elf32_Ehdr eh;
+
+ Elf32_Shdr sh_null;
+
+ scf_vector_t* sections;
+ scf_vector_t* phdrs;
+
+ Elf32_Shdr sh_symtab;
+ scf_vector_t* symbols;
+
+ Elf32_Shdr sh_strtab;
+
+ Elf32_Shdr sh_shstrtab;
+ scf_string_t* sh_shstrtab_data;
+
+ scf_vector_t* dynsyms;
+ scf_vector_t* dyn_needs;
+ scf_vector_t* dyn_relas;
+
+ elf_section_t* interp;
+ elf_section_t* dynsym;
+ elf_section_t* dynstr;
+ elf_section_t* gnu_version;
+ elf_section_t* gnu_version_r;
+ elf_section_t* rela_plt;
+ elf_section_t* plt;
+ elf_section_t* dynamic;
+ elf_section_t* got_plt;
+
+} elf_native_t;
+
+
+int elf32_open (scf_elf_context_t* elf);
+int elf32_close(scf_elf_context_t* elf);
+
+int elf32_add_sym (scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name);
+int elf32_add_section (scf_elf_context_t* elf, const scf_elf_section_t* section);
+int elf32_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas);
+
+int elf32_read_shstrtab(scf_elf_context_t* elf);
+int elf32_read_section (scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name);
+
+int elf32_add_dyn_need(scf_elf_context_t* elf, const char* soname);
+int elf32_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela);
+
+int elf32_read_phdrs (scf_elf_context_t* elf, scf_vector_t* phdrs);
+int elf32_read_relas (scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name);
+int elf32_read_syms (scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name);
+
+int elf32_find_sym (elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols);
+void elf32_process_syms(elf_native_t* native, uint32_t cs_index);
+
+int elf32_write_sections(scf_elf_context_t* elf);
+int elf32_write_shstrtab(scf_elf_context_t* elf);
+int elf32_write_symtab (scf_elf_context_t* elf);
+int elf32_write_strtab (scf_elf_context_t* elf);
+int elf32_write_rel (scf_elf_context_t* elf, uint16_t e_machine);
+
+int elf32_sym_cmp(const void* v0, const void* v1);
+
+static inline void elf_header(Elf32_Ehdr* eh,
+ uint16_t e_type,
+ uint16_t e_machine,
+ Elf32_Addr e_entry,
+ Elf32_Off e_phoff,
+ uint16_t e_phnum,
+ uint16_t e_shnum,
+ uint16_t e_shstrndx)
+{
+ eh->e_ident[EI_MAG0] = ELFMAG0;
+ eh->e_ident[EI_MAG1] = ELFMAG1;
+ eh->e_ident[EI_MAG2] = ELFMAG2;
+ eh->e_ident[EI_MAG3] = ELFMAG3;
+ eh->e_ident[EI_CLASS] = ELFCLASS32;
+ eh->e_ident[EI_DATA] = ELFDATA2LSB;
+ eh->e_ident[EI_VERSION] = EV_CURRENT;
+ eh->e_ident[EI_OSABI] = ELFOSABI_SYSV;
+
+ eh->e_type = e_type;
+ eh->e_machine = e_machine;
+ eh->e_version = EV_CURRENT;
+ eh->e_entry = e_entry;
+ eh->e_ehsize = sizeof(Elf32_Ehdr);
+
+ eh->e_flags = 0x5000400;
+
+ eh->e_phoff = e_phoff;
+ eh->e_phentsize = sizeof(Elf32_Phdr);
+ eh->e_phnum = e_phnum;
+
+ eh->e_shoff = sizeof(Elf32_Ehdr);
+ eh->e_shentsize = sizeof(Elf32_Shdr);
+ eh->e_shnum = e_shnum;
+ eh->e_shstrndx = e_shstrndx;
+}
+
+static inline void section_header(Elf32_Shdr* sh,
+ uint32_t sh_name,
+ Elf32_Addr sh_addr,
+ Elf32_Off sh_offset,
+ uint64_t sh_size,
+ uint32_t sh_link,
+ uint32_t sh_info,
+ uint64_t sh_entsize)
+{
+ sh->sh_name = sh_name;
+ sh->sh_addr = sh_addr;
+ sh->sh_offset = sh_offset;
+ sh->sh_size = sh_size;
+ sh->sh_link = sh_link;
+ sh->sh_info = sh_info;
+ sh->sh_entsize = sh_entsize;
+}
+
+#endif
+
--- /dev/null
+.text
+.global _start, main
+
+_start:
+ bl main
+ mov r7, #1
+ swi #0
+.fill 4, 1, 0
--- /dev/null
+#include"scf_risc.h"
+
+int arm32_inst_I2G(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes)
+{
+ scf_instruction_t* inst;
+
+ uint32_t opcode;
+
+ // mov rd, imm[15:0]
+ opcode = (0xe3 << 24) | (((imm >> 12 ) & 0xf) << 16) | (rd->id << 12) | (imm & 0xfff);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ imm >>= 16;
+ if (imm & 0xffff) {
+
+ // movk rd, imm[31:16]
+ opcode = (0xe3 << 24) | (0x1 << 22) | (((imm >> 12 ) & 0xf) << 16) | (rd->id << 12) | (imm & 0xfff);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ }
+
+ return 0;
+}
+
+int arm32_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs)
+{
+ scf_register_t* fp = f->rops->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 = f->rops->variable_size(vs);
+
+ if (vs->local_flag || vs->tmp_flag) {
+
+ offset = vs->bp_offset;
+
+ if (offset >= 0 && offset <= 0xff)
+
+ opcode = (0xe2 << 24) | (0x8 << 20) | (fp->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && -offset <= 0xff)
+
+ opcode = (0xe2 << 24) | (0x4 << 20) | (fp->id << 16) | (rd->id << 12) | (-offset);
+
+ else {
+ int ret = arm32_inst_I2G(c, rd, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (fp->id << 16) | (rd->id << 12) | rd->id;
+ }
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ } else if (vs->global_flag) {
+ offset = 0;
+
+ opcode = (0xe3 << 24) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL);
+ rela->type = R_ARM_REL32;
+
+ opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ } else {
+ scf_loge("temp var should give a register\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int arm32_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs)
+{
+ scf_register_t* fp = f->rops->find_register("fp");
+ scf_register_t* ri = NULL;
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
+
+ int32_t offset;
+ uint32_t opcode;
+
+ int size = f->rops->variable_size(vs);
+
+ if (!rb) {
+ if (vs->local_flag || vs->tmp_flag) {
+
+ offset = vs->bp_offset;
+ rb = fp;
+
+ } else if (vs->global_flag) {
+ offset = 0;
+
+ opcode = (0xe3 << 24) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL);
+ rela->type = R_ARM_REL32;
+
+ opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ rb = rd;
+
+ } else {
+ scf_loge("temp var should give a register\n");
+ return -EINVAL;
+ }
+
+ } else {
+ if (vs->local_flag || vs->tmp_flag)
+ offset = vs->bp_offset;
+ else
+ offset = vs->offset;
+ }
+
+ if (1 == size) {
+
+ if (scf_variable_signed(vs)) {
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xd) << 4) | (offset & 0xf);
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xd) << 4) | (offset & 0xf);
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xd << 4) | ri->id;
+ }
+
+ } else {
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id;
+ }
+ }
+
+ } else if (2 == size) {
+
+ if (offset & 0x1) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xb << 4) | ri->id;
+ }
+
+ if (scf_variable_signed(vs))
+ opcode |= 0x1 << 6;
+
+ } else if (4 == size) {
+
+ if (offset & 0x3) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x1 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | ri->id;
+ }
+
+ } else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ return 0;
+}
+
+int arm32_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs)
+{
+ scf_register_t* fp = f->rops->find_register("fp");
+ scf_register_t* ri = NULL;
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
+
+ int32_t offset;
+ uint32_t opcode;
+
+ int size = f->rops->variable_size(vs);
+
+ if (!rb) {
+ if (vs->local_flag || vs->tmp_flag) {
+
+ offset = vs->bp_offset;
+ rb = fp;
+
+ } else if (vs->global_flag) {
+ offset = 0;
+
+ int ret = risc_select_free_reg(&rb, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_ADR2G(c, f, rb, vs);
+ if (ret < 0)
+ return -EINVAL;
+
+ } else {
+ scf_loge("temp var should give a register\n");
+ return -EINVAL;
+ }
+
+ } else {
+ if (vs->local_flag || vs->tmp_flag)
+ offset = vs->bp_offset;
+ else
+ offset = vs->offset;
+ }
+
+ if (1 == size) {
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id;
+ }
+
+ } else if (2 == size) {
+
+ if (offset & 0x1) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xe1 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe1 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe1 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0xb << 4) | ri->id;
+ }
+
+ } else if (4 == size) {
+
+ if (offset & 0x3) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x0 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | ri->id;
+ }
+
+ } else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+////////
+int arm32_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* v)
+{
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
+
+ int size1 = f->rops->variable_size(v);
+
+ assert(4 == rd->bytes);
+ assert(4 == size1);
+
+ v->global_flag = 1;
+ v->local_flag = 0;
+ v->tmp_flag = 0;
+
+ uint32_t opcode;
+
+ opcode = (0xe3 << 24) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL);
+ rela->type = R_ARM_REL32;
+
+ opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+
+int arm32_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size)
+{
+ scf_register_t* ri = NULL;
+ scf_instruction_t* inst = NULL;
+
+ uint32_t opcode;
+
+ if (!rb)
+ return -EINVAL;
+
+ if (1 == size) {
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id;
+ }
+
+ } else if (2 == size) {
+
+ if (offset & 0x1) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xe1 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe1 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe1 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0xb << 4) | ri->id;
+ }
+
+ } else if (4 == size) {
+
+ if (offset & 0x3) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x0 << 20) | (rb->id << 16) | (rs->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | ri->id;
+ }
+
+ } else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+
+int arm32_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size)
+{
+ scf_register_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) {
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id;
+ }
+
+ } else if (2 == size) {
+
+ if (offset & 0x1) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf);
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xb << 4) | ri->id;
+ }
+
+ } else if (4 == size) {
+
+ if (offset & 0x3) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ if (offset >= 0 && offset < 0xfff)
+ opcode = (0xe5 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xfff) {
+ offset = -offset;
+ opcode = (0xe5 << 24) | (0x1 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ri, c, f, 0);
+ if (ret < 0) {
+ scf_loge("\n");
+ return -EINVAL;
+ }
+
+ ret = arm32_inst_I2G(c, ri, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | ri->id;
+ }
+
+ } else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ return 0;
+}
+
+int arm32_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset)
+{
+ scf_register_t* r = NULL;
+ scf_instruction_t* inst = NULL;
+
+ uint32_t opcode = 0;
+
+ if (offset >= 0 && offset <= 0xff)
+ opcode = (0xe2 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xe2 << 24) | (0x4 << 20) | (rb->id << 16) | (rd->id << 12) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&r, c, f, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = arm32_inst_I2G(c, r, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | r->id;
+ }
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ return 0;
+}
+
+int arm32_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib)
+{
+ scf_register_t* rb = sib->base;
+ scf_register_t* ri = sib->index;
+ scf_instruction_t* inst = NULL;
+
+ assert(0 == sib->disp);
+
+ if (!rb || !ri)
+ return -EINVAL;
+
+ uint32_t opcode;
+ uint32_t SH;
+
+ if (1 == sib->scale)
+ SH = 0;
+
+ else if (2 == sib->scale)
+ SH = 1;
+
+ else if (4 == sib->scale)
+ SH = 2;
+ else
+ return -EINVAL;
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | (SH << 7) | ri->id;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ return 0;
+}
+
+int arm32_inst_SIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib)
+{
+ scf_register_t* rb = sib->base;
+ scf_register_t* ri = sib->index;
+ scf_instruction_t* inst = NULL;
+
+ assert(0 == sib->disp);
+
+ if (!rb || !ri)
+ return -EINVAL;
+
+ int scale = sib->scale;
+ int size = sib->size;
+
+ uint32_t opcode;
+
+ if (1 == size)
+ opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id;
+
+ else if (2 == size)
+ opcode = (0xf8 << 24) | (0x3 << 20) | (rb->id << 16) | (rd->id << 12) | (0x1 << 4) | ri->id;
+
+ else if (4 == size)
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0x2 << 7) | ri->id;
+ else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+
+int arm32_inst_G2SIB(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_sib_t* sib)
+{
+ scf_register_t* rb = sib->base;
+ scf_register_t* ri = sib->index;
+ scf_instruction_t* inst = NULL;
+
+ assert(0 == sib->disp);
+
+ if (!rb || !ri)
+ return -EINVAL;
+
+ int scale = sib->scale;
+ int size = sib->size;
+
+ uint32_t opcode;
+
+ if (1 == size)
+ opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id;
+
+ else if (2 == size)
+ opcode = (0xf8 << 24) | (0x2 << 20) | (rb->id << 16) | (rs->id << 12) | (0x1 << 4) | ri->id;
+
+ else if (4 == size)
+ opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0x2 << 7) | ri->id;
+ else
+ return -EINVAL;
+
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+
+int arm32_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs)
+{
+ scf_register_t* fp = f->rops->find_register("fp");
+ scf_register_t* ro = NULL;
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
+
+ int32_t offset;
+ uint32_t opcode;
+ uint32_t SIZE = 0;
+ uint32_t D = 0;
+ uint32_t V = 0;
+
+ int size = f->rops->variable_size(vs);
+
+ scf_loge("\n");
+ return -EINVAL;
+
+ if (!rb) {
+ if (vs->local_flag || vs->tmp_flag) {
+
+ offset = vs->bp_offset;
+ rb = fp;
+
+ } else if (vs->global_flag) {
+ offset = 0;
+
+ int ret = risc_select_free_reg(&rb, c, f, 0);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe3 << 24) | (rb->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL);
+ rela->type = R_ARM_REL32;
+
+ opcode = (0xe3 << 24) | (0x4 << 20) | (rb->id << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rb->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rb->id << 12) | 0xf;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ } else {
+ scf_loge("temp var should give a register\n");
+ return -EINVAL;
+ }
+
+ } else {
+ if (vs->local_flag || vs->tmp_flag)
+ offset = vs->bp_offset;
+ else
+ offset = vs->offset;
+ }
+
+
+ if (2 == size) {
+
+ if (offset & 0x1) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ offset >>= 1;
+ SIZE = 1;
+ D = rd->id & 0x1;
+ V = rd->id >> 1;
+
+ } else if (4 == size) {
+
+ if (offset & 0x3) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ offset >>= 2;
+ SIZE = 2;
+ D = rd->id & 0x1;
+ V = rd->id >> 1;
+
+ } else if (8 == size) {
+
+ if (offset & 0x7) {
+ scf_loge("memory align error\n");
+ return -EINVAL;
+ }
+
+ offset >>= 3;
+ SIZE = 3;
+ V = rd->id & 0xf;
+ D = (rd->id >> 4) & 0x1;
+ } else
+ return -EINVAL;
+
+ if (offset >= 0 && offset < 0xff)
+ opcode = (0xed << 24) | (0x9 << 20) | (rb->id << 16) | (0x2 << 10) | (SIZE << 8) | offset;
+
+ else if (offset < 0 && offset >= -0xff) {
+ offset = -offset;
+ opcode = (0xed << 24) | (0x1 << 20) | (rb->id << 16) | (0x2 << 10) | (SIZE << 8) | offset;
+
+ } else {
+ int ret = risc_select_free_reg(&ro, c, f, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = arm32_inst_I2G(c, ro, offset, 4);
+ if (ret < 0)
+ return ret;
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (ro->id << 12) | (SIZE << 7) | ro->id;
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode = (0xed << 24) | (0x9 << 20) | (ro->id << 16) | (0x2 << 10) | (SIZE << 8) | 0;
+ }
+
+ opcode |= (D << 22) | (V << 12);
+ inst = risc_make_inst(c, opcode);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ return 0;
+}
+
+scf_instruction_t* arm32_inst_PUSH(scf_3ac_code_t* c, scf_register_t* r)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe5 << 24) | (0x2 << 20) | (0xd << 16) | (r->id << 12) | 0x4;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_POP(scf_3ac_code_t* c, scf_register_t* r)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe4 << 24) | (0x9 << 20) | (0xd << 16) | (r->id << 12) | 0x4;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_RET(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xe12fff1e;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MOV_SP(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MVN(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xe << 20) | (rd->id << 12) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FMOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xee << 24) | (0xe << 20) | (rd->id << 12) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MOVSX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ if (1 == size)
+ opcode = (0xe6 << 24) | (0xa << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id;
+
+ else if (2 == size)
+ opcode = (0xe6 << 24) | (0xb << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id;
+ else
+ return NULL;
+
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MOVZX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ if (1 == size)
+ opcode = (0xe6 << 24) | (0xe << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id;
+
+ else if (2 == size)
+ opcode = (0xe6 << 24) | (0xf << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id;
+ else
+ return NULL;
+
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t M = rs->id & 0x1;
+ uint32_t Vm = rs->id >> 1;
+ uint32_t D = rd->id >> 4;
+ uint32_t Vd = rd->id & 0xf;
+
+ opcode = (0xee << 24) | (0xb7 << 16) | (0xa << 8) | (0xc << 4) | (D << 22) | (Vd << 12) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTSD2SS(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t M = rd->id >> 4;
+ uint32_t Vm = rd->id & 0xf;
+ uint32_t D = rs->id & 0x1;
+ uint32_t Vd = rs->id >> 1;
+
+ opcode = (0xee << 24) | (0xb7 << 16) | (0xb << 8) | (0xc << 4) | (D << 22) | (Vd << 12) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTF2SI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t M = rs->id & 0x1;
+ uint32_t Vm = rs->id >> 1;
+ uint32_t D = 15 >> 4;
+ uint32_t Vd = 15 & 0xf;
+ uint32_t SZ = (8 == rs->bytes) ? 0x3 : 0x2;
+
+ opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0xd << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+ if (!inst)
+ return NULL;
+
+ if (scf_vector_add(c->instructions, inst) < 0) {
+ free(inst);
+ return NULL;
+ }
+
+ opcode = (0xee << 24) | (0x1 << 20) | (Vd << 16) | (rd->id << 12) | (0xa << 8) | (D << 7) | (0x1 << 4);
+ inst = risc_make_inst(c, opcode);
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTF2UI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t M = rs->id & 0x1;
+ uint32_t Vm = rs->id >> 1;
+ uint32_t D = 15 >> 4;
+ uint32_t Vd = 15 & 0xf;
+ uint32_t SZ = (8 == rs->bytes) ? 0x3 : 0x2;
+
+ opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0xc << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+ if (!inst)
+ return NULL;
+
+ if (scf_vector_add(c->instructions, inst) < 0) {
+ free(inst);
+ return NULL;
+ }
+
+ opcode = (0xee << 24) | (0x1 << 20) | (Vd << 16) | (rd->id << 12) | (0xa << 8) | (D << 7) | (0x1 << 4);
+ inst = risc_make_inst(c, opcode);
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTSI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t D = rs->id & 0x1;
+ uint32_t Vd = rs->id >> 1;
+ uint32_t M = 15 >> 4;
+ uint32_t Vm = 15 & 0xf;
+ uint32_t SZ = (8 == rd->bytes) ? 0x3 : 0x2;
+
+ opcode = (0xee << 24) | (0x0 << 20) | (Vm << 16) | (rd->id << 12) | (0xa << 8) | (M << 7) | (0x1 << 4);
+ inst = risc_make_inst(c, opcode);
+ if (!inst)
+ return NULL;
+
+ if (scf_vector_add(c->instructions, inst) < 0) {
+ free(inst);
+ return NULL;
+ }
+
+ opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0x8 << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CVTUI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ uint32_t D = rs->id & 0x1;
+ uint32_t Vd = rs->id >> 1;
+ uint32_t M = 15 >> 4;
+ uint32_t Vm = 15 & 0xf;
+ uint32_t SZ = (8 == rd->bytes) ? 0x3 : 0x2;
+
+ opcode = (0xee << 24) | (0x0 << 20) | (Vm << 16) | (rd->id << 12) | (0xa << 8) | (M << 7) | (0x1 << 4);
+ inst = risc_make_inst(c, opcode);
+ if (!inst)
+ return NULL;
+
+ if (scf_vector_add(c->instructions, inst) < 0) {
+ free(inst);
+ return NULL;
+ }
+
+ opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0x8 << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x1 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SUB_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t sh = 0;
+
+ if (imm > 0xff) {
+ scf_loge("NOT support too big imm: %#lx\n", imm);
+ return NULL;
+ }
+
+ opcode = (0xe2 << 24) | (0x4 << 20) | (rs->id << 16) | (rd->id << 12) | imm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CMP_IMM(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t sh = 0;
+
+ if (imm > 0xff) {
+ scf_loge("NOT support too big imm: %#lx\n", imm);
+ return NULL;
+ }
+
+ opcode = (0xe3 << 24) | (0x5 << 20) | (rs->id << 16) | imm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_ADD_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t sh = 0;
+
+ if (imm > 0xff) {
+ scf_loge("NOT support too big imm: %#lx\n", imm);
+ return NULL;
+ }
+
+ opcode = (0xe2 << 24) | (0x8 << 20) | (rs->id << 16) | (rd->id << 12) | imm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_ADD_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe0 << 24) | (0x8 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SHL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SHR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x3 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_ASR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x5 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_AND_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe0 << 24) | (0x0 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_OR_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0x8 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SUB_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe0 << 24) | (0x4 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_CMP_G(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0x5 << 20) | (rs0->id << 16) | rs1->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FCMP(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t D;
+ uint32_t M;
+ uint32_t Vd;
+ uint32_t Vm;
+ uint32_t SIZE;
+
+ if (8 == rs0->bytes) {
+ D = rs0->id >> 4;
+ Vd = rs0->id & 0xf;
+
+ M = rs1->id >> 4;
+ Vm = rs1->id & 0xf;
+
+ SIZE = 3;
+
+ } else {
+ D = rs0->id & 0x1;
+ Vd = rs0->id >> 1;
+
+ M = rs1->id & 0x1;
+ Vm = rs1->id >> 1;
+
+ SIZE = 2;
+ }
+
+ opcode = (0xee << 24) | (0x1 << 23) | (D << 22) | (0x3 << 20) | (0x4 << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (0x1 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_NEG(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0x3 << 20) | (rs->id << 16) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_TEQ(scf_3ac_code_t* c, scf_register_t* rs)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe1 << 24) | (0x3 << 20) | (rs->id << 16) | rs->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FADD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t D;
+ uint32_t M;
+ uint32_t N;
+ uint32_t Vd;
+ uint32_t Vm;
+ uint32_t Vn;
+ uint32_t SIZE;
+
+ if (8 == rd->bytes) {
+ D = rd->id >> 4;
+ Vd = rd->id & 0xf;
+
+ M = rs1->id >> 4;
+ Vm = rs1->id & 0xf;
+
+ N = rs0->id >> 4;
+ Vn = rs0->id & 0xf;
+
+ SIZE = 3;
+
+ } else {
+ D = rd->id & 0x1;
+ Vd = rd->id >> 1;
+
+ M = rs1->id & 0x1;
+ Vm = rs1->id >> 1;
+
+ N = rs0->id & 0x1;
+ Vn = rs0->id >> 1;
+
+ SIZE = 2;
+ }
+
+ opcode = (0xee << 24) | (D << 22) | (0x3 << 20) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t D;
+ uint32_t M;
+ uint32_t N;
+ uint32_t Vd;
+ uint32_t Vm;
+ uint32_t Vn;
+ uint32_t SIZE;
+
+ if (8 == rd->bytes) {
+ D = rd->id >> 4;
+ Vd = rd->id & 0xf;
+
+ M = rs1->id >> 4;
+ Vm = rs1->id & 0xf;
+
+ N = rs0->id >> 4;
+ Vn = rs0->id & 0xf;
+
+ SIZE = 3;
+
+ } else {
+ D = rd->id & 0x1;
+ Vd = rd->id >> 1;
+
+ M = rs1->id & 0x1;
+ Vm = rs1->id >> 1;
+
+ N = rs0->id & 0x1;
+ Vn = rs0->id >> 1;
+
+ SIZE = 2;
+ }
+
+ opcode = (0xee << 24) | (D << 22) | (0x3 << 20) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (0x1 << 6) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe0 << 24) | (rd->id << 16) | (rs1->id << 8) | (0x9 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FMUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t D;
+ uint32_t M;
+ uint32_t N;
+ uint32_t Vd;
+ uint32_t Vm;
+ uint32_t Vn;
+ uint32_t SIZE;
+
+ if (8 == rd->bytes) {
+ D = rd->id >> 4;
+ Vd = rd->id & 0xf;
+
+ M = rs1->id >> 4;
+ Vm = rs1->id & 0xf;
+
+ N = rs0->id >> 4;
+ Vn = rs0->id & 0xf;
+
+ SIZE = 3;
+
+ } else {
+ D = rd->id & 0x1;
+ Vd = rd->id >> 1;
+
+ M = rs1->id & 0x1;
+ Vm = rs1->id >> 1;
+
+ N = rs0->id & 0x1;
+ Vn = rs0->id >> 1;
+
+ SIZE = 2;
+ }
+
+ opcode = (0xee << 24) | (0x0 << 23) | (D << 22) | (0x1 << 21) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_FDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t D;
+ uint32_t M;
+ uint32_t N;
+ uint32_t Vd;
+ uint32_t Vm;
+ uint32_t Vn;
+ uint32_t SIZE;
+
+ if (8 == rd->bytes) {
+ D = rd->id >> 4;
+ Vd = rd->id & 0xf;
+
+ M = rs1->id >> 4;
+ Vm = rs1->id & 0xf;
+
+ N = rs0->id >> 4;
+ Vn = rs0->id & 0xf;
+
+ SIZE = 3;
+
+ } else {
+ D = rd->id & 0x1;
+ Vd = rd->id >> 1;
+
+ M = rs1->id & 0x1;
+ Vm = rs1->id >> 1;
+
+ N = rs0->id & 0x1;
+ Vn = rs0->id >> 1;
+
+ SIZE = 2;
+ }
+
+ opcode = (0xee << 24) | (0x1 << 23) | (D << 22) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_DIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe7 << 24) | (0x3 << 20) | (rd->id << 16) | (0xf << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe7 << 24) | (0x1 << 20) | (rd->id << 16) | (0xf << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = (0xe0 << 24) | (0x6 << 20) | (rd->id << 16) | (ra->id << 12) | (rm->id << 8) | (0x9 << 4) | rn->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+int arm32_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf)
+{
+ scf_instruction_t* inst;
+ scf_rela_t* rela;
+ uint32_t opcode;
+
+ opcode = 0xeb << 24;
+ inst = risc_make_inst(c, opcode);
+
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
+
+ rela->type = R_ARM_CALL;
+ return 0;
+}
+
+scf_instruction_t* arm32_inst_BLR(scf_3ac_code_t* c, scf_register_t* r)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xe12fff30 | r->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_SETZ(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 1;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+scf_instruction_t* arm32_inst_SETNZ(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 0;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+scf_instruction_t* arm32_inst_SETGT(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 0xd;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+scf_instruction_t* arm32_inst_SETGE(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 0xb;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+scf_instruction_t* arm32_inst_SETLT(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 0xa;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+scf_instruction_t* arm32_inst_SETLE(scf_3ac_code_t* c, scf_register_t* rd)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+ uint32_t cc = 0xc;
+
+ opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JMP(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xea000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JZ(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0x0a000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JNZ(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0x1a000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JGT(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xca000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JGE(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xaa000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JLT(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xba000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JLE(scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst;
+ uint32_t opcode;
+
+ opcode = 0xda000000;
+ inst = risc_make_inst(c, opcode);
+
+ return inst;
+}
+
+scf_instruction_t* arm32_inst_JA(scf_3ac_code_t* c)
+{
+ return NULL;
+}
+scf_instruction_t* arm32_inst_JB(scf_3ac_code_t* c)
+{
+ return NULL;
+}
+scf_instruction_t* arm32_inst_JAE(scf_3ac_code_t* c)
+{
+ return NULL;
+}
+scf_instruction_t* arm32_inst_JBE(scf_3ac_code_t* c)
+{
+ return NULL;
+}
+
+void arm32_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
+{
+ bytes -= 8; // 'pc = current + 8'
+ bytes >>= 2;
+
+ assert(bytes < 0x7fffff && bytes > -0x7fffff);
+
+ inst->code[0] |= 0xff & bytes;
+ inst->code[1] |= 0xff & (bytes >> 8);
+ inst->code[2] |= 0xff & (bytes >> 16);
+}
+
+int arm32_cmp_update(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* cmp)
+{
+ scf_instruction_t* inst;
+ scf_register_t* r12 = f->rops->find_register_type_id_bytes(0, 12, 4);
+ scf_register_t* r14 = f->rops->find_register_type_id_bytes(0, 14, 4);
+ scf_register_t* r0;
+
+ uint32_t opcode;
+ uint32_t mov;
+ uint32_t i0;
+ uint32_t i1;
+
+ opcode = cmp->code[0];
+ opcode |= cmp->code[1] << 8;
+ opcode |= cmp->code[2] << 16;
+ opcode |= cmp->code[3] << 24;
+
+ switch (cmp->code[3]) {
+ // arm32
+ case 0xe3: // imm
+ i0 = (opcode >> 16) & 0xf;
+ r0 = f->rops->find_register_type_id_bytes(0, i0, 4);
+ inst = f->iops->MOV_G(c, r12, r0); // use r12 to backup r0
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode &= ~(0xf << 16);
+ opcode |= (0xc << 16);
+ break;
+
+ case 0xe1: // register
+ i0 = (opcode >> 16) & 0xf;
+ i1 = (opcode ) & 0xf;
+
+ r0 = f->rops->find_register_type_id_bytes(0, i0, 4);
+ inst = f->iops->MOV_G(c, r12, r0); // use r16 to backup r0
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ r0 = f->rops->find_register_type_id_bytes(0, i1, 4);
+ inst = f->iops->MOV_G(c, r14, r0); // use r17 to backup r1
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+
+ opcode &= ~(0xf << 16);
+ opcode |= (0xc << 16);
+
+ opcode &= ~0xf;
+ opcode |= 0xe;
+ 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);
+ return 0;
+}
+
+int arm32_set_rel_veneer(scf_function_t* f)
+{
+ scf_basic_block_t* bb;
+ scf_instruction_t* inst;
+ scf_3ac_code_t* c;
+ scf_3ac_code_t* end;
+ scf_list_t* l;
+ scf_rela_t* r;
+
+ int bytes = f->init_code_bytes;
+
+ for (l = scf_list_head(&f->basic_block_list_head); l != scf_list_sentinel(&f->basic_block_list_head); l = scf_list_next(l)) {
+ bb = scf_list_data(l, scf_basic_block_t, list);
+
+ bytes += bb->code_bytes;
+ }
+
+ l = scf_list_tail(&bb->code_list_head);
+ end = scf_list_data(l, scf_3ac_code_t, list);
+
+ int i;
+ for (i = 0; i < f->data_relas->size; i++) {
+ r = f->data_relas->data[i];
+
+ int offset = bytes - r->inst_offset - 16; // 'pc = current + 8'
+
+ inst = risc_make_inst(end, offset - 4);
+ RISC_INST_ADD_CHECK(end->instructions, inst);
+
+ r->inst_offset = bytes;
+
+ bytes += 4;
+ end->inst_bytes += 4;
+ bb ->code_bytes += 4;
+
+ r->inst->code[0] = 0xff & offset;
+ r->inst->code[1] &= 0xf0;
+ r->inst->code[1] |= 0x0f & (offset >> 8);
+ r->inst->code[2] &= 0xf0;
+ r->inst->code[2] |= 0x0f & (offset >> 12);
+
+ int j;
+ for (j = 0; j < r->code->instructions->size; j++) {
+ inst = r->code->instructions->data[j];
+
+ if (inst == r->inst)
+ break;
+ }
+
+ assert(r->code->instructions->size > j + 1);
+
+ inst = r->code->instructions->data[j + 1];
+
+ inst->code[0] = 0xff & (offset >> 16);
+ inst->code[1] &= 0xf0;
+ inst->code[1] |= 0x0f & (offset >> 24);
+ inst->code[2] &= 0xf0;
+ inst->code[2] |= 0x0f & (offset >> 28);
+ }
+
+ return 0;
+}
+
+scf_inst_ops_t inst_ops_arm32 =
+{
+ .name = "arm32",
+
+ .BL = arm32_inst_BL,
+ .BLR = arm32_inst_BLR,
+ .PUSH = arm32_inst_PUSH,
+ .POP = arm32_inst_POP,
+ .TEQ = arm32_inst_TEQ,
+ .NEG = arm32_inst_NEG,
+
+ .MOVZX = arm32_inst_MOVZX,
+ .MOVSX = arm32_inst_MOVSX,
+ .MVN = arm32_inst_MVN,
+ .MOV_G = arm32_inst_MOV_G,
+ .MOV_SP = arm32_inst_MOV_SP,
+
+ .ADD_G = arm32_inst_ADD_G,
+ .ADD_IMM = arm32_inst_ADD_IMM,
+ .SUB_G = arm32_inst_SUB_G,
+ .SUB_IMM = arm32_inst_SUB_IMM,
+ .CMP_G = arm32_inst_CMP_G,
+ .CMP_IMM = arm32_inst_CMP_IMM,
+ .AND_G = arm32_inst_AND_G,
+ .OR_G = arm32_inst_OR_G,
+
+ .MUL = arm32_inst_MUL,
+ .DIV = arm32_inst_DIV,
+ .SDIV = arm32_inst_SDIV,
+ .MSUB = arm32_inst_MSUB,
+
+ .SHL = arm32_inst_SHL,
+ .SHR = arm32_inst_SHR,
+ .ASR = arm32_inst_ASR,
+
+ .CVTSS2SD = arm32_inst_CVTSS2SD,
+ .CVTSD2SS = arm32_inst_CVTSD2SS,
+ .CVTF2SI = arm32_inst_CVTF2SI,
+ .CVTF2UI = arm32_inst_CVTF2UI,
+ .CVTSI2F = arm32_inst_CVTSI2F,
+ .CVTUI2F = arm32_inst_CVTUI2F,
+
+ .FCMP = arm32_inst_FCMP,
+ .FADD = arm32_inst_FADD,
+ .FSUB = arm32_inst_FSUB,
+ .FMUL = arm32_inst_FMUL,
+ .FDIV = arm32_inst_FDIV,
+ .FMOV_G = arm32_inst_FMOV_G,
+
+ .JA = arm32_inst_JA,
+ .JB = arm32_inst_JB,
+ .JZ = arm32_inst_JZ,
+ .JNZ = arm32_inst_JNZ,
+ .JGT = arm32_inst_JGT,
+ .JGE = arm32_inst_JGE,
+ .JLT = arm32_inst_JLT,
+ .JLE = arm32_inst_JLE,
+ .JAE = arm32_inst_JAE,
+ .JBE = arm32_inst_JBE,
+ .JMP = arm32_inst_JMP,
+ .RET = arm32_inst_RET,
+
+ .SETZ = arm32_inst_SETZ,
+ .SETNZ = arm32_inst_SETNZ,
+ .SETGT = arm32_inst_SETGT,
+ .SETGE = arm32_inst_SETGE,
+ .SETLT = arm32_inst_SETLT,
+ .SETLE = arm32_inst_SETLE,
+
+ .I2G = arm32_inst_I2G,
+ .M2G = arm32_inst_M2G,
+ .M2GF = arm32_inst_M2GF,
+ .G2M = arm32_inst_G2M,
+ .G2P = arm32_inst_G2P,
+ .P2G = arm32_inst_P2G,
+ .ISTR2G = arm32_inst_ISTR2G,
+ .SIB2G = arm32_inst_SIB2G,
+ .G2SIB = arm32_inst_G2SIB,
+ .ADR2G = arm32_inst_ADR2G,
+ .ADRP2G = arm32_inst_ADRP2G,
+ .ADRSIB2G = arm32_inst_ADRSIB2G,
+
+ .cmp_update = arm32_cmp_update,
+ .set_jmp_offset = arm32_set_jmp_offset,
+ .set_rel_veneer = arm32_set_rel_veneer,
+};
+
uint32_t SIZE = 0;
uint32_t S = 1;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (vs->local_flag || vs->tmp_flag) {
uint32_t SIZE = 0;
uint32_t S = 1;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (!rb) {
if (vs->local_flag || vs->tmp_flag) {
uint32_t SIZE = 0;
uint32_t S = 1;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (!rb) {
if (vs->local_flag || vs->tmp_flag) {
scf_instruction_t* inst = NULL;
scf_rela_t* rela = NULL;
- int size1 = risc_variable_size(v);
+ int size1 = f->rops->variable_size(v);
assert(8 == rd->bytes);
assert(8 == size1);
uint32_t SIZE = 0;
uint32_t S = 1;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (!rb) {
if (vs->local_flag || vs->tmp_flag) {
return inst;
}
-scf_instruction_t* arm64_inst_BL(scf_3ac_code_t* c)
+int arm64_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf)
{
scf_instruction_t* inst;
+ scf_rela_t* rela;
uint32_t opcode;
opcode = 0x25 << 26;
inst = risc_make_inst(c, opcode);
- return inst;
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
+
+ rela->type = R_AARCH64_CALL26;
+ return 0;
}
scf_instruction_t* arm64_inst_BLR(scf_3ac_code_t* c, scf_register_t* r)
uint32_t SIZE = 0;
uint32_t S = 1;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (vs->local_flag || vs->tmp_flag) {
int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs)
{
- scf_register_t* fp = f->rops->find_register("fp");
- scf_register_t* ri = NULL;
- scf_instruction_t* inst = NULL;
- scf_rela_t* rela = NULL;
+ scf_register_t* fp = f->rops->find_register("fp");
+ scf_register_t* ri = NULL;
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
int64_t offset;
uint32_t opcode;
uint32_t SIZE = 0;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (!rb) {
if (vs->local_flag || vs->tmp_flag) {
int naja_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs)
{
- scf_register_t* fp = f->rops->find_register("fp");
- scf_register_t* ri = NULL;
- scf_instruction_t* inst = NULL;
- scf_rela_t* rela = NULL;
+ scf_register_t* fp = f->rops->find_register("fp");
+ scf_register_t* ri = NULL;
+ scf_instruction_t* inst = NULL;
+ scf_rela_t* rela = NULL;
int64_t offset;
uint32_t opcode;
uint32_t SIZE = 0;
- int size = risc_variable_size(vs);
+ int size = f->rops->variable_size(vs);
if (!rb) {
if (vs->local_flag || vs->tmp_flag) {
scf_instruction_t* inst = NULL;
scf_rela_t* rela = NULL;
- int size1 = risc_variable_size(v);
+ int size1 = f->rops->variable_size(v);
assert(8 == rd->bytes);
assert(8 == size1);
return inst;
}
-scf_instruction_t* naja_inst_BL(scf_3ac_code_t* c)
+int naja_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf)
{
scf_instruction_t* inst;
+ scf_rela_t* rela;
uint32_t opcode;
opcode = (0x18 << 26);
inst = risc_make_inst(c, opcode);
- return inst;
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
+
+ rela->type = R_AARCH64_CALL26;
+ return 0;
}
scf_instruction_t* naja_inst_BLR(scf_3ac_code_t* c, scf_register_t* r)
#include"scf_3ac.h"
extern scf_regs_ops_t regs_ops_arm64;
+extern scf_regs_ops_t regs_ops_arm32;
extern scf_regs_ops_t regs_ops_naja;
extern scf_inst_ops_t inst_ops_arm64;
+extern scf_inst_ops_t inst_ops_arm32;
extern scf_inst_ops_t inst_ops_naja;
static scf_inst_ops_t* inst_ops_array[] =
{
&inst_ops_arm64,
+ &inst_ops_arm32,
&inst_ops_naja,
NULL
static scf_regs_ops_t* regs_ops_array[] =
{
®s_ops_arm64,
+ ®s_ops_arm32,
®s_ops_naja,
NULL
f->args_float = 0;
int bp_int = -8;
- int bp_floats = -8 - (int)RISC_ABI_NB * 8;
+ int bp_floats = -8 - (int)f->rops->ABI_NB * 8;
int bp_others = 16;
int i;
assert(f->inline_flag);
}
- int is_float = scf_variable_float(v);
- int size = risc_variable_size(v);
+ int is_float = scf_variable_float(v);
+ int size = f->rops->variable_size (v);
if (is_float) {
- if (f->args_float < RISC_ABI_NB) {
+ if (f->args_float < f->rops->ABI_NB) {
- v->rabi = f->rops->find_register_type_id_bytes(is_float, risc_abi_float_regs[f->args_float], size);
+ v->rabi = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_float_regs[f->args_float], size);
v->bp_offset = bp_floats;
bp_floats -= 8;
f->args_float++;
continue;
}
- } else if (f->args_int < RISC_ABI_NB) {
+ } else if (f->args_int < f->rops->ABI_NB) {
- v->rabi = f->rops->find_register_type_id_bytes(is_float, risc_abi_regs[f->args_int], size);
+ v->rabi = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_regs[f->args_int], size);
v->bp_offset = bp_int;
bp_int -= 8;
f->args_int++;
_risc_argv_rabi(f);
- int local_vars_size = 8 + RISC_ABI_NB * 8 * 2;
+ int local_vars_size = 8 + f->rops->ABI_NB * 8 * 2;
for (i = 0; i < local_vars->size; i++) {
v = local_vars->data[i];
f->init_code_bytes = 0;
int i;
- for (i = 0; i < RISC_ABI_CALLEE_SAVES_NB; i++) {
+ for (i = 0; i < f->rops->ABI_CALLEE_SAVES_NB; i++) {
- r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8);
+ r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 8);
if (!r->used) {
- r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4);
+ r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 4);
if (!r->used)
continue;
goto error;
}
- ret = scf_risc_graph_kcolor(g, 16, colors);
+ ret = scf_risc_graph_kcolor(g, 16, colors, f);
if (ret < 0)
goto error;
goto error;
}
- ret = scf_risc_graph_kcolor(g, 16, colors);
+ ret = scf_risc_graph_kcolor(g, 16, colors, f);
if (ret < 0)
goto error;
_risc_set_offset_for_relas(ctx, f, f->text_relas);
_risc_set_offset_for_relas(ctx, f, f->data_relas);
+
+ if (f->iops->set_rel_veneer)
+ return f->iops->set_rel_veneer(f);
+
return 0;
}
int risc_optimize_peephole(scf_native_t* ctx, scf_function_t* f);
-int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors);
+int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f);
intptr_t risc_bb_find_color (scf_vector_t* dn_colors, scf_dag_node_t* dn);
int risc_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f)
{
scf_register_t* r0;
- scf_register_t* r16 = f->rops->find_register_type_id_bytes(0, 16, 8);
- scf_register_t* r17 = f->rops->find_register_type_id_bytes(0, 17, 8);
scf_instruction_t* cmp = NULL;
scf_instruction_t* inst;
scf_3ac_code_t* c;
#include"scf_graph.h"
#include"scf_risc.h"
-static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors)
+static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors, scf_function_t* f)
{
risc_rcg_node_t* rn = node->data;
int bytes = RISC_COLOR_BYTES(c);
uint32_t type = RISC_COLOR_TYPE(c);
- if (bytes == risc_variable_size(rn->dag_node->var)
+ if (bytes == f->rops->variable_size (rn->dag_node->var)
&& type == scf_variable_float(rn->dag_node->var))
return c;
}
}
static int _risc_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors,
- scf_vector_t* deleted_nodes)
+ scf_vector_t* deleted_nodes, scf_function_t* f)
{
scf_logd("graph->nodes->size: %d\n", graph->nodes->size);
int i;
assert(colors2->size >= 0);
if (0 == node->color) {
- node->color = _risc_color_select(node, colors2);
+ node->color = _risc_color_select(node, colors2, f);
if (0 == node->color) {
node->color = -1;
scf_logd("colors2->size: %d\n", colors2->size);
}
}
-static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
+static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f)
{
int ret = -1;
scf_vector_t* colors2 = NULL;
if (0 == _risc_kcolor_check(graph)) {
scf_logd("graph->nodes->size: %d\n", graph->nodes->size);
- ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes);
+ ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes, f);
if (ret < 0)
goto error;
goto error;
}
- int reg_size0 = risc_variable_size(rn0->dag_node->var);
- int reg_size1 = risc_variable_size(rn1->dag_node->var);
+ int reg_size0 = f->rops->variable_size(rn0->dag_node->var);
+ int reg_size1 = f->rops->variable_size(rn1->dag_node->var);
if (reg_size0 > reg_size1) {
- node0->color = _risc_color_select(node0, colors2);
+ node0->color = _risc_color_select(node0, colors2, f);
if (0 == node0->color)
goto overflow;
assert(!scf_vector_find(colors2, (void*)node1->color));
} else {
- node1->color = _risc_color_select(node1, colors2);
+ node1->color = _risc_color_select(node1, colors2, f);
if (0 == node1->color)
goto overflow;
if (ret < 0)
goto error;
- ret = scf_risc_graph_kcolor(graph, k - 1, colors2);
+ ret = scf_risc_graph_kcolor(graph, k - 1, colors2, f);
if (ret < 0)
goto error;
goto error;
node_max->color = -1;
- ret = scf_risc_graph_kcolor(graph, k, colors);
+ ret = scf_risc_graph_kcolor(graph, k, colors, f);
if (ret < 0)
goto error;
goto error;
}
- ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes);
+ ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes, f);
if (ret < 0)
goto error;
return ret;
}
-int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
+int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f)
{
if (!graph || !colors || 0 == colors->size) {
scf_loge("\n");
_risc_kcolor_process_conflict(graph);
- return _risc_graph_kcolor(graph, k, colors);
+ return _risc_graph_kcolor(graph, k, colors, f);
}
}
-static int _risc_inst_call_stack_size(scf_3ac_code_t* c)
+static int _risc_inst_call_stack_size(scf_3ac_code_t* c, scf_function_t* f)
{
int stack_size = 0;
if (src->dag_node->rabi2)
continue;
- int size = risc_variable_size(v);
+ int size = f->rops->variable_size(v);
if (size & 0x7)
size = (size + 7) >> 3 << 3;
scf_risc_OpCode_t* lea;
scf_risc_OpCode_t* mov;
scf_risc_OpCode_t* movx;
- scf_instruction_t* inst;
+ scf_instruction_t* inst;
uint32_t opcode;
int ret;
int i;
for (i = c->srcs->size - 1; i >= 1; i--) {
- scf_3ac_operand_t* src = c->srcs->data[i];
- scf_variable_t* v = src->dag_node->var;
- scf_register_t* rd = src->rabi;
- scf_register_t* rabi = src->dag_node->rabi2;
- scf_register_t* rs = NULL;
- int size = risc_variable_size(v);
- int is_float = scf_variable_float(v);
+ scf_3ac_operand_t* src = c->srcs->data[i];
+ scf_variable_t* v = src->dag_node->var;
+ scf_register_t* rd = src->rabi;
+ scf_register_t* rabi = src->dag_node->rabi2;
+ scf_register_t* rs = NULL;
+
+ int size = f->rops->variable_size (v);
+ int is_float = scf_variable_float(v);
if (!rabi) {
rabi = f->rops->find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size);
}
}
+ scf_loge("i: %d, size: %d, v: %s\n", i, size, v->w->text->data);
+
movx = NULL;
if (!is_float) {
- mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_G2E);
+ mov = risc_find_OpCode(SCF_RISC_MOV, f->rops->MAX_BYTES, f->rops->MAX_BYTES, SCF_RISC_G2E);
+
+ if (size < f->rops->MAX_BYTES) {
- if (size < 8) {
if (scf_variable_signed(v))
- movx = risc_find_OpCode(SCF_RISC_MOVSX, size, 8, SCF_RISC_E2G);
+ movx = risc_find_OpCode(SCF_RISC_MOVSX, size, f->rops->MAX_BYTES, SCF_RISC_E2G);
else if (size < 4)
- movx = risc_find_OpCode(SCF_RISC_MOVZX, size, 8, SCF_RISC_E2G);
+ movx = risc_find_OpCode(SCF_RISC_MOVZX, size, f->rops->MAX_BYTES, SCF_RISC_E2G);
}
if (0 == src->dag_node->color) {
return ret;
}
- rabi = f->rops->find_register_color_bytes(rabi->color, 8);
+ rabi = f->rops->find_register_color_bytes(rabi->color, f->rops->MAX_BYTES);
rs = rabi;
} else {
if (src->dag_node->color < 0)
}
RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
- rs = f->rops->find_register_color_bytes(rs->color, 8);
+ rs = f->rops->find_register_color_bytes(rs->color, f->rops->MAX_BYTES);
}
if (movx) {
r = f->rops->find_register_type_id_bytes(is_float, 0, 8);
} else
- r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], 8);
+ r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], f->rops->MAX_BYTES);
int ret = f->rops->overflow_reg(r, c, f);
if (ret < 0) {
for (i = abi_idx; i < abi_total; i++) {
- r = f->rops->find_register_type_id_bytes(RISC_COLOR_TYPE(rd->color), risc_abi_ret_regs[i], rd->bytes);
+ r = f->rops->find_register_type_id_bytes(RISC_COLOR_TYPE(rd->color), f->rops->abi_ret_regs[i], rd->bytes);
if (RISC_COLOR_CONFLICT(r->color, rd->color))
return 0;
continue;
int is_float = scf_variable_float(v);
- int dst_size = risc_variable_size (v);
+ int dst_size = f->rops->variable_size (v);
if (is_float) {
if (i > 0) {
idx_float++;
} else {
- rs = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[idx_int], dst_size);
+ rs = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[idx_int], dst_size);
mov = risc_find_OpCode(SCF_RISC_MOV, dst_size, dst_size, SCF_RISC_G2E);
return -EINVAL;
}
- scf_risc_context_t* risc = ctx->priv;
- scf_function_t* f = risc->f;
+ scf_instruction_t* inst_sp2 = NULL;
+ scf_instruction_t* inst_sp = NULL;
+ scf_instruction_t* inst;
+
+ scf_risc_context_t* risc = ctx->priv;
+ scf_function_t* f = risc->f;
- scf_3ac_operand_t* src0 = c->srcs->data[0];
- scf_variable_t* var_pf = src0->dag_node->var;
- scf_function_t* pf = var_pf->func_ptr;
+ scf_3ac_operand_t* src0 = c->srcs->data[0];
+ scf_variable_t* var_pf = src0->dag_node->var;
+ scf_function_t* pf = var_pf->func_ptr;
if (SCF_FUNCTION_PTR != var_pf->type || !pf) {
scf_loge("\n");
scf_register_t* lr = f->rops->find_register("lr");
scf_register_t* sp = f->rops->find_register("sp");
scf_register_t* x0 = f->rops->find_register("x0");
- scf_instruction_t* inst;
- scf_instruction_t* inst_sp = NULL;
- scf_instruction_t* inst_sp2 = NULL;
lr->used = 1;
sp->used = 1;
risc_call_rabi(NULL, NULL, c, f);
- int32_t stack_size = _risc_inst_call_stack_size(c);
+ int32_t stack_size = _risc_inst_call_stack_size(c, f);
if (stack_size > 0) {
inst_sp = risc_make_inst(c, 0);
inst_sp2 = risc_make_inst(c, 0);
return ret;
}
- scf_register_t* saved_regs[RISC_ABI_CALLER_SAVES_NB];
+ scf_register_t* saved_regs[RISC_ABI_CALLER_SAVES_MAX];
- int save_size = f->rops->caller_save_regs(c, f, risc_abi_caller_saves, RISC_ABI_CALLER_SAVES_NB, stack_size, saved_regs);
+ int save_size = f->rops->caller_save_regs(c, f, f->rops->abi_caller_saves, f->rops->ABI_CALLER_SAVES_NB, stack_size, saved_regs);
if (save_size < 0) {
scf_loge("\n");
return save_size;
}
+ scf_loge("stack_size: %d, save_size: %d\n", stack_size, save_size);
+
if (stack_size > 0) {
assert(inst_sp);
assert(inst_sp2);
inst = NULL;
} else
return -ENOMEM;
+
+ } else {
+ scf_vector_del(c->instructions, inst_sp2);
+
+ free(inst_sp2);
+ inst_sp2 = NULL;
}
+
+ } else {
+ scf_vector_del(c->instructions, inst_sp);
+ scf_vector_del(c->instructions, inst_sp2);
+
+ free(inst_sp);
+ free(inst_sp2);
+
+ inst_sp = NULL;
+ inst_sp2 = NULL;
}
if (var_pf->const_literal_flag) {
assert(0 == src0->dag_node->color);
- inst = ctx->iops->BL(c);
- RISC_INST_ADD_CHECK(c->instructions, inst);
-
- scf_rela_t* rela = NULL;
-
- RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
- rela->type = R_AARCH64_CALL26;
+ ret = ctx->iops->BL(c, f, pf);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
} else {
assert(0 != src0->dag_node->color);
}
int nb_updated = 0;
- scf_register_t* updated_regs[RISC_ABI_RET_NB * 2];
+ scf_register_t* updated_regs[RISC_ABI_RET_MAX * 2];
if (pf->rets && pf->rets->size > 0 && c->dsts) {
- nb_updated = _risc_call_update_dsts(ctx, c, f, updated_regs, RISC_ABI_RET_NB * 2);
+ nb_updated = _risc_call_update_dsts(ctx, c, f, updated_regs, f->rops->ABI_RET_NB * 2);
if (nb_updated < 0) {
scf_loge("\n");
return nb_updated;
}
if (save_size > 0) {
- ret = f->rops->pop_regs(c, f, saved_regs, save_size >> 3, updated_regs, nb_updated);
+ ret = f->rops->pop_regs(c, f, saved_regs, save_size / f->rops->MAX_BYTES, updated_regs, nb_updated);
if (ret < 0) {
scf_loge("\n");
return ret;
uint32_t opcode;
int is_float = scf_variable_float(v);
- int size = risc_variable_size(v);
+ int size = f->rops->variable_size(v);
if (!is_float) {
scf_register_t* r = NULL;
scf_sib_t sib = {0};
- int size = risc_variable_size(vm);
+ int size = f->rops->variable_size(vm);
int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f);
if (ret < 0)
scf_register_t* r = NULL;
scf_sib_t sib = {0};
- int size = risc_variable_size(vm);
+ int size = f->rops->variable_size(vm);
int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f);
if (ret < 0)
scf_register_t* rd = NULL;
scf_sib_t sib = {0};
- int size = risc_variable_size(vm);
+ int size = f->rops->variable_size(vm);
int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f);
if (ret < 0)
scf_register_t* rd = NULL;
scf_sib_t sib = {0};
- int size = risc_variable_size(vm);
+ int size = f->rops->variable_size(vm);
int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f);
if (ret < 0)
scf_variable_t* v = ap->dag_node->var;
int offset_int = -f->args_int * 8 - 8;
- int offset_float = -f->args_float * 8 - RISC_ABI_NB * 8 - 8;
+ int offset_float = -f->args_float * 8 - f->rops->ABI_NB * 8 - 8;
int offset_others = 16;
if (v->bp_offset >= 0) {
RISC_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0);
int is_float = scf_variable_float(v);
- int size = risc_variable_size(v);
+ int size = f->rops->variable_size(v);
uint32_t nints = RISC_ABI_NB;
uint32_t nfloats = RISC_ABI_NB;
scf_variable_t* vs = s->var;
scf_variable_t* vd = d->var;
- int src_size = risc_variable_size(vs);
- int dst_size = risc_variable_size(vd);
+ int src_size = f->rops->variable_size(vs);
+ int dst_size = f->rops->variable_size(vd);
RISC_SELECT_REG_CHECK(&rd, d, c, f, 0);
v = src->dag_node->var;
- int size = risc_variable_size(v);
- int is_float = scf_variable_float(v);
+ int size = f->rops->variable_size (v);
+ int is_float = scf_variable_float(v);
if (i > 0 && is_float) {
scf_loge("\n");
return -1;
} else {
- rd = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], retsize);
+ rd = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], retsize);
if (0 == src->dag_node->color) {
if (rd->bytes > size)
#if 0
#define RISC_MEMSET_LOAD_REG(r, dn) \
do { \
- int size = risc_variable_size(dn->var); \
+ int size = f->rops->variable_size(dn->var); \
assert(8 == size); \
\
if (0 == dn->color) { \
scf_register_t* r;
int i;
- for (i = RISC_ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) {
+ for (i = f->rops->ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) {
- r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8);
+ r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 8);
if (!r->used) {
- r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4);
+ r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 4);
if (!r->used)
continue;
assert(0 != d->color);
- int size = risc_variable_size(v);
+ int size = f->rops->variable_size(v);
int is_float = scf_variable_float(v);
RISC_SELECT_REG_CHECK(&rd, d, c, f, 0);
scf_instruction_t* inst;
int is_float = scf_variable_float(vs);
- int size = risc_variable_size (vs);
+ int size = f->rops->variable_size (vs);
if (size > vscale->data.i)
size = vscale->data.i;
scf_instruction_t* inst;
int is_float = scf_variable_float(vs);
- int size = risc_variable_size (vs);
+ int size = f->rops->variable_size (vs);
if (size > vscale->data.i)
size = vscale->data.i;
scf_instruction_t* inst;
int is_float = scf_variable_float(vs);
- int size = risc_variable_size (vs);
+ int size = f->rops->variable_size (vs);
if (size > vscale->data.i)
size = vscale->data.i;
scf_instruction_t* inst;
int is_float = scf_variable_float(vs);
- int size = risc_variable_size (vs);
+ int size = f->rops->variable_size (vs);
if (size > vscale->data.i)
size = vscale->data.i;
scf_instruction_t* inst;
int is_float = scf_variable_float(vs);
- int size = risc_variable_size (vs);
+ int size = f->rops->variable_size (vs);
if (size > vscale->data.i)
size = vscale->data.i;
if (c->dsts) {
- if (c->dsts->size > RISC_ABI_RET_NB) {
+ if (c->dsts->size > f->rops->ABI_RET_NB) {
scf_loge("\n");
return -EINVAL;
}
continue;
int is_float = scf_variable_float(dn->var);
- int size = risc_variable_size (dn->var);
+ int size = f->rops->variable_size (dn->var);
if (0 == i)
r = f->rops->find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size);
else if (!is_float)
- r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size);
+ r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], size);
else
r = NULL;
scf_register_t* rabi = NULL;
scf_graph_node_t* gn_rabi = NULL;
- rabi = f->rops->find_register_type_id_bytes(0, risc_abi_regs[i], dn_pf->var->size);
+ rabi = f->rops->find_register_type_id_bytes(0, f->rops->abi_regs[i], dn_pf->var->size);
ret = _risc_rcg_make_node(&gn_rabi, g, NULL, rabi);
if (ret < 0) {
dn = src->dag_node;
int is_float = scf_variable_float(dn->var);
- int size = risc_variable_size(dn->var);
+ int size = f->rops->variable_size(dn->var);
size = size > 4 ? 8 : 4;
r = f->rops->find_register_type_id_bytes(is_float, 0, size);
} else
- r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size);
+ r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], size);
ret = _risc_rcg_make_node(&gn, g, dn, r);
if (ret < 0)
if (!c->srcs || c->srcs->size != 3)
return -EINVAL;
#if 0
- for (i = 0; i < c->srcs->size; i++) {
- src = c->srcs->data[i];
- dn = src->dag_node;
-
- int size = risc_variable_size (dn->var);
- size = size > 4 ? 8 : 4;
-
- if (0 == i)
- r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_DI, size);
-
- else if (1 == i)
- r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_AX, size);
-
- else if (2 == i)
- r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_CX, size);
- else
- return -EINVAL;
-
- ret = _risc_rcg_make_node(&gn, g, dn, r, NULL);
- if (ret < 0)
- return ret;
- }
#endif
return 0;
}
scf_risc_OpCode_t* mov;
scf_instruction_t* inst;
- int size = risc_variable_size(v);
- int is_float = scf_variable_float(v);
+ int size = f->rops->variable_size (v);
+ int is_float = scf_variable_float(v);
assert(size == r->bytes);
v = dn->var;
r->used = 1;
- int size = risc_variable_size(v);
- int is_float = scf_variable_float(v);
+ int size = f->rops->variable_size (v);
+ int is_float = scf_variable_float(v);
if (SCF_FUNCTION_PTR == v->type) {
scf_instruction_t* inst;
scf_rela_t* rela = NULL;
- int is_float = scf_variable_float(dn->var);
- int var_size = risc_variable_size(dn->var);
+ int is_float = scf_variable_float(dn->var);
+ int var_size = f->rops->variable_size (dn->var);
r->used = 1;
int ret;
int is_float = scf_variable_float(dn->var);
- int var_size = risc_variable_size(dn->var);
+ int var_size = f->rops->variable_size(dn->var);
if (dn->color > 0) {
r = f->rops->find_register_color(dn->color);
sib->index = NULL;
sib->scale = 0;
sib->disp = disp;
- sib->size = risc_variable_size(vm);
+ sib->size = f->rops->variable_size(vm);
return 0;
}
src = c->srcs->data[i];
dn = src->dag_node;
- int is_float = scf_variable_float(dn->var);
- int size = risc_variable_size (dn->var);
+ int is_float = scf_variable_float(dn->var);
+ int size = f->rops->variable_size (dn->var);
if (is_float) {
- if (nfloats < RISC_ABI_NB)
- dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, risc_abi_float_regs[nfloats++], size);
+ if (nfloats < f->rops->ABI_NB)
+ dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_float_regs[nfloats++], size);
else
dn->rabi2 = NULL;
} else {
- if (nints < RISC_ABI_NB)
- dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, risc_abi_regs[nints++], size);
+ if (nints < f->rops->ABI_NB)
+ dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_regs[nints++], size);
else
dn->rabi2 = NULL;
}
assert(dn->color > 0); \
} while (0)
-static uint32_t risc_abi_regs[] =
-{
- SCF_RISC_REG_X0,
- SCF_RISC_REG_X1,
- SCF_RISC_REG_X2,
- SCF_RISC_REG_X3,
- SCF_RISC_REG_X4,
- SCF_RISC_REG_X5,
- SCF_RISC_REG_X6,
- SCF_RISC_REG_X7,
-};
-
-static uint32_t risc_abi_float_regs[] =
-{
- SCF_RISC_REG_D0,
- SCF_RISC_REG_D1,
- SCF_RISC_REG_D2,
- SCF_RISC_REG_D3,
- SCF_RISC_REG_D4,
- SCF_RISC_REG_D5,
- SCF_RISC_REG_D6,
- SCF_RISC_REG_D7,
-};
-#define RISC_ABI_NB (sizeof(risc_abi_regs) / sizeof(risc_abi_regs[0]))
-
-static uint32_t risc_abi_ret_regs[] =
-{
- SCF_RISC_REG_X0,
- SCF_RISC_REG_X1,
- SCF_RISC_REG_X2,
- SCF_RISC_REG_X3,
-};
-#define RISC_ABI_RET_NB (sizeof(risc_abi_ret_regs) / sizeof(risc_abi_ret_regs[0]))
-
-static uint32_t risc_abi_caller_saves[] =
-{
- SCF_RISC_REG_X0,
- SCF_RISC_REG_X1,
- SCF_RISC_REG_X2,
- SCF_RISC_REG_X3,
- SCF_RISC_REG_X4,
- SCF_RISC_REG_X5,
- SCF_RISC_REG_X6,
- SCF_RISC_REG_X7,
-
- SCF_RISC_REG_X9,
- SCF_RISC_REG_X10,
- SCF_RISC_REG_X11,
- SCF_RISC_REG_X12,
- SCF_RISC_REG_X13,
- SCF_RISC_REG_X14,
- SCF_RISC_REG_X15,
-};
-#define RISC_ABI_CALLER_SAVES_NB (sizeof(risc_abi_caller_saves) / sizeof(risc_abi_caller_saves[0]))
-
-static uint32_t risc_abi_callee_saves[] =
-{
- SCF_RISC_REG_X19,
- SCF_RISC_REG_X20,
- SCF_RISC_REG_X21,
- SCF_RISC_REG_X22,
- SCF_RISC_REG_X23,
- SCF_RISC_REG_X24,
- SCF_RISC_REG_X25,
- SCF_RISC_REG_X26,
- SCF_RISC_REG_X27,
- SCF_RISC_REG_X28,
- SCF_RISC_REG_X29,
- SCF_RISC_REG_X30,
-};
-#define RISC_ABI_CALLEE_SAVES_NB (sizeof(risc_abi_callee_saves) / sizeof(risc_abi_callee_saves[0]))
-
-static inline int risc_variable_size(scf_variable_t* v)
-{
- if (v->nb_dimentions > 0)
- return 8;
-
- if (v->type >= SCF_STRUCT && 0 == v->nb_pointers)
- return 8;
-
- return v->size < 4 ? 4 : v->size;
-}
-
-typedef int (*risc_sib_fill_pt)(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_3ac_code_t* c, scf_function_t* f);
-
-int risc_registers_init();
-int risc_registers_reset();
-void risc_registers_clear();
-scf_vector_t* risc_register_colors();
-
-scf_register_t* risc_find_register(const char* name);
-
-scf_register_t* risc_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes);
-
-scf_register_t* risc_find_register_color(intptr_t color);
-
-scf_register_t* risc_find_register_color_bytes(intptr_t color, int bytes);
-
-scf_register_t* risc_find_abi_register(int index, int bytes);
-
-scf_register_t* risc_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float);
-
-int risc_reg_cached_vars(scf_register_t* r);
-
-int risc_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
+#define RISC_ABI_CALLER_SAVES_MAX 32
+#define RISC_ABI_RET_MAX 8
-int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f);
-
-int risc_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated);
+int risc_save_var (scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
-int risc_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs);
+int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f);
-int risc_save_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f);
+int risc_save_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f);
int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
int risc_load_reg (scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
-int risc_reg_used (scf_register_t* r, scf_dag_node_t* dn);
-
-int risc_overflow_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f);
-int risc_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
-int risc_overflow_reg3(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f);
int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag);
void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c, scf_function_t* f);
-static inline int risc_inst_data_is_reg(scf_inst_data_t* id)
-{
- scf_register_t* fp = (scf_register_t*)risc_find_register("fp");
- scf_register_t* sp = (scf_register_t*)risc_find_register("sp");
-
- if (!id->flag && id->base && id->base != sp && id->base != fp && 0 == id->imm_size)
- return 1;
- return 0;
-}
-
-static inline int risc_inst_data_is_local(scf_inst_data_t* id)
-{
- scf_register_t* fp = (scf_register_t*)risc_find_register("fp");
- scf_register_t* sp = (scf_register_t*)risc_find_register("sp");
-
- if (id->flag && (id->base == fp || id->base == sp))
- return 1;
- return 0;
-}
-
-static inline int risc_inst_data_is_global(scf_inst_data_t* id)
-{
- if (id->flag && !id->base)
- return 1;
- return 0;
-}
-
-static inline int risc_inst_data_is_const(scf_inst_data_t* id)
-{
- if (!id->flag && id->imm_size > 0)
- return 1;
- return 0;
-}
-
#endif
--- /dev/null
+#include"scf_risc.h"
+
+#define SCF_RISC_REG_FP 11
+#define SCF_RISC_REG_SP 13
+#define SCF_RISC_REG_LR 14
+#define SCF_RISC_REG_PC 15
+
+scf_register_t arm32_registers[] = {
+
+ {0, 1, "b0", RISC_COLOR(0, 0, 0x1), NULL, 0, 0},
+ {0, 2, "h0", RISC_COLOR(0, 0, 0x3), NULL, 0, 0},
+ {0, 4, "x0", RISC_COLOR(0, 0, 0xf), NULL, 0, 0},
+
+ {1, 1, "b1", RISC_COLOR(0, 1, 0x1), NULL, 0, 0},
+ {1, 2, "h1", RISC_COLOR(0, 1, 0x3), NULL, 0, 0},
+ {1, 4, "x1", RISC_COLOR(0, 1, 0xf), NULL, 0, 0},
+
+ {2, 1, "b2", RISC_COLOR(0, 2, 0x1), NULL, 0, 0},
+ {2, 2, "h2", RISC_COLOR(0, 2, 0x3), NULL, 0, 0},
+ {2, 4, "x2", RISC_COLOR(0, 2, 0xf), NULL, 0, 0},
+
+ {3, 1, "b3", RISC_COLOR(0, 3, 0x1), NULL, 0, 0},
+ {3, 2, "h3", RISC_COLOR(0, 3, 0x3), NULL, 0, 0},
+ {3, 4, "x3", RISC_COLOR(0, 3, 0xf), NULL, 0, 0},
+
+ {4, 1, "b4", RISC_COLOR(0, 4, 0x1), NULL, 0, 0},
+ {4, 2, "h4", RISC_COLOR(0, 4, 0x3), NULL, 0, 0},
+ {4, 4, "x4", RISC_COLOR(0, 4, 0xf), NULL, 0, 0},
+
+ {5, 1, "b5", RISC_COLOR(0, 5, 0x1), NULL, 0, 0},
+ {5, 2, "h5", RISC_COLOR(0, 5, 0x3), NULL, 0, 0},
+ {5, 4, "x5", RISC_COLOR(0, 5, 0xf), NULL, 0, 0},
+
+ {6, 1, "b6", RISC_COLOR(0, 6, 0x1), NULL, 0, 0},
+ {6, 2, "h6", RISC_COLOR(0, 6, 0x3), NULL, 0, 0},
+ {6, 4, "x6", RISC_COLOR(0, 6, 0xf), NULL, 0, 0},
+
+ {7, 1, "b7", RISC_COLOR(0, 7, 0x1), NULL, 0, 0},
+ {7, 2, "h7", RISC_COLOR(0, 7, 0x3), NULL, 0, 0},
+ {7, 4, "x7", RISC_COLOR(0, 7, 0xf), NULL, 0, 0},
+
+ {8, 1, "b8", RISC_COLOR(0, 8, 0x1), NULL, 0, 0},
+ {8, 2, "h8", RISC_COLOR(0, 8, 0x3), NULL, 0, 0},
+ {8, 4, "x8", RISC_COLOR(0, 8, 0xf), NULL, 0, 0},
+
+ {9, 1, "b9", RISC_COLOR(0, 9, 0x1), NULL, 0, 0},
+ {9, 2, "h9", RISC_COLOR(0, 9, 0x3), NULL, 0, 0},
+ {9, 4, "x9", RISC_COLOR(0, 9, 0xf), NULL, 0, 0},
+
+ {10, 1, "b10", RISC_COLOR(0, 10, 0x1), NULL, 0, 0},
+ {10, 2, "h10", RISC_COLOR(0, 10, 0x3), NULL, 0, 0},
+ {10, 4, "x10", RISC_COLOR(0, 10, 0xf), NULL, 0, 0},
+
+ {11, 4, "fp", RISC_COLOR(0, 11, 0xf), NULL, 0, 0},
+
+ {12, 4, "x12", RISC_COLOR(0, 12, 0xf), NULL, 0, 0},
+
+ {13, 4, "sp", RISC_COLOR(0, 13, 0xf), NULL, 0, 0},
+
+ {14, 4, "lr", RISC_COLOR(0, 14, 0xf), NULL, 0, 0},
+
+// {15, 4, "pc", RISC_COLOR(0, 15, 0xf), NULL, 0, 0},
+
+#if 0
+ {0, 2, "h0", RISC_COLOR(1, 0, 0x3), NULL, 0, 0},
+ {0, 4, "s0", RISC_COLOR(1, 0, 0xf), NULL, 0, 0},
+ {0, 8, "d0", RISC_COLOR(1, 0, 0xff), NULL, 0, 0},
+
+ {1, 2, "h1", RISC_COLOR(1, 1, 0x3), NULL, 0, 0},
+ {1, 4, "s1", RISC_COLOR(1, 1, 0xf), NULL, 0, 0},
+ {1, 8, "d1", RISC_COLOR(1, 1, 0xff), NULL, 0, 0},
+
+ {2, 2, "h2", RISC_COLOR(1, 2, 0x3), NULL, 0, 0},
+ {2, 4, "s2", RISC_COLOR(1, 2, 0xf), NULL, 0, 0},
+ {2, 8, "d2", RISC_COLOR(1, 2, 0xff), NULL, 0, 0},
+
+ {3, 2, "h3", RISC_COLOR(1, 3, 0x3), NULL, 0, 0},
+ {3, 4, "s3", RISC_COLOR(1, 3, 0xf), NULL, 0, 0},
+ {3, 8, "d3", RISC_COLOR(1, 3, 0xff), NULL, 0, 0},
+
+ {4, 2, "h4", RISC_COLOR(1, 4, 0x3), NULL, 0, 0},
+ {4, 4, "s4", RISC_COLOR(1, 4, 0xf), NULL, 0, 0},
+ {4, 8, "d4", RISC_COLOR(1, 4, 0xff), NULL, 0, 0},
+
+ {5, 2, "h5", RISC_COLOR(1, 5, 0x3), NULL, 0, 0},
+ {5, 4, "s5", RISC_COLOR(1, 5, 0xf), NULL, 0, 0},
+ {5, 8, "d5", RISC_COLOR(1, 5, 0xff), NULL, 0, 0},
+
+ {6, 2, "h6", RISC_COLOR(1, 6, 0x3), NULL, 0, 0},
+ {6, 4, "s6", RISC_COLOR(1, 6, 0xf), NULL, 0, 0},
+ {6, 8, "d6", RISC_COLOR(1, 6, 0xff), NULL, 0, 0},
+
+ {7, 2, "h7", RISC_COLOR(1, 7, 0x3), NULL, 0, 0},
+ {7, 4, "s7", RISC_COLOR(1, 7, 0xf), NULL, 0, 0},
+ {7, 8, "d7", RISC_COLOR(1, 7, 0xff), NULL, 0, 0},
+
+ {8, 2, "h8", RISC_COLOR(1, 8, 0x3), NULL, 0, 0},
+ {8, 4, "s8", RISC_COLOR(1, 8, 0xf), NULL, 0, 0},
+ {8, 8, "d8", RISC_COLOR(1, 8, 0xff), NULL, 0, 0},
+
+ {9, 2, "h9", RISC_COLOR(1, 9, 0x3), NULL, 0, 0},
+ {9, 4, "s9", RISC_COLOR(1, 9, 0xf), NULL, 0, 0},
+ {9, 8, "d9", RISC_COLOR(1, 9, 0xff), NULL, 0, 0},
+
+ {10, 2, "h10", RISC_COLOR(1, 10, 0x3), NULL, 0, 0},
+ {10, 4, "s10", RISC_COLOR(1, 10, 0xf), NULL, 0, 0},
+ {10, 8, "d10", RISC_COLOR(1, 10, 0xff), NULL, 0, 0},
+
+ {11, 2, "h11", RISC_COLOR(1, 11, 0x3), NULL, 0, 0},
+ {11, 4, "s11", RISC_COLOR(1, 11, 0xf), NULL, 0, 0},
+ {11, 8, "d11", RISC_COLOR(1, 11, 0xff), NULL, 0, 0},
+
+ {12, 2, "h12", RISC_COLOR(1, 12, 0x3), NULL, 0, 0},
+ {12, 4, "s12", RISC_COLOR(1, 12, 0xf), NULL, 0, 0},
+ {12, 8, "d12", RISC_COLOR(1, 12, 0xff), NULL, 0, 0},
+
+ {13, 2, "h13", RISC_COLOR(1, 13, 0x3), NULL, 0, 0},
+ {13, 4, "s13", RISC_COLOR(1, 13, 0xf), NULL, 0, 0},
+ {13, 8, "d13", RISC_COLOR(1, 13, 0xff), NULL, 0, 0},
+
+ {14, 2, "h14", RISC_COLOR(1, 14, 0x3), NULL, 0, 0},
+ {14, 4, "s14", RISC_COLOR(1, 14, 0xf), NULL, 0, 0},
+ {14, 8, "d14", RISC_COLOR(1, 14, 0xff), NULL, 0, 0},
+
+ {15, 2, "h15", RISC_COLOR(1, 15, 0x3), NULL, 0, 0},
+ {15, 4, "s15", RISC_COLOR(1, 15, 0xf), NULL, 0, 0},
+ {15, 8, "d15", RISC_COLOR(1, 15, 0xff), NULL, 0, 0},
+
+ {16, 2, "h16", RISC_COLOR(1, 16, 0x3), NULL, 0, 0},
+ {16, 4, "s16", RISC_COLOR(1, 16, 0xf), NULL, 0, 0},
+ {16, 8, "d16", RISC_COLOR(1, 16, 0xff), NULL, 0, 0},
+
+ {17, 2, "h17", RISC_COLOR(1, 17, 0x3), NULL, 0, 0},
+ {17, 4, "s17", RISC_COLOR(1, 17, 0xf), NULL, 0, 0},
+ {17, 8, "d17", RISC_COLOR(1, 17, 0xff), NULL, 0, 0},
+
+ {18, 2, "h18", RISC_COLOR(1, 18, 0x3), NULL, 0, 0},
+ {18, 4, "s18", RISC_COLOR(1, 18, 0xf), NULL, 0, 0},
+ {18, 8, "d18", RISC_COLOR(1, 18, 0xff), NULL, 0, 0},
+
+ {19, 2, "h19", RISC_COLOR(1, 19, 0x3), NULL, 0, 0},
+ {19, 4, "s19", RISC_COLOR(1, 19, 0xf), NULL, 0, 0},
+ {19, 8, "d19", RISC_COLOR(1, 19, 0xff), NULL, 0, 0},
+
+ {20, 2, "h20", RISC_COLOR(1, 20, 0x3), NULL, 0, 0},
+ {20, 4, "s20", RISC_COLOR(1, 20, 0xf), NULL, 0, 0},
+ {20, 8, "d20", RISC_COLOR(1, 20, 0xff), NULL, 0, 0},
+
+ {21, 2, "h21", RISC_COLOR(1, 21, 0x3), NULL, 0, 0},
+ {21, 4, "s21", RISC_COLOR(1, 21, 0xf), NULL, 0, 0},
+ {21, 8, "d21", RISC_COLOR(1, 21, 0xff), NULL, 0, 0},
+
+ {22, 2, "h22", RISC_COLOR(1, 22, 0x3), NULL, 0, 0},
+ {22, 4, "s22", RISC_COLOR(1, 22, 0xf), NULL, 0, 0},
+ {22, 8, "d22", RISC_COLOR(1, 22, 0xff), NULL, 0, 0},
+
+ {23, 2, "h23", RISC_COLOR(1, 23, 0x3), NULL, 0, 0},
+ {23, 4, "s23", RISC_COLOR(1, 23, 0xf), NULL, 0, 0},
+ {23, 8, "d23", RISC_COLOR(1, 23, 0xff), NULL, 0, 0},
+
+ {24, 2, "h24", RISC_COLOR(1, 24, 0x3), NULL, 0, 0},
+ {24, 4, "s24", RISC_COLOR(1, 24, 0xf), NULL, 0, 0},
+ {24, 8, "d24", RISC_COLOR(1, 24, 0xff), NULL, 0, 0},
+
+ {25, 2, "h25", RISC_COLOR(1, 25, 0x3), NULL, 0, 0},
+ {25, 4, "s25", RISC_COLOR(1, 25, 0xf), NULL, 0, 0},
+ {25, 8, "d25", RISC_COLOR(1, 25, 0xff), NULL, 0, 0},
+
+ {26, 2, "h26", RISC_COLOR(1, 26, 0x3), NULL, 0, 0},
+ {26, 4, "s26", RISC_COLOR(1, 26, 0xf), NULL, 0, 0},
+ {26, 8, "d26", RISC_COLOR(1, 26, 0xff), NULL, 0, 0},
+
+ {27, 2, "h27", RISC_COLOR(1, 27, 0x3), NULL, 0, 0},
+ {27, 4, "s27", RISC_COLOR(1, 27, 0xf), NULL, 0, 0},
+ {27, 8, "d27", RISC_COLOR(1, 27, 0xff), NULL, 0, 0},
+
+ {28, 2, "h28", RISC_COLOR(1, 28, 0x3), NULL, 0, 0},
+ {28, 4, "s28", RISC_COLOR(1, 28, 0xf), NULL, 0, 0},
+ {28, 8, "d28", RISC_COLOR(1, 28, 0xff), NULL, 0, 0},
+
+ {29, 2, "h29", RISC_COLOR(1, 29, 0x3), NULL, 0, 0},
+ {29, 4, "s29", RISC_COLOR(1, 29, 0xf), NULL, 0, 0},
+ {29, 8, "d29", RISC_COLOR(1, 29, 0xff), NULL, 0, 0},
+
+ {30, 2, "h30", RISC_COLOR(1, 30, 0x3), NULL, 0, 0},
+ {30, 4, "s30", RISC_COLOR(1, 30, 0xf), NULL, 0, 0},
+ {30, 8, "d30", RISC_COLOR(1, 30, 0xff), NULL, 0, 0},
+
+ {31, 2, "h31", RISC_COLOR(1, 31, 0x3), NULL, 0, 0},
+ {31, 4, "s31", RISC_COLOR(1, 31, 0xf), NULL, 0, 0},
+ {31, 8, "d31", RISC_COLOR(1, 31, 0xff), NULL, 0, 0},
+#endif
+};
+
+static uint32_t arm32_abi_regs[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+};
+
+static uint32_t arm32_abi_float_regs[] =
+{
+ SCF_RISC_REG_D0,
+ SCF_RISC_REG_D1,
+ SCF_RISC_REG_D2,
+ SCF_RISC_REG_D3,
+ SCF_RISC_REG_D4,
+ SCF_RISC_REG_D5,
+ SCF_RISC_REG_D6,
+ SCF_RISC_REG_D7,
+};
+
+static uint32_t arm32_abi_ret_regs[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+};
+
+static uint32_t arm32_abi_caller_saves[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+};
+
+static uint32_t arm32_abi_callee_saves[] =
+{
+ SCF_RISC_REG_X4,
+ SCF_RISC_REG_X5,
+ SCF_RISC_REG_X6,
+ SCF_RISC_REG_X7,
+ SCF_RISC_REG_X8,
+ SCF_RISC_REG_X9,
+ SCF_RISC_REG_X10,
+ SCF_RISC_REG_X11,
+ SCF_RISC_REG_X13,
+ SCF_RISC_REG_X14,
+};
+
+static int arm32_variable_size(scf_variable_t* v)
+{
+ if (v->nb_dimentions > 0)
+ return 4;
+
+ if (v->nb_pointers > 0)
+ return 4;
+
+ if (v->type >= SCF_STRUCT)
+ return 4;
+
+ return v->size;
+}
+
+scf_register_t* arm32_find_register(const char* name)
+{
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (!strcmp(r->name, name))
+ return r;
+ }
+ return NULL;
+}
+
+scf_register_t* arm32_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes)
+{
+ int i;
+
+ if (bytes > 4 && 0 == type)
+ bytes = 4;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (RISC_COLOR_TYPE(r->color) == type && r->id == id && r->bytes == bytes)
+ return r;
+ }
+ return NULL;
+}
+
+scf_register_t* arm32_find_register_color(intptr_t color)
+{
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (r->color == color)
+ return r;
+ }
+ return NULL;
+}
+
+scf_register_t* arm32_find_register_color_bytes(intptr_t color, int bytes)
+{
+ int i;
+
+ if (bytes > 4 && 0 == RISC_COLOR_TYPE(color))
+ bytes = 4;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (RISC_COLOR_CONFLICT(r->color, color) && r->bytes == bytes)
+ return r;
+ }
+ return NULL;
+}
+
+scf_vector_t* arm32_register_colors()
+{
+ scf_vector_t* colors = scf_vector_alloc();
+ if (!colors)
+ return NULL;
+
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ int ret = scf_vector_add(colors, (void*)r->color);
+ if (ret < 0) {
+ scf_vector_free(colors);
+ return NULL;
+ }
+ }
+#if 0
+ srand(time(NULL));
+ for (i = 0; i < colors->size; i++) {
+ int j = rand() % colors->size;
+
+ void* t = colors->data[i];
+ colors->data[i] = colors->data[j];
+ colors->data[j] = t;
+ }
+#endif
+ return colors;
+}
+
+int arm32_reg_cached_vars(scf_register_t* r)
+{
+ int nb_vars = 0;
+ int i;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r2 = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r2->id
+ || SCF_RISC_REG_FP == r2->id
+ || SCF_RISC_REG_LR == r2->id
+ || SCF_RISC_REG_X12 == r2->id)
+ continue;
+
+ if (!RISC_COLOR_CONFLICT(r->color, r2->color))
+ continue;
+
+ nb_vars += r2->dag_nodes->size;
+ }
+
+ return nb_vars;
+}
+
+int arm32_registers_init()
+{
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ assert(!r->dag_nodes);
+
+ r->dag_nodes = scf_vector_alloc();
+ if (!r->dag_nodes)
+ return -ENOMEM;
+
+ r->used = 0;
+ }
+
+ return 0;
+}
+
+void arm32_registers_clear()
+{
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (r->dag_nodes) {
+ scf_vector_free(r->dag_nodes);
+ r->dag_nodes = NULL;
+ }
+
+ r->used = 0;
+ }
+}
+
+static scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs)
+{
+ scf_register_t* r_min = NULL;
+
+ int min = 0;
+ int i;
+
+ for (i = 0; i < nb_regs; i++) {
+ scf_register_t* r = regs[i];
+
+ int nb_vars = arm32_reg_cached_vars(r);
+
+ if (!r_min) {
+ r_min = r;
+ min = nb_vars;
+ continue;
+ }
+
+ if (min > nb_vars) {
+ r_min = r;
+ min = nb_vars;
+ }
+ }
+
+ return r_min;
+}
+
+int arm32_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs)
+{
+ int i;
+ int j;
+ scf_instruction_t* inst;
+ scf_register_t* r;
+ scf_register_t* r2;
+ scf_register_t* sp = arm32_find_register("sp");
+
+ uint32_t opcode;
+
+ int ret;
+ int size = 0;
+ int k = 0;
+
+ for (j = 0; j < nb_regs; j++) {
+ r2 = arm32_find_register_type_id_bytes(0, regs[j], f->rops->MAX_BYTES);
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+ r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (0 == r->dag_nodes->size)
+ continue;
+
+ if (RISC_COLOR_CONFLICT(r2->color, r->color))
+ break;
+ }
+
+ if (i == sizeof(arm32_registers) / sizeof(arm32_registers[0]))
+ continue;
+
+ if (stack_size > 0) {
+ ret = f->iops->G2P(c, f, r2, sp, size + stack_size, r2->bytes);
+ if (ret < 0)
+ return ret;
+ } else {
+ inst = f->iops->PUSH(NULL, r2);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ }
+
+ saved_regs[k++] = r2;
+ size += r2->bytes;
+ }
+
+ while (size & 0xf) {
+ r2 = saved_regs[k - 1];
+
+ if (stack_size > 0) {
+ ret = f->iops->G2P(c, f, r2, sp, size + stack_size, r2->bytes);
+ if (ret < 0)
+ return ret;
+
+ } else {
+ inst = f->iops->PUSH(NULL, r2);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ }
+
+ saved_regs[k++] = r2;
+ size += r2->bytes;
+ }
+
+ if (stack_size > 0) {
+ for (j = 0; j < k / 2; j++) {
+
+ i = k - 1 - j;
+ SCF_XCHG(saved_regs[i], saved_regs[j]);
+ }
+ }
+
+ return size;
+}
+
+int arm32_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated)
+{
+ int i;
+ int j;
+
+ scf_register_t* sp = arm32_find_register("sp");
+ scf_register_t* r;
+ scf_register_t* r2;
+ scf_instruction_t* inst;
+
+ for (j = nb_regs - 1; j >= 0; j--) {
+ r2 = regs[j];
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+ r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (0 == r->dag_nodes->size)
+ continue;
+
+ if (RISC_COLOR_CONFLICT(r2->color, r->color))
+ break;
+ }
+
+ if (i == sizeof(arm32_registers) / sizeof(arm32_registers[0]))
+ continue;
+
+ for (i = 0; i < nb_updated; i++) {
+
+ r = updated_regs[i];
+
+ if (RISC_COLOR_CONFLICT(r2->color, r->color))
+ break;
+ }
+
+ if (i == nb_updated) {
+ inst = f->iops->POP(c, r2);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ } else {
+ inst = f->iops->ADD_IMM(c, sp, sp, 4);
+ RISC_INST_ADD_CHECK(c->instructions, inst);
+ }
+ }
+ return 0;
+}
+
+int arm32_registers_reset()
+{
+ int i;
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (!r->dag_nodes)
+ continue;
+
+ int j = 0;
+ while (j < r->dag_nodes->size) {
+ scf_dag_node_t* dn = r->dag_nodes->data[j];
+
+ if (dn->var->w)
+ scf_logw("drop: v_%d_%d/%s\n", dn->var->w->line, dn->var->w->pos, dn->var->w->text->data);
+ else
+ scf_logw("drop: v_%#lx\n", 0xffff & (uintptr_t)dn->var);
+
+ int ret = scf_vector_del(r->dag_nodes, dn);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
+
+ dn->loaded = 0;
+ dn->color = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+int arm32_overflow_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f)
+{
+ int i;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r2 = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r2->id
+ || SCF_RISC_REG_FP == r2->id
+ || SCF_RISC_REG_LR == r2->id
+ || SCF_RISC_REG_X12 == r2->id)
+ continue;
+
+ if (!RISC_COLOR_CONFLICT(r->color, r2->color))
+ continue;
+
+ int ret = risc_save_reg(r2, c, f);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
+ }
+
+ r->used = 1;
+ return 0;
+}
+
+int arm32_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f)
+{
+ scf_register_t* r2;
+ scf_dag_node_t* dn2;
+
+ int i;
+ int j;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ r2 = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r2->id
+ || SCF_RISC_REG_FP == r2->id
+ || SCF_RISC_REG_LR == r2->id
+ || SCF_RISC_REG_X12 == r2->id)
+ continue;
+
+ if (!RISC_COLOR_CONFLICT(r->color, r2->color))
+ continue;
+
+ for (j = 0; j < r2->dag_nodes->size; ) {
+ dn2 = r2->dag_nodes->data[j];
+
+ if (dn2 == dn) {
+ j++;
+ continue;
+ }
+
+ int ret = risc_save_var(dn2, c, f);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ r->used = 1;
+ return 0;
+}
+
+int arm32_overflow_reg3(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f)
+{
+ scf_register_t* r2;
+ scf_dn_status_t* ds2;
+ scf_dag_node_t* dn2;
+
+ int i;
+ int j;
+ int ret;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ r2 = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r2->id
+ || SCF_RISC_REG_FP == r2->id
+ || SCF_RISC_REG_LR == r2->id
+ || SCF_RISC_REG_X12 == r2->id)
+ continue;
+
+ if (!RISC_COLOR_CONFLICT(r->color, r2->color))
+ continue;
+
+ for (j = 0; j < r2->dag_nodes->size; ) {
+ dn2 = r2->dag_nodes->data[j];
+
+ if (dn2 == dn) {
+ j++;
+ continue;
+ }
+
+ ds2 = scf_vector_find_cmp(c->active_vars, dn2, scf_dn_status_cmp);
+ if (!ds2) {
+ j++;
+ continue;
+ }
+
+ if (!ds2->active) {
+ j++;
+ continue;
+ }
+#if 1
+ scf_variable_t* v = dn->var;
+ scf_variable_t* v2 = dn2->var;
+ if (v->w)
+ scf_loge("v_%d_%d/%s, bp_offset: %d\n", v->w->line, v->w->pos, v->w->text->data, v->bp_offset);
+ else
+ scf_loge("v_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v, v->bp_offset);
+
+ if (v2->w)
+ scf_loge("v2_%d_%d/%s, bp_offset: %d\n", v2->w->line, v2->w->pos, v2->w->text->data, v2->bp_offset);
+ else
+ scf_loge("v2_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v2, v2->bp_offset);
+#endif
+ int ret = risc_save_var(dn2, c, f);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ r->used = 1;
+ return 0;
+}
+
+int arm32_reg_used(scf_register_t* r, scf_dag_node_t* dn)
+{
+ scf_register_t* r2;
+ scf_dag_node_t* dn2;
+
+ int i;
+ int j;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ r2 = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r2->id
+ || SCF_RISC_REG_FP == r2->id
+ || SCF_RISC_REG_LR == r2->id
+ || SCF_RISC_REG_X12 == r2->id)
+ continue;
+
+ if (!RISC_COLOR_CONFLICT(r->color, r2->color))
+ continue;
+
+ for (j = 0; j < r2->dag_nodes->size; j++) {
+ dn2 = r2->dag_nodes->data[j];
+
+ if (dn2 != dn)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+scf_register_t* arm32_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float)
+{
+ scf_vector_t* neighbors = NULL;
+ scf_graph_node_t* gn = NULL;
+ scf_register_t* free_regs[sizeof(arm32_registers) / sizeof(arm32_registers[0])];
+
+ int nb_free_regs = 0;
+ int bytes = 4;
+ int ret;
+ int i;
+ int j;
+
+ assert(c->rcg);
+
+ if (dn) {
+ is_float = scf_variable_float(dn->var);
+ bytes = arm32_variable_size (dn->var);
+ }
+
+ ret = risc_rcg_find_node(&gn, c->rcg, dn, NULL);
+ if (ret < 0)
+ neighbors = c->rcg->nodes;
+ else
+ neighbors = gn->neighbors;
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float)
+ continue;
+
+ for (j = 0; j < neighbors->size; j++) {
+
+ scf_graph_node_t* neighbor = neighbors->data[j];
+ risc_rcg_node_t* rn = neighbor->data;
+
+ if (rn->dag_node) {
+ if (rn->dag_node->color <= 0)
+ continue;
+
+ if (RISC_COLOR_CONFLICT(r->color, rn->dag_node->color))
+ break;
+ } else {
+ assert(rn->reg);
+
+ if (RISC_COLOR_CONFLICT(r->color, rn->reg->color))
+ break;
+ }
+ }
+
+ if (j == neighbors->size)
+ free_regs[nb_free_regs++] = r;
+ }
+
+ if (nb_free_regs > 0)
+ return risc_reg_cached_min_vars(free_regs, nb_free_regs);
+
+ for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) {
+
+ scf_register_t* r = &(arm32_registers[i]);
+
+ if (SCF_RISC_REG_SP == r->id
+ || SCF_RISC_REG_FP == r->id
+ || SCF_RISC_REG_LR == r->id
+ || SCF_RISC_REG_X12 == r->id)
+ continue;
+
+ if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float)
+ continue;
+
+ if (c->dsts) {
+ scf_3ac_operand_t* dst;
+
+ for (j = 0; j < c->dsts->size; j++) {
+ dst = c->dsts->data[j];
+
+ if (dst->dag_node && dst->dag_node->color > 0
+ && RISC_COLOR_CONFLICT(r->color, dst->dag_node->color))
+ break;
+ }
+
+ if (j < c->dsts->size)
+ continue;
+ }
+
+ if (c->srcs) {
+ scf_3ac_operand_t* src;
+
+ for (j = 0; j < c->srcs->size; j++) {
+ src = c->srcs->data[j];
+
+ if (src->dag_node && src->dag_node->color > 0
+ && RISC_COLOR_CONFLICT(r->color, src->dag_node->color))
+ break;
+ }
+
+ if (j < c->srcs->size)
+ continue;
+ }
+
+ return r;
+ }
+
+ return NULL;
+}
+
+scf_regs_ops_t regs_ops_arm32 =
+{
+ .name = "arm32",
+
+ .abi_regs = arm32_abi_regs,
+ .abi_float_regs = arm32_abi_float_regs,
+ .abi_ret_regs = arm32_abi_ret_regs,
+ .abi_caller_saves = arm32_abi_caller_saves,
+ .abi_callee_saves = arm32_abi_callee_saves,
+
+ .ABI_NB = sizeof(arm32_abi_regs) / sizeof(uint32_t),
+ .ABI_RET_NB = sizeof(arm32_abi_ret_regs) / sizeof(uint32_t),
+ .ABI_CALLER_SAVES_NB = sizeof(arm32_abi_caller_saves) / sizeof(uint32_t),
+ .ABI_CALLEE_SAVES_NB = sizeof(arm32_abi_callee_saves) / sizeof(uint32_t),
+
+ .MAX_BYTES = 4,
+
+ .registers_init = arm32_registers_init,
+ .registers_reset = arm32_registers_reset,
+ .registers_clear = arm32_registers_clear,
+ .register_colors = arm32_register_colors,
+
+ .reg_used = arm32_reg_used,
+ .reg_cached_vars = arm32_reg_cached_vars,
+
+ .variable_size = arm32_variable_size,
+
+ .caller_save_regs = arm32_caller_save_regs,
+ .pop_regs = arm32_pop_regs,
+
+ .find_register = arm32_find_register,
+ .find_register_color = arm32_find_register_color,
+ .find_register_color_bytes = arm32_find_register_color_bytes,
+ .find_register_type_id_bytes = arm32_find_register_type_id_bytes,
+
+ .select_overflowed_reg = arm32_select_overflowed_reg,
+ .overflow_reg = arm32_overflow_reg,
+ .overflow_reg2 = arm32_overflow_reg2,
+ .overflow_reg3 = arm32_overflow_reg3,
+};
+
#include"scf_risc.h"
+#define SCF_RISC_REG_FP 29
+#define SCF_RISC_REG_LR 30
+#define SCF_RISC_REG_SP 31
+
scf_register_t arm64_registers[] = {
{0, 4, "w0", RISC_COLOR(0, 0, 0xf), NULL, 0, 0},
{31, 8, "d31", RISC_COLOR(1, 31, 0xff), NULL, 0, 0},
};
+static uint32_t arm64_abi_regs[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+ SCF_RISC_REG_X4,
+ SCF_RISC_REG_X5,
+ SCF_RISC_REG_X6,
+ SCF_RISC_REG_X7,
+};
+
+static uint32_t arm64_abi_float_regs[] =
+{
+ SCF_RISC_REG_D0,
+ SCF_RISC_REG_D1,
+ SCF_RISC_REG_D2,
+ SCF_RISC_REG_D3,
+ SCF_RISC_REG_D4,
+ SCF_RISC_REG_D5,
+ SCF_RISC_REG_D6,
+ SCF_RISC_REG_D7,
+};
+
+static uint32_t arm64_abi_ret_regs[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+};
+
+static uint32_t arm64_abi_caller_saves[] =
+{
+ SCF_RISC_REG_X0,
+ SCF_RISC_REG_X1,
+ SCF_RISC_REG_X2,
+ SCF_RISC_REG_X3,
+ SCF_RISC_REG_X4,
+ SCF_RISC_REG_X5,
+ SCF_RISC_REG_X6,
+ SCF_RISC_REG_X7,
+
+ SCF_RISC_REG_X9,
+ SCF_RISC_REG_X10,
+ SCF_RISC_REG_X11,
+ SCF_RISC_REG_X12,
+ SCF_RISC_REG_X13,
+ SCF_RISC_REG_X14,
+ SCF_RISC_REG_X15,
+};
+
+static uint32_t arm64_abi_callee_saves[] =
+{
+ SCF_RISC_REG_X19,
+ SCF_RISC_REG_X20,
+ SCF_RISC_REG_X21,
+ SCF_RISC_REG_X22,
+ SCF_RISC_REG_X23,
+ SCF_RISC_REG_X24,
+ SCF_RISC_REG_X25,
+ SCF_RISC_REG_X26,
+ SCF_RISC_REG_X27,
+ SCF_RISC_REG_X28,
+ SCF_RISC_REG_X29,
+ SCF_RISC_REG_X30,
+};
+
+static int arm64_variable_size(scf_variable_t* v)
+{
+ if (v->nb_dimentions > 0)
+ return 8;
+
+ if (v->type >= SCF_STRUCT && 0 == v->nb_pointers)
+ return 8;
+
+ return v->size < 4 ? 4 : v->size;
+}
+
scf_register_t* arm64_find_register(const char* name)
{
int i;
}
}
-scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs)
+static scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs)
{
scf_register_t* r_min = NULL;
if (dn) {
is_float = scf_variable_float(dn->var);
- bytes = risc_variable_size (dn->var);
+ bytes = arm64_variable_size (dn->var);
}
ret = risc_rcg_find_node(&gn, c->rcg, dn, NULL);
return NULL;
}
+#define RISC_ABI_NB (sizeof(arm64_abi_regs) / sizeof(arm64_abi_regs[0]))
+#define RISC_ABI_RET_NB (sizeof(risc_abi_ret_regs) / sizeof(risc_abi_ret_regs[0]))
+#define RISC_ABI_CALLER_SAVES_NB (sizeof(risc_abi_caller_saves) / sizeof(risc_abi_caller_saves[0]))
+#define RISC_ABI_CALLEE_SAVES_NB (sizeof(risc_abi_callee_saves) / sizeof(risc_abi_callee_saves[0]))
+
scf_regs_ops_t regs_ops_arm64 =
{
.name = "arm64",
+ .abi_regs = arm64_abi_regs,
+ .abi_float_regs = arm64_abi_float_regs,
+ .abi_ret_regs = arm64_abi_ret_regs,
+ .abi_caller_saves = arm64_abi_caller_saves,
+ .abi_callee_saves = arm64_abi_callee_saves,
+
+ .ABI_NB = sizeof(arm64_abi_regs) / sizeof(uint32_t),
+ .ABI_RET_NB = sizeof(arm64_abi_ret_regs) / sizeof(uint32_t),
+ .ABI_CALLER_SAVES_NB = sizeof(arm64_abi_caller_saves) / sizeof(uint32_t),
+ .ABI_CALLEE_SAVES_NB = sizeof(arm64_abi_callee_saves) / sizeof(uint32_t),
+
+ .MAX_BYTES = 8,
+
.registers_init = arm64_registers_init,
.registers_reset = arm64_registers_reset,
.registers_clear = arm64_registers_clear,
.reg_used = arm64_reg_used,
.reg_cached_vars = arm64_reg_cached_vars,
+ .variable_size = arm64_variable_size,
+
.caller_save_regs = arm64_caller_save_regs,
.pop_regs = arm64_pop_regs,
{
.name = "naja",
+ .abi_regs = arm64_abi_regs,
+ .abi_float_regs = arm64_abi_float_regs,
+ .abi_ret_regs = arm64_abi_ret_regs,
+ .abi_caller_saves = arm64_abi_caller_saves,
+ .abi_callee_saves = arm64_abi_callee_saves,
+
+ .ABI_NB = sizeof(arm64_abi_regs) / sizeof(uint32_t),
+ .ABI_RET_NB = sizeof(arm64_abi_ret_regs) / sizeof(uint32_t),
+ .ABI_CALLER_SAVES_NB = sizeof(arm64_abi_caller_saves) / sizeof(uint32_t),
+ .ABI_CALLEE_SAVES_NB = sizeof(arm64_abi_callee_saves) / sizeof(uint32_t),
+
+ .MAX_BYTES = 8,
+
.registers_init = arm64_registers_init,
.registers_reset = arm64_registers_reset,
.registers_clear = arm64_registers_clear,
.reg_used = arm64_reg_used,
.reg_cached_vars = arm64_reg_cached_vars,
+ .variable_size = arm64_variable_size,
+
.caller_save_regs = arm64_caller_save_regs,
.pop_regs = arm64_pop_regs,
SCF_RISC_REG_X28 = 28,
SCF_RISC_REG_X29 = 29,
- SCF_RISC_REG_FP = 29,
SCF_RISC_REG_X30 = 30,
- SCF_RISC_REG_LR = 30,
- SCF_RISC_REG_SP = 31,
+ SCF_RISC_REG_X31 = 31,
};
enum scf_risc_EG_types {
{
const char* name;
+ uint32_t* abi_regs;
+ uint32_t* abi_float_regs;
+ uint32_t* abi_ret_regs;
+ uint32_t* abi_caller_saves;
+ uint32_t* abi_callee_saves;
+
+ const int ABI_NB;
+ const int ABI_RET_NB;
+ const int ABI_CALLER_SAVES_NB;
+ const int ABI_CALLEE_SAVES_NB;
+
+ const int MAX_BYTES;
+
int (*registers_init )();
int (*registers_reset )();
void (*registers_clear )();
int (*reg_used )(scf_register_t* r, scf_dag_node_t* dn);
int (*reg_cached_vars )(scf_register_t* r);
+ int (*variable_size )(scf_variable_t* v);
+
int (*caller_save_regs)(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs);
int (*pop_regs )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated);
{
const char* name;
- scf_instruction_t* (*BL )(scf_3ac_code_t* c);
+ int (*BL )(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf);
scf_instruction_t* (*BLR )(scf_3ac_code_t* c, scf_register_t* r);
scf_instruction_t* (*PUSH )(scf_3ac_code_t* c, scf_register_t* r);
scf_instruction_t* (*POP )(scf_3ac_code_t* c, scf_register_t* r);
scf_instruction_t* (*ADD_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm);
scf_instruction_t* (*SUB_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*SUB_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm);
- scf_instruction_t* (*CMP_G)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*CMP_IMM)(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm);
- scf_instruction_t* (*AND_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*OR_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*CMP_G )(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*CMP_IMM )(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm);
+ scf_instruction_t* (*AND_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*OR_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*MUL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*DIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*SDIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*MSUB )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra);
- scf_instruction_t* (*SHL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*SHR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*ASR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*SHL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*SHR )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*ASR )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
scf_instruction_t* (*CVTSS2SD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
scf_instruction_t* (*CVTSD2SS)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
- scf_instruction_t* (*CVTF2SI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
- scf_instruction_t* (*CVTF2UI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
- scf_instruction_t* (*CVTSI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
- scf_instruction_t* (*CVTUI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
-
- scf_instruction_t* (*FCMP)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*FADD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*FSUB)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*FMUL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*FDIV)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
- scf_instruction_t* (*FMOV_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
-
- scf_instruction_t* (*JA )(scf_3ac_code_t* c);
- scf_instruction_t* (*JB )(scf_3ac_code_t* c);
- scf_instruction_t* (*JZ )(scf_3ac_code_t* c);
- scf_instruction_t* (*JNZ)(scf_3ac_code_t* c);
- scf_instruction_t* (*JGT)(scf_3ac_code_t* c);
- scf_instruction_t* (*JGE)(scf_3ac_code_t* c);
- scf_instruction_t* (*JLT)(scf_3ac_code_t* c);
- scf_instruction_t* (*JLE)(scf_3ac_code_t* c);
- scf_instruction_t* (*JMP)(scf_3ac_code_t* c);
- scf_instruction_t* (*JAE)(scf_3ac_code_t* c);
- scf_instruction_t* (*JBE)(scf_3ac_code_t* c);
- scf_instruction_t* (*RET)(scf_3ac_code_t* c);
-
- scf_instruction_t* (*SETZ )(scf_3ac_code_t* c, scf_register_t* rd);
- scf_instruction_t* (*SETNZ)(scf_3ac_code_t* c, scf_register_t* rd);
- scf_instruction_t* (*SETGT)(scf_3ac_code_t* c, scf_register_t* rd);
- scf_instruction_t* (*SETGE)(scf_3ac_code_t* c, scf_register_t* rd);
- scf_instruction_t* (*SETLT)(scf_3ac_code_t* c, scf_register_t* rd);
- scf_instruction_t* (*SETLE)(scf_3ac_code_t* c, scf_register_t* rd);
-
- int (*I2G )(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes);
- int (*M2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs);
- int (*M2GF )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs);
- int (*G2M )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs);
- int (*G2P )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size);
- int (*P2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size);
- int (*ISTR2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs);
- int (*SIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
- int (*G2SIB )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
- int (*ADR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs);
- int (*ADRP2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset);
-
- int (*ADRSIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
- int (*cmp_update)(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* inst);
+ scf_instruction_t* (*CVTF2SI )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
+ scf_instruction_t* (*CVTF2UI )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
+ scf_instruction_t* (*CVTSI2F )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
+ scf_instruction_t* (*CVTUI2F )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
+
+ scf_instruction_t* (*FCMP )(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*FADD )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*FSUB )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*FMUL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*FDIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1);
+ scf_instruction_t* (*FMOV_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs);
+
+ scf_instruction_t* (*JA )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JB )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JZ )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JNZ )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JGT )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JGE )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JLT )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JLE )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JMP )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JAE )(scf_3ac_code_t* c);
+ scf_instruction_t* (*JBE )(scf_3ac_code_t* c);
+ scf_instruction_t* (*RET )(scf_3ac_code_t* c);
+
+ scf_instruction_t* (*SETZ )(scf_3ac_code_t* c, scf_register_t* rd);
+ scf_instruction_t* (*SETNZ )(scf_3ac_code_t* c, scf_register_t* rd);
+ scf_instruction_t* (*SETGT )(scf_3ac_code_t* c, scf_register_t* rd);
+ scf_instruction_t* (*SETGE )(scf_3ac_code_t* c, scf_register_t* rd);
+ scf_instruction_t* (*SETLT )(scf_3ac_code_t* c, scf_register_t* rd);
+ scf_instruction_t* (*SETLE )(scf_3ac_code_t* c, scf_register_t* rd);
+
+ int (*I2G )(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes);
+ int (*M2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs);
+ int (*M2GF )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs);
+ int (*G2M )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs);
+ int (*G2P )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size);
+ int (*P2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size);
+ int (*ISTR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs);
+ int (*SIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
+ int (*G2SIB )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
+ int (*ADR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs);
+ int (*ADRP2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset);
+ int (*ADRSIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib);
+
+ int (*cmp_update )(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* inst);
+ int (*set_rel_veneer)(scf_function_t* f);
void (*set_jmp_offset)(scf_instruction_t* inst, int32_t bytes);
};
CFILES += ../native/risc/scf_risc_rcg.c
CFILES += ../native/risc/scf_risc_reg.c
CFILES += ../native/risc/scf_risc_reg_arm64.c
+CFILES += ../native/risc/scf_risc_reg_arm32.c
CFILES += ../native/risc/scf_arm64.c
+CFILES += ../native/risc/scf_arm32.c
CFILES += ../native/risc/scf_naja.c
CFILES += ../elf/scf_elf.c
CFILES += ../elf/scf_elf_link.c
CFILES += ../elf/scf_elf_native.c
+CFILES += ../elf/scf_elf_native32.c
CFILES += ../elf/scf_elf_x64.c
CFILES += ../elf/scf_elf_x64_so.c
CFILES += ../elf/scf_elf_arm64.c
CFILES += ../elf/scf_elf_arm64_so.c
+CFILES += ../elf/scf_elf_arm32.c
+CFILES += ../elf/scf_elf_arm32_so.c
CFILES += ../elf/scf_elf_naja.c
CFILES += ../elf/scf_elf_naja_so.c
CFILES += ../elf/scf_dwarf.c
"../lib/arm64/libc.so.6",
};
+static char* __arm32_objs[] =
+{
+ "../lib/arm32/_start.o",
+};
+
+static char* __arm32_sofiles[] =
+{
+ "../lib/arm32//lib/ld-linux-armhf.so.3",
+ "../lib/arm32/libc.so.6",
+};
+
void usage(char* path)
{
fprintf(stderr, "Usage: %s [-c] [-a arch] [-o out] src0 [src1]\n\n", path);
if (!strcmp(arch, "arm64") || !strcmp(arch, "naja"))
MAIN_ADD_FILES(__arm64_objs, __arm64_sofiles);
+
+ else if (!strcmp(arch, "arm32"))
+ MAIN_ADD_FILES(__arm32_objs, __arm32_sofiles);
else
MAIN_ADD_FILES(__objs, __sofiles);
s.sh_link = 0;
s.sh_info = SCF_SHNDX_DATA;
+ if (!strcmp(elf->ops->machine, "arm32")) {
+
+ for (i = 0; i < relas->size; i++) {
+ rela = relas->data[i];
+
+ rela->r_info = ELF32_R_INFO(ELF64_R_SYM(rela->r_info), ELF64_R_TYPE(rela->r_info));
+ }
+ }
+
ret = scf_elf_add_rela_section(elf, &s, relas);
}
error:
static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_elf_context_t* elf, int sh_index, const char* sh_name)
{
- scf_elf_sym_t* sym;
- scf_vector_t* relas;
- scf_rela_t* r;
+ scf_elf_rela_t* rela;
+ scf_elf_sym_t* sym;
+ scf_vector_t* relas;
+ scf_rela_t* r;
int ret;
int i;
return -EINVAL;
}
- scf_elf_rela_t* rela = calloc(1, sizeof(scf_elf_rela_t));
+ rela = calloc(1, sizeof(scf_elf_rela_t));
if (!rela)
return -ENOMEM;
s.sh_link = 0;
s.sh_info = sh_index;
+ if (!strcmp(elf->ops->machine, "arm32")) {
+
+ for (i = 0; i < relas->size; i++) {
+ rela = relas->data[i];
+
+ rela->r_info = ELF32_R_INFO(ELF64_R_SYM(rela->r_info), ELF64_R_TYPE(rela->r_info));
+ }
+ }
+
ret = scf_elf_add_rela_section(elf, &s, relas);
#endif
if (relas->size > 0) {
scf_elf_section_t s = {0};
+ scf_elf_rela_t* r;
s.name = ".rela.text";
s.sh_type = SHT_RELA;
s.sh_link = 0;
s.sh_info = SCF_SHNDX_TEXT;
+ if (!strcmp(elf->ops->machine, "arm32")) {
+
+ for (i = 0; i < relas->size; i++) {
+ r = relas->data[i];
+
+ r->r_info = ELF32_R_INFO(ELF64_R_SYM(r->r_info), ELF64_R_TYPE(r->r_info));
+ }
+ }
+
ret = scf_elf_add_rela_section(elf, &s, relas);
}
error:
CFILES += ../elf/scf_elf.c
CFILES += ../elf/scf_elf_link.c
CFILES += ../elf/scf_elf_native.c
+CFILES += ../elf/scf_elf_native32.c
CFILES += ../elf/scf_elf_x64.c
CFILES += ../elf/scf_elf_x64_so.c
CFILES += ../elf/scf_elf_arm64.c
CFILES += ../elf/scf_elf_arm64_so.c
+CFILES += ../elf/scf_elf_arm32.c
+CFILES += ../elf/scf_elf_arm32_so.c
CFILES += ../elf/scf_elf_naja.c
CFILES += ../elf/scf_elf_naja_so.c
CFILES += ../elf/scf_dwarf.c