support arm32: 'hanoi.c' and 'hello.c' of 'scf/examples' test ok
authoryu.dongliang <18588496441@163.com>
Sun, 14 May 2023 09:24:15 +0000 (17:24 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 14 May 2023 09:24:51 +0000 (17:24 +0800)
33 files changed:
elf/scf_dwarf_info.c
elf/scf_dwarf_line.c
elf/scf_elf.c
elf/scf_elf_arm32.c [new file with mode: 0644]
elf/scf_elf_arm32.h [new file with mode: 0644]
elf/scf_elf_arm32_so.c [new file with mode: 0644]
elf/scf_elf_link.c
elf/scf_elf_native.h
elf/scf_elf_native32.c [new file with mode: 0644]
elf/scf_elf_native32.h [new file with mode: 0644]
lib/arm32/_start.o [new file with mode: 0644]
lib/arm32/_start.s [new file with mode: 0644]
lib/arm32/lib/ld-linux-armhf.so.3 [new file with mode: 0755]
lib/arm32/libc.so.6 [new file with mode: 0755]
native/risc/scf_arm32.c [new file with mode: 0644]
native/risc/scf_arm64.c
native/risc/scf_naja.c
native/risc/scf_risc.c
native/risc/scf_risc.h
native/risc/scf_risc_bb_color.c
native/risc/scf_risc_graph.c
native/risc/scf_risc_inst.c
native/risc/scf_risc_rcg.c
native/risc/scf_risc_reg.c
native/risc/scf_risc_reg.h
native/risc/scf_risc_reg_arm32.c [new file with mode: 0644]
native/risc/scf_risc_reg_arm64.c
native/risc/scf_risc_util.h
native/scf_native.h
parse/Makefile
parse/main.c
parse/scf_parse2.c
vm/Makefile

index 818f87865139f6a1739dbfdaa1c6a3ecdd308b97..b270d169c29e8117cad9223925eeb89cedc94d21 100644 (file)
@@ -330,6 +330,21 @@ static int _add_rela_common(scf_dwarf_debug_t* debug, const char* sym, uint64_t
                                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;
index ac44410159b525fdd4798837ea575052fd29232b..0bd4fb37871ecbab2e9505fe43a51fcc7f488ce0 100644 (file)
@@ -683,6 +683,8 @@ int scf_dwarf_line_encode(scf_dwarf_debug_t* debug, scf_dwarf_line_machine_t* lm
 
                        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);
                }
index 60a4ef417438ad4fcf3bedb451e22a5de53c5b85..1764f53763ca99b8bc713ff41bab93d7a5e3667d 100644 (file)
@@ -2,12 +2,14 @@
 
 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,
diff --git a/elf/scf_elf_arm32.c b/elf/scf_elf_arm32.c
new file mode 100644 (file)
index 0000000..cdedc55
--- /dev/null
@@ -0,0 +1,463 @@
+#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,
+};
+
diff --git a/elf/scf_elf_arm32.h b/elf/scf_elf_arm32.h
new file mode 100644 (file)
index 0000000..bc606f3
--- /dev/null
@@ -0,0 +1,20 @@
+#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
+
diff --git a/elf/scf_elf_arm32_so.c b/elf/scf_elf_arm32_so.c
new file mode 100644 (file)
index 0000000..60f078b
--- /dev/null
@@ -0,0 +1,894 @@
+#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;
+}
+
index 514f16f7f30a1f00e001af07dcea95c2f4f27b32..c1de02e671ff7903337309e9b50eeb7bc3d1a90b 100644 (file)
@@ -274,9 +274,17 @@ int scf_elf_file_read(scf_elf_file_t* ef)
 #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);
 
@@ -425,7 +433,7 @@ sym_error:
        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;
@@ -435,7 +443,11 @@ static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int
                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)
@@ -453,6 +465,8 @@ static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int
                        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;
@@ -517,6 +531,8 @@ static int merge_syms(scf_elf_file_t* exec, scf_elf_file_t* obj)
                        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;
@@ -531,13 +547,13 @@ static int merge_syms(scf_elf_file_t* exec, scf_elf_file_t* obj)
        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; \
@@ -581,7 +597,14 @@ static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj)
 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;
@@ -599,7 +622,9 @@ static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const
                        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;
@@ -612,14 +637,19 @@ static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const
        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);
 
@@ -716,6 +746,12 @@ static int merge_ar_obj(scf_elf_file_t* exec, scf_ar_file_t* ar, uint32_t offset
 {
        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");
@@ -741,7 +777,7 @@ static int merge_ar_obj(scf_elf_file_t* exec, scf_ar_file_t* ar, uint32_t offset
                return -1;
        }
 
-       ret = merge_obj(exec, obj);
+       ret = merge_obj(exec, obj, bits);
        if (ret < 0) {
                scf_loge("\n");
                return -1;
@@ -801,6 +837,12 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char*
        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) {
@@ -831,15 +873,19 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char*
                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;
@@ -896,7 +942,10 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char*
                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);
@@ -906,13 +955,17 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char*
                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;
@@ -942,7 +995,10 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char*
                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;
index 179b4b53b5ec90612a12e54cf425dbb1307f419e..d36abc1a476cb01f51496266eede180b660fe857 100644 (file)
@@ -90,6 +90,9 @@ int  elf_read_syms   (scf_elf_context_t* elf, scf_vector_t* syms,  const char* s
 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);
diff --git a/elf/scf_elf_native32.c b/elf/scf_elf_native32.c
new file mode 100644 (file)
index 0000000..70384a8
--- /dev/null
@@ -0,0 +1,1098 @@
+#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));
+               }
+       }
+}
+
diff --git a/elf/scf_elf_native32.h b/elf/scf_elf_native32.h
new file mode 100644 (file)
index 0000000..ca53874
--- /dev/null
@@ -0,0 +1,154 @@
+#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
+
diff --git a/lib/arm32/_start.o b/lib/arm32/_start.o
new file mode 100644 (file)
index 0000000..9aa3713
Binary files /dev/null and b/lib/arm32/_start.o differ
diff --git a/lib/arm32/_start.s b/lib/arm32/_start.s
new file mode 100644 (file)
index 0000000..cc8b58a
--- /dev/null
@@ -0,0 +1,8 @@
+.text
+.global _start, main
+
+_start:
+       bl   main
+       mov  r7, #1
+       swi  #0
+.fill 4, 1, 0
diff --git a/lib/arm32/lib/ld-linux-armhf.so.3 b/lib/arm32/lib/ld-linux-armhf.so.3
new file mode 100755 (executable)
index 0000000..27cf789
Binary files /dev/null and b/lib/arm32/lib/ld-linux-armhf.so.3 differ
diff --git a/lib/arm32/libc.so.6 b/lib/arm32/libc.so.6
new file mode 100755 (executable)
index 0000000..9a76155
Binary files /dev/null and b/lib/arm32/libc.so.6 differ
diff --git a/native/risc/scf_arm32.c b/native/risc/scf_arm32.c
new file mode 100644 (file)
index 0000000..20e6d94
--- /dev/null
@@ -0,0 +1,1954 @@
+#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,
+};
+
index d51f81050c11a3e9f711ede7e33522bd527b9841..b23801b968a374ca52589470fcad0377fe9934f4 100644 (file)
@@ -70,7 +70,7 @@ int arm64_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, s
        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) {
 
@@ -130,7 +130,7 @@ int arm64_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf
        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) {
@@ -251,7 +251,7 @@ int arm64_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf
        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) {
@@ -356,7 +356,7 @@ int arm64_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd,
        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);
@@ -716,7 +716,7 @@ int arm64_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc
        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) {
@@ -1305,15 +1305,20 @@ scf_instruction_t* arm64_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_re
        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)
index 2fa5c4f89425744b1f040517be7fcf7d156fdffe..40d0ea4e43de7295e07f71db12de91e1b806d1ce 100644 (file)
@@ -70,7 +70,7 @@ int naja_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc
        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) {
 
@@ -120,16 +120,16 @@ int naja_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc
 
 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) {
@@ -228,16 +228,16 @@ int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
 
 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) {
@@ -340,7 +340,7 @@ int naja_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, s
        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);
@@ -1125,15 +1125,20 @@ scf_instruction_t* naja_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_reg
        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)
index f338387bbf1ed2fc83a8c25159d0a79f9265a395..5f46cdba81a1b14f32b6ee824a282061f02377cb 100644 (file)
@@ -4,14 +4,17 @@
 #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
@@ -20,6 +23,7 @@ static scf_inst_ops_t*   inst_ops_array[] =
 static scf_regs_ops_t*   regs_ops_array[] =
 {
        &regs_ops_arm64,
+       &regs_ops_arm32,
        &regs_ops_naja,
 
        NULL
@@ -81,7 +85,7 @@ static void _risc_argv_rabi(scf_function_t* f)
        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;
@@ -93,22 +97,22 @@ static void _risc_argv_rabi(scf_function_t* f)
                        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++;
@@ -138,7 +142,7 @@ static int _risc_function_init(scf_function_t* f, scf_vector_t* local_vars)
 
        _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];
@@ -281,12 +285,12 @@ static int _risc_function_finish(scf_native_t* ctx, scf_function_t* f)
                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;
@@ -580,7 +584,7 @@ static int _risc_select_bb_regs(scf_basic_block_t* bb, scf_native_t* ctx)
                goto error;
        }
 
-       ret = scf_risc_graph_kcolor(g, 16, colors);
+       ret = scf_risc_graph_kcolor(g, 16, colors, f);
        if (ret < 0)
                goto error;
 
@@ -631,7 +635,7 @@ static int _risc_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx)
                goto error;
        }
 
-       ret = scf_risc_graph_kcolor(g, 16, colors);
+       ret = scf_risc_graph_kcolor(g, 16, colors, f);
        if (ret < 0)
                goto error;
 
@@ -1193,6 +1197,10 @@ int scf_risc_select_inst(scf_native_t* ctx, scf_function_t* f)
 
        _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;
 }
 
index 4259da16c67343de283f63c2b4ae5ba993de3506..3821c12f41a650ce0cca6b53a6d338a0ddd5fa84 100644 (file)
@@ -82,7 +82,7 @@ int scf_risc_select(scf_native_t* ctx);
 
 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);
index a65991fb5c076b15ba48f3cf0cab986181135d30..ee58d60b72a8bef45b5d62f908a677c87da16c00 100644 (file)
@@ -170,8 +170,6 @@ int risc_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_b
 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;
index f05b156abdb2739cf4f6984bb35a6233317dd689..6765e791fc40b7b683734b34db851d72401a14fa 100644 (file)
@@ -1,7 +1,7 @@
 #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;
 
@@ -16,7 +16,7 @@ static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors)
                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;
        }
@@ -111,7 +111,7 @@ static int _risc_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted_
 }
 
 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;
@@ -157,7 +157,7 @@ static int _risc_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors,
                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);
@@ -336,7 +336,7 @@ static void _risc_kcolor_process_conflict(scf_graph_t* graph)
        }
 }
 
-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;
@@ -354,7 +354,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
        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;
 
@@ -386,12 +386,12 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
                        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;
 
@@ -409,7 +409,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
                        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;
 
@@ -436,7 +436,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
                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;
 
@@ -460,7 +460,7 @@ overflow:
                        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;
 
@@ -469,7 +469,7 @@ overflow:
                        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;
 
@@ -487,7 +487,7 @@ 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");
@@ -496,7 +496,7 @@ int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors)
 
        _risc_kcolor_process_conflict(graph);
 
-       return _risc_graph_kcolor(graph, k, colors);
+       return _risc_graph_kcolor(graph, k, colors, f);
 }
 
 
index d6bedbd7162f39165a60cb3993ce59cbc9df3b9a..560275f1c5f6fd0fbc1978e244f5d408a0200adb 100644 (file)
@@ -29,7 +29,7 @@
        }
 
 
-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;
 
@@ -41,7 +41,7 @@ static int _risc_inst_call_stack_size(scf_3ac_code_t* c)
                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;
 
@@ -63,7 +63,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi
        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;
 
@@ -71,14 +71,15 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi
        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);
@@ -90,16 +91,19 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi
                        }
                }
 
+               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) {
@@ -116,7 +120,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi
                                        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)
@@ -153,7 +157,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi
                        }
 
                        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) {
@@ -228,7 +232,7 @@ static int _risc_call_save_ret_regs(scf_3ac_code_t* c, scf_function_t* f, scf_fu
 
                        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) {
@@ -254,7 +258,7 @@ static int _risc_dst_reg_valid(scf_function_t* f, scf_register_t* rd, scf_regist
 
        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;
@@ -308,7 +312,7 @@ static int _risc_call_update_dsts(scf_native_t* ctx, scf_3ac_code_t* c, scf_func
                        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) {
@@ -328,7 +332,7 @@ static int _risc_call_update_dsts(scf_native_t* ctx, scf_3ac_code_t* c, scf_func
 
                        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);
 
@@ -408,12 +412,16 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                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");
@@ -429,9 +437,6 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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;
@@ -460,7 +465,7 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
        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);
@@ -474,14 +479,16 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                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);
@@ -517,19 +524,33 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                                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);
@@ -559,11 +580,11 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        }
 
        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;
@@ -571,7 +592,7 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        }
 
        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;
@@ -827,7 +848,7 @@ static int _risc_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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) {
 
@@ -980,7 +1001,7 @@ static int _risc_inst_inc_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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)
@@ -1047,7 +1068,7 @@ static int _risc_inst_dec_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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)
@@ -1122,7 +1143,7 @@ static int _risc_inst_inc_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t
        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)
@@ -1200,7 +1221,7 @@ static int _risc_inst_dec_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t
        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)
@@ -1814,7 +1835,7 @@ static int _risc_inst_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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) {
@@ -1963,7 +1984,7 @@ static int _risc_inst_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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;
@@ -3291,8 +3312,8 @@ static int _risc_inst_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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);
 
@@ -3585,8 +3606,8 @@ static int _risc_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
                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");
@@ -3607,7 +3628,7 @@ static int _risc_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                        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)
@@ -3714,7 +3735,7 @@ static int _risc_inst_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 #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) { \
@@ -3769,12 +3790,12 @@ static int _risc_inst_end_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        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;
@@ -3998,7 +4019,7 @@ static int _risc_inst_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
        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);
@@ -5011,7 +5032,7 @@ static int _risc_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code
        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;
@@ -5093,7 +5114,7 @@ static int _risc_inst_add_assign_array_index_handler(scf_native_t* ctx, scf_3ac_
        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;
@@ -5192,7 +5213,7 @@ static int _risc_inst_sub_assign_array_index_handler(scf_native_t* ctx, scf_3ac_
        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;
@@ -5293,7 +5314,7 @@ static int _risc_inst_and_assign_array_index_handler(scf_native_t* ctx, scf_3ac_
        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;
@@ -5383,7 +5404,7 @@ static int _risc_inst_or_assign_array_index_handler(scf_native_t* ctx, scf_3ac_c
        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;
index 23af8420f083413eb700048bb2d48afbbc4732aa..c106364d5b32eec888a4edc2c2cd8e9afacee507 100644 (file)
@@ -302,7 +302,7 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
 
        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;
                }
@@ -321,13 +321,13 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
                                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;
 
@@ -383,7 +383,7 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
                        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) {
@@ -862,7 +862,7 @@ static int _risc_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr
                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;
 
@@ -874,7 +874,7 @@ static int _risc_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr
 
                        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)
@@ -904,28 +904,6 @@ static int _risc_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr
        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;
 }
index 3b7d661e671462bc7af24115c147b56be646b3b5..dda0bcac56785dbbf3db4c6f6e065336487da3d4 100644 (file)
@@ -7,8 +7,8 @@ int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf
        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);
 
@@ -89,8 +89,8 @@ int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, sc
        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) {
 
@@ -130,8 +130,8 @@ int risc_load_reg(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_
        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;
 
@@ -209,7 +209,7 @@ int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c
 
        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);
@@ -361,7 +361,7 @@ int risc_pointer_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* membe
        sib->index = NULL;
        sib->scale = 0;
        sib->disp  = disp;
-       sib->size  = risc_variable_size(vm);
+       sib->size  = f->rops->variable_size(vm);
        return 0;
 }
 
@@ -562,17 +562,17 @@ void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c, scf_functio
                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;
                }
index 4fea8c2af3b50248e6304f6c0a021dcd79660fb9..abd1e689c3c23df537c97b6552972139a7d1c237 100644 (file)
                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);
 
@@ -165,39 +55,5 @@ int                 risc_array_index_reg(scf_sib_t* sib, scf_dag_node_t* base, s
 
 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
 
diff --git a/native/risc/scf_risc_reg_arm32.c b/native/risc/scf_risc_reg_arm32.c
new file mode 100644 (file)
index 0000000..36108b1
--- /dev/null
@@ -0,0 +1,937 @@
+#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,
+};
+
index 4560f4bc9eec625fc871db5d1f128bd3c0824b1c..8a7b32184e2722a33e49ec6af4210b0a4df7c7e5 100644 (file)
@@ -1,5 +1,9 @@
 #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},
@@ -231,6 +235,85 @@ scf_register_t     arm64_registers[] = {
        {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;
@@ -394,7 +477,7 @@ void arm64_registers_clear()
        }
 }
 
-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;
 
@@ -775,7 +858,7 @@ scf_register_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t*
 
        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);
@@ -874,10 +957,28 @@ scf_register_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t*
        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,
@@ -886,6 +987,8 @@ scf_regs_ops_t  regs_ops_arm64 =
        .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,
 
@@ -904,6 +1007,19 @@ scf_regs_ops_t  regs_ops_naja =
 {
        .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,
@@ -912,6 +1028,8 @@ scf_regs_ops_t  regs_ops_naja =
        .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,
 
index bed67ced6d1afa1a45d441f9cdd72ec11b481f8f..5e943f26dc01beea58d844f0ed017cb4e637a1ea 100644 (file)
@@ -222,12 +222,10 @@ enum scf_risc_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 {
index e5b0b661cdbd319b996659abd6ad7eca6a87f245..e3cf74fb438d8f0edb0df39375719bda6bce6fa9 100644 (file)
@@ -99,6 +99,19 @@ struct scf_regs_ops_s
 {
        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 )();
@@ -107,6 +120,8 @@ struct scf_regs_ops_s
        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);
 
@@ -126,7 +141,7 @@ struct scf_inst_ops_s
 {
        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);
@@ -143,68 +158,69 @@ struct scf_inst_ops_s
        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);
 };
index f6faa4c1462bb672730263dcdc9053d31e6c9378..1795ff2d9bb93bb5d0ead6c9bbf4223a03bc28d3 100644 (file)
@@ -37,16 +37,21 @@ CFILES += ../native/risc/scf_risc_opcode.c
 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
index b4aedef574987b1333f16e3b03dbb6232c1aa793..0eae6c392bebc9d009ae56c824cfd00b125b4044 100644 (file)
@@ -27,6 +27,17 @@ static char* __arm64_sofiles[] =
        "../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);
@@ -177,6 +188,9 @@ int main(int argc, char* argv[])
 
        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);
 
index b1db2839c7b88c3c5ebc45f03a5b34bb4f9d95ef..98b9d9b62d7b25af1e176704174b31fe4f45002b 100644 (file)
@@ -1845,6 +1845,15 @@ static int _scf_parse_add_data_relas(scf_parse_t* parse, scf_elf_context_t* elf)
                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:
@@ -1925,9 +1934,10 @@ static int _add_debug_section(scf_elf_context_t* elf, const char* name, const sc
 
 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;
@@ -1955,7 +1965,7 @@ static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_e
                        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;
 
@@ -1985,6 +1995,15 @@ static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_e
        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
 
@@ -2151,6 +2170,7 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf,
        if (relas->size > 0) {
 
                scf_elf_section_t s = {0};
+               scf_elf_rela_t*   r;
 
                s.name         = ".rela.text";
                s.sh_type      = SHT_RELA;
@@ -2161,6 +2181,15 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf,
                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:
index 9d1be3e9849c6e6861bd1cc0df9217f2186e171d..cbc0a7444119c1f5980d58012b3f9bf991958756 100644 (file)
@@ -3,10 +3,13 @@ CFILES += ../util/scf_string.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