1, add Naja Virtual Machine for naja bytecode,
authoryu.dongliang <18588496441@163.com>
Tue, 28 Mar 2023 12:51:46 +0000 (20:51 +0800)
committeryu.dongliang <18588496441@163.com>
Tue, 28 Mar 2023 12:51:53 +0000 (20:51 +0800)
2, lexer: support "\033" in string, so printf() can print with color.

19 files changed:
elf/scf_elf.c
elf/scf_elf.h
elf/scf_elf_arm64.c
elf/scf_elf_naja.c
elf/scf_elf_naja_so.c
elf/scf_elf_native.c
elf/scf_elf_native.h
lex/scf_lex.c
native/risc/scf_arm64.c
native/risc/scf_naja.c
native/risc/scf_risc_bb_color.c
native/scf_native.h
parse/Makefile
vm/Makefile [new file with mode: 0644]
vm/scf_vm.c [new file with mode: 0644]
vm/scf_vm.h [new file with mode: 0644]
vm/scf_vm_naja.c [new file with mode: 0644]
vm/scf_vm_naja_asm.c [new file with mode: 0644]
vm/scf_vm_test.c [new file with mode: 0644]

index 5577d72de69e5f5b596b27b7402312261a657ca0..60a4ef417438ad4fcf3bedb451e22a5de53c5b85 100644 (file)
@@ -200,6 +200,15 @@ int scf_elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char*
        return -1;
 }
 
+int scf_elf_read_phdrs(scf_elf_context_t* elf, scf_vector_t* phdrs)
+{
+       if (elf && elf->ops && elf->ops->read_phdrs && phdrs)
+               return elf->ops->read_phdrs(elf, phdrs);
+
+       scf_loge("\n");
+       return -1;
+}
+
 int scf_elf_write_rel(scf_elf_context_t* elf)
 {
        if (elf && elf->ops && elf->ops->write_rel)
index 0cdb91f100b3c3ac76bab8b749ab091c9eeb699e..cc9717f193d696e9c255ccc6e4d2e204a7203b3d 100644 (file)
@@ -42,6 +42,14 @@ typedef struct {
        uint32_t    sh_info;
 } scf_elf_section_t;
 
+typedef struct {
+       Elf64_Phdr  ph;
+
+       uint64_t    addr;
+       uint64_t    len;
+       void*       data;
+} scf_elf_phdr_t;
+
 struct scf_elf_ops_s
 {
        const char*             machine;
@@ -52,6 +60,7 @@ struct scf_elf_ops_s
        int                             (*add_sym   )(scf_elf_context_t* elf, const scf_elf_sym_t*  sym,   const char* sh_name);
        int                             (*read_syms )(scf_elf_context_t* elf,       scf_vector_t*   syms,  const char* sh_name);
        int                             (*read_relas)(scf_elf_context_t* elf,       scf_vector_t*   relas, const char* sh_name);
+       int                             (*read_phdrs)(scf_elf_context_t* elf,       scf_vector_t*   phdrs);
 
        int                             (*add_section )(scf_elf_context_t* elf, const scf_elf_section_t*  section);
        int                             (*read_section)(scf_elf_context_t* elf,       scf_elf_section_t** psection, const char* name);
@@ -94,6 +103,7 @@ int scf_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, c
 
 int scf_elf_read_syms (scf_elf_context_t* elf, scf_vector_t* syms,  const char* sh_name);
 int scf_elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name);
+int scf_elf_read_phdrs(scf_elf_context_t* elf, scf_vector_t* phdrs);
 
 int scf_elf_write_rel( scf_elf_context_t* elf);
 int scf_elf_write_exec(scf_elf_context_t* elf);
index ea13de447214be1384c0bc20323161dceb685337..f8e14ef0e0a003a28935f4a6e69a144c9b3b9092 100644 (file)
@@ -52,11 +52,10 @@ static int _arm64_elf_link_cs(elf_native_t* arm64, elf_section_t* s, elf_section
                                }
 
                                offset &= 0x3ffffff;
-                               offset |= (0x25 << 26);
 
                                scf_loge("sym: %s, offset: %#x, %#lx\n", sym->name->data, offset, rela->r_offset);
 
-                               *(uint32_t*)(s->data + rela->r_offset) = offset;
+                               *(uint32_t*)(s->data + rela->r_offset) |= offset;
                                break;
 
                        case R_AARCH64_ADR_PREL_PG_HI21:
index fe4e21fb3724608e96833a8628de3d3aa77d2a38..e62bbe619b4dea5e746c50f8f4b1ac2d5d06a838 100644 (file)
@@ -52,24 +52,23 @@ static int _naja_elf_link_cs(elf_native_t* naja, elf_section_t* s, elf_section_t
                                }
 
                                offset &= 0x3ffffff;
-                               offset |= (0x25 << 26);
 
                                scf_loge("sym: %s, offset: %#x, %#lx\n", sym->name->data, offset, rela->r_offset);
 
-                               *(uint32_t*)(s->data + rela->r_offset) = offset;
+                               *(uint32_t*)(s->data + rela->r_offset) |= offset;
                                break;
 
                        case R_AARCH64_ADR_PREL_PG_HI21:
 
-                               offset >>= 12;
-                               offset   = ((offset & 0x3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
+                               offset >>= 15;
+                               offset  &= 0x1fffff;
 
                                *(uint32_t*)(s->data + rela->r_offset) |= offset;
                                break;
 
                        case R_AARCH64_ADD_ABS_LO12_NC:
 
-                               *(uint32_t*)(s->data + rela->r_offset) |= (sym->sym.st_value & 0xfff) << 10;
+                               *(uint32_t*)(s->data + rela->r_offset) |= (sym->sym.st_value & 0x7fff) << 5;
                                break;
 
                        default:
@@ -343,7 +342,7 @@ static int _naja_elf_write_exec(scf_elf_context_t* elf)
        for (i  = 0; i < naja->symbols->size; i++) {
                sym =        naja->symbols->data[i];
 
-               if (!strcmp(sym->name->data, "_start")) {
+               if (!strcmp(sym->name->data, "main")) {
 
                        if (0 != _start) {
                                scf_loge("\n");
@@ -469,6 +468,7 @@ scf_elf_ops_t       elf_ops_naja =
        .read_syms        = elf_read_syms,
        .read_relas       = elf_read_relas,
        .read_section     = elf_read_section,
+       .read_phdrs       = elf_read_phdrs,
 
        .write_rel            = _naja_elf_write_rel,
        .write_exec       = _naja_elf_write_exec,
index 345a9af5da36bf54be190461a098516989e7ad26..6e2fb8cbf944a50dca413e646bfed768d115d7a8 100644 (file)
@@ -2,22 +2,23 @@
 #include"scf_elf_link.h"
 
 static uint32_t naja_plt_lazy[8] = {
-       0xa9bf7bf0,  // stp  x16, x30, [sp, #-16]!
-       0x90000010,  // adrp x16, 0
-       0xf9400211,  // ldr  x17, [x16, #0]
-       0x91000210,  // add  x16,  x16, #0
-
-       0xd61f0220,  // br   x17
-       0xd503201f,  // nop
-       0xd503201f,  // nop
-       0xd503201f,  // nop
+       // str  x16, x30, [sp, #-16]!
+       (5    << 26) | (16 << 21) | (1 << 20) | (3 << 17) | (((-1) & 0xfff) << 5) | 0x1f,
+       (5    << 26) | (30 << 21) | (1 << 20) | (3 << 17) | (((-1) & 0xfff) << 5) | 0x1f,
+       (0x2a << 26) | (16 << 21),                  // adrp  x16, 0
+       (0    << 26) | (16 << 21) | (1 << 20) | 16, // add   x16,  x16, #0
+
+       (4    << 26) | (17 << 21) | (3 << 17) | 16, // ldr   x17, [x16, #0]
+       (0xa  << 26) | (17 << 21),                  // jmp  *x17
+       (0xf  << 26),                               // nop, mov r0, r0
+       (0xf  << 26),                               // nop, mov r0, r0
 };
 
 static uint32_t naja_plt[4] = {
-       0x90000010,  // adrp x16, 0
-       0xf9400211,  // ldr  x17, [x16, #0]
-       0x91000210,  // add  x16,  x16, #0
-       0xd61f0220,  // br   x17
+       (0x2a << 26) | (16 << 21),                  // adrp  x16, 0
+       (0    << 26) | (16 << 21) | (1 << 20) | 16, // add   x16,  x16, #0
+       (4    << 26) | (17 << 21) | (3 << 17) | 16, // ldr   x17, [x16, #0]
+       (0xa  << 26) | (17 << 21),                  // jmp  *x17
 };
 
 
@@ -539,7 +540,7 @@ int __naja_elf_add_dyn (elf_native_t* naja)
 
        Elf64_Dyn* dyns = (Elf64_Dyn*)naja->dynamic->data;
 
-       size_t prefix   = strlen("../lib/naja");
+       size_t prefix   = strlen("../lib/arm64");
 
        for (i = 0; i < naja->dyn_needs->size; i++) {
                scf_string_t* needed = naja->dyn_needs->data[i];
@@ -687,9 +688,8 @@ int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base,
 
        scf_loge("got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", got_addr, plt_addr, offset, offset);
 
-       plt[1] |= (((offset >> 12) & 0x3) << 29) | (((offset >> 14) & 0x7ffff) << 5);
-       plt[2] |=  ((got_addr & 0xfff) >> 3) << 10;
-       plt[3] |=   (got_addr & 0xfff) << 10;
+       plt[2] |=  (offset >> 15) & 0x1fffff;
+       plt[3] |=  (got_addr & 0x7fff) << 5;
 
        got_addr += 8;
        plt_addr += sizeof(naja_plt_lazy);
@@ -707,9 +707,8 @@ int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base,
 
                scf_loge("i: %d, got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", i, got_addr, plt_addr, offset, offset);
 
-               plt[0] |= (((offset >> 12) & 0x3) << 29) | (((offset >> 14) & 0x7ffff) << 5);
-               plt[1] |=  ((got_addr & 0xfff) >> 3) << 10;
-               plt[2] |=   (got_addr & 0xfff) << 10;
+               plt[0] |= (offset >> 15) & 0x1fffff;
+               plt[1] |= (got_addr & 0x7fff) << 5;
 
                plt += sizeof(naja_plt) / sizeof(naja_plt[0]);
                plt_addr += sizeof(naja_plt);
@@ -739,9 +738,8 @@ int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base,
                }
 
                offset &= 0x3ffffff;
-               offset |= (0x25 << 26);
 
-               *(uint32_t*)(cs->data + r->r_offset) = offset;
+               *(uint32_t*)(cs->data + r->r_offset) |= offset;
        }
 
        Elf64_Dyn* dtags = (Elf64_Dyn*)naja->dynamic->data;
index 9a3860404452c38a8689de540bd1a12eabf1b3f7..3a32ffeeb3d369ffa01ac87b67bac414b19328ef 100644 (file)
@@ -376,6 +376,60 @@ static int __elf_read_section_by_index(scf_elf_context_t* elf, elf_section_t** p
        return -1;
 }
 
+int elf_read_phdrs(scf_elf_context_t* elf, scf_vector_t* phdrs)
+{
+       elf_native_t*   e = elf->priv;
+       scf_elf_phdr_t* ph;
+       Elf64_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(Elf64_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(Elf64_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;
index 08916c3061ac9f57002e4a7415c13cd3819993a3..179b4b53b5ec90612a12e54cf425dbb1307f419e 100644 (file)
@@ -41,6 +41,7 @@ typedef struct {
        Elf64_Shdr      sh_null;
 
        scf_vector_t*   sections;
+       scf_vector_t*   phdrs;
 
        Elf64_Shdr      sh_symtab;
        scf_vector_t*   symbols;
@@ -82,6 +83,7 @@ int  elf_read_section (scf_elf_context_t* elf, scf_elf_section_t** psection, con
 int  elf_add_dyn_need(scf_elf_context_t* elf, const char* soname);
 int  elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela);
 
+int  elf_read_phdrs  (scf_elf_context_t* elf, scf_vector_t* phdrs);
 int  elf_read_relas  (scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name);
 int  elf_read_syms   (scf_elf_context_t* elf, scf_vector_t* syms,  const char* sh_name);
 
index 1768b375cf2597f86f55abff607c23229ab76cc0..7402ddf246620df29ddcc110ef24e412ef1e2415 100644 (file)
@@ -839,14 +839,36 @@ static int _lex_string(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_char_t* c
 
                        scf_string_cat_cstr_len(s, (char*)&c1->c, 1);
                        scf_string_cat_cstr_len(s, (char*)&c2->c, 1);
-
-                       scf_string_cat_cstr_len(data, (char*)&ch2, 1);
                        lex->pos += 2;
 
                        free(c2);
-                       c2 = NULL;
                        free(c1);
+                       c2 = NULL;
                        c1 = NULL;
+
+                       if (0 == ch2) {
+                               while (1) {
+                                       c1 = _lex_pop_char(lex);
+
+                                       if ('0' <= c1->c && c1->c <= '7') {
+                                               ch2 <<= 3;
+                                               ch2  += c1->c - '0';
+
+                                               scf_string_cat_cstr_len(s, (char*)&c1->c, 1);
+                                               lex->pos++;
+
+                                               free(c1);
+                                               c1 = NULL;
+                                       } else {
+                                               _lex_push_char(lex, c1);
+                                               break;
+                                       }
+                               }
+
+                               scf_string_cat_cstr_len(data, (char*)&ch2, 1);
+                       } else
+                               scf_string_cat_cstr_len(data, (char*)&ch2, 1);
+
                } else if (EOF == c1->c) {
                        printf("%s(),%d, error: \n", __func__, __LINE__);
                        return -1;
index d72007ba1fb26a2e096a99dd922c0a24a926d8a5..b8e46e61eb122317899615307aae1d2e7bf84b0e 100644 (file)
@@ -1488,7 +1488,7 @@ scf_instruction_t* arm64_inst_JBE(scf_3ac_code_t* c)
        return NULL;
 }
 
-void risc_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
+void arm64_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
 {
        if (0x54 == inst->code[3]) {
 
@@ -1522,6 +1522,66 @@ void risc_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
        }
 }
 
+int arm64_cmp_update(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* cmp)
+{
+       scf_instruction_t* inst;
+       scf_register_t*    r16 = risc_find_register_type_id_bytes(0, 16, 8);
+       scf_register_t*    r17 = risc_find_register_type_id_bytes(0, 17, 8);
+       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] & 0x7f) {
+               // arm64
+               case 0x71:  // imm
+                       i0   = (opcode >> 5) & 0x1f;
+                       r0   = risc_find_register_type_id_bytes(0, i0, 8);
+                       inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       opcode &= ~(0x1f << 5);
+                       opcode |=  (0x10 << 5);
+                       break;
+
+               case 0x6b:  // register
+                       i0   = (opcode >>  5) & 0x1f;
+                       i1   = (opcode >> 16) & 0x1f;
+
+                       r0   = risc_find_register_type_id_bytes(0, i0, 8);
+                       inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       r0   = risc_find_register_type_id_bytes(0, i1, 8);
+                       inst = f->iops->MOV_G(c, r17, r0);  // use r17 to backup r1
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       opcode &= ~(0x1f << 5);
+                       opcode |=  (0x10 << 5);
+
+                       opcode &= ~(0x1f << 16);
+                       opcode |=  (0x11 << 16);
+                       break;
+               default:
+                       scf_loge("%#x\n", opcode);
+                       return -EINVAL;
+                       break;
+       };
+
+       cmp->code[0] = 0xff &  opcode;
+       cmp->code[1] = 0xff & (opcode >>  8);
+       cmp->code[2] = 0xff & (opcode >> 16);
+       cmp->code[3] = 0xff & (opcode >> 24);
+       return 0;
+}
+
 scf_inst_ops_t  inst_ops_arm64 =
 {
        .name      = "arm64",
@@ -1604,6 +1664,7 @@ scf_inst_ops_t  inst_ops_arm64 =
        .ADRP2G    = arm64_inst_ADRP2G,
        .ADRSIB2G  = arm64_inst_ADRSIB2G,
 
-       .set_jmp_offset = risc_set_jmp_offset,
+       .set_jmp_offset = arm64_set_jmp_offset,
+       .cmp_update     = arm64_cmp_update,
 };
 
index 53ee2cd63810d5886dc105245e0e9fa3d416e54e..63f1565d8763f7fea093470dc916923fc2fa89a7 100644 (file)
@@ -167,7 +167,7 @@ int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 1;
+               offset >>= 1;
                SIZE = 1;
 
        } else if (4 == size) {
@@ -177,7 +177,7 @@ int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 2;
+               offset >>= 2;
                SIZE = 2;
 
        } else if (8 == size) {
@@ -187,7 +187,7 @@ int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 3;
+               offset >>= 3;
                SIZE = 3;
        } else
                return -EINVAL;
@@ -274,7 +274,7 @@ int naja_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 1;
+               offset >>= 1;
                SIZE = 1;
 
        } else if (4 == size) {
@@ -284,7 +284,7 @@ int naja_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 2;
+               offset >>= 2;
                SIZE = 2;
 
        } else if (8 == size) {
@@ -294,12 +294,14 @@ int naja_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 3;
+               offset >>= 3;
                SIZE = 3;
 
        } else
                return -EINVAL;
 
+       scf_loge("offset: %ld, SIZE: %d\n", offset, SIZE);
+
        if (offset >= -0x7ff && offset <= 0x7ff)
                opcode = (0x5 << 26) | ((offset & 0xfff) << 5) | rb->id;
        else {
@@ -376,7 +378,7 @@ int naja_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 1;
+               offset >>= 1;
                SIZE = 1;
 
        } else if (4 == size) {
@@ -386,7 +388,7 @@ int naja_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 2;
+               offset >>= 2;
                SIZE = 2;
 
        } else if (8 == size) {
@@ -396,7 +398,7 @@ int naja_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_
                        return -EINVAL;
                }
 
-               offset >> 3;
+               offset >>= 3;
                SIZE = 3;
 
        } else
@@ -447,7 +449,7 @@ int naja_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 1;
+               offset >>= 1;
                SIZE = 1;
 
        } else if (4 == size) {
@@ -457,7 +459,7 @@ int naja_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 2;
+               offset >>= 2;
                SIZE = 2;
 
        } else if (8 == size) {
@@ -467,7 +469,7 @@ int naja_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_
                        return -EINVAL;
                }
 
-               offset >> 3;
+               offset >>= 3;
                SIZE = 3;
 
        } else
@@ -653,7 +655,7 @@ scf_instruction_t* naja_inst_PUSH(scf_3ac_code_t* c, scf_register_t* r)
        scf_instruction_t* inst;
        uint32_t           opcode;
 
-       opcode = (0x5 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | (1 << 5) | 0x1f;
+       opcode = (0x5 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | ((0xfff & -1) << 5) | 0x1f;
        inst   = risc_make_inst(c, opcode);
 
        return inst;
@@ -664,7 +666,7 @@ scf_instruction_t* naja_inst_POP(scf_3ac_code_t* c, scf_register_t* r)
        scf_instruction_t* inst;
        uint32_t           opcode;
 
-       opcode = (0x4 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | ((0xfff & -1) << 5) | 0x1f;
+       opcode = (0x4 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | (1 << 5) | 0x1f;
        inst   = risc_make_inst(c, opcode);
 
        return inst;
@@ -1296,7 +1298,7 @@ scf_instruction_t* naja_inst_JBE(scf_3ac_code_t* c)
 
 void naja_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
 {
-       if (0xa == inst->code[3] && 1 == (inst->code[0] & 1)) {
+       if (0x28 == inst->code[3] && 1 == (inst->code[0] & 1)) {
 
                if (bytes  >= 0 && bytes < (0x1 << 20)) {
                        bytes >>= 2;
@@ -1305,7 +1307,7 @@ void naja_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
                } else if (bytes < 0 && bytes > -(0x1 << 20)) {
 
                        bytes >>= 2;
-                       bytes  &= 0x7ffff;
+                       bytes  &= 0x1fffff;
                        bytes <<= 5;
                } else
                        assert(0);
@@ -1313,9 +1315,10 @@ void naja_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
                inst->code[0] |= 0xff &  bytes;
                inst->code[1] |= 0xff & (bytes >>  8);
                inst->code[2] |= 0xff & (bytes >> 16);
+               inst->code[3] |= 0x3  & (bytes >> 24);
 
        } else {
-               assert(8 == inst->code[3]);
+               assert(0x20 == inst->code[3]);
 
                bytes >>= 2;
 
@@ -1328,6 +1331,67 @@ void naja_set_jmp_offset(scf_instruction_t* inst, int32_t bytes)
        }
 }
 
+int naja_cmp_update(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* cmp)
+{
+       scf_instruction_t* inst;
+       scf_register_t*    r16 = risc_find_register_type_id_bytes(0, 16, 8);
+       scf_register_t*    r17 = risc_find_register_type_id_bytes(0, 17, 8);
+       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]) {
+
+               case 0x14:  // imm
+                       i0   = opcode & 0x1f;
+                       r0   = risc_find_register_type_id_bytes(0, i0, 8);
+                       inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       opcode &= ~0x1f;
+                       opcode |=  0x10;
+                       break;
+
+               case 0x24:  // register
+                       i0   =  opcode & 0x1f;
+                       i1   = (opcode >> 5) & 0x1f;
+
+                       r0   = risc_find_register_type_id_bytes(0, i0, 8);
+                       inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       r0   = risc_find_register_type_id_bytes(0, i1, 8);
+                       inst = f->iops->MOV_G(c, r17, r0);  // use r17 to backup r1
+                       RISC_INST_ADD_CHECK(c->instructions, inst);
+
+                       opcode &= ~0x1f;
+                       opcode |=  0x10;
+
+                       opcode &= ~(0x1f << 5);
+                       opcode |=  (0x11 << 5);
+                       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;
+}
+
+
 scf_inst_ops_t  inst_ops_naja =
 {
        .name      = "naja",
@@ -1411,5 +1475,6 @@ scf_inst_ops_t  inst_ops_naja =
        .ADRSIB2G  = naja_inst_ADRSIB2G,
 
        .set_jmp_offset = naja_set_jmp_offset,
+       .cmp_update     = naja_cmp_update,
 };
 
index 668b01801aeaf73668fd43bf81cda4831d42a297..0cac255dcb90c06f8d9b0dca92fbb6e2d55b92f9 100644 (file)
@@ -190,55 +190,13 @@ int risc_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb,
        if (bb->cmp_flag) {
 
                cmp = c->instructions->data[c->instructions->size - 1];
-
                c->instructions->size--;
 
-               opcode  = cmp->code[0];
-               opcode |= cmp->code[1] <<  8;
-               opcode |= cmp->code[2] << 16;
-               opcode |= cmp->code[3] << 24;
-
-               switch (cmp->code[3] & 0x7f) {
-
-                       case 0x71:  // imm
-                               i0   = (opcode >> 5) & 0x1f;
-                               r0   = risc_find_register_type_id_bytes(0, i0, 8);
-                               inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
-                               RISC_INST_ADD_CHECK(c->instructions, inst);
-
-                               opcode &= ~(0x1f << 5);
-                               opcode |=  (0x10 << 5);
-                               break;
-
-                       case 0x6b:  // register
-                               i0   = (opcode >>  5) & 0x1f;
-                               i1   = (opcode >> 16) & 0x1f;
-
-                               r0   = risc_find_register_type_id_bytes(0, i0, 8);
-                               inst = f->iops->MOV_G(c, r16, r0);  // use r16 to backup r0
-                               RISC_INST_ADD_CHECK(c->instructions, inst);
-
-                               r0   = risc_find_register_type_id_bytes(0, i1, 8);
-                               inst = f->iops->MOV_G(c, r17, r0);  // use r17 to backup r1
-                               RISC_INST_ADD_CHECK(c->instructions, inst);
-
-                               opcode &= ~(0x1f << 5);
-                               opcode |=  (0x10 << 5);
-
-                               opcode &= ~(0x1f << 16);
-                               opcode |=  (0x11 << 16);
-                               break;
-
-                       default:
-                               scf_loge("%#x\n", opcode);
-                               return -EINVAL;
-                               break;
-               };
-
-               cmp->code[0] = 0xff &  opcode;
-               cmp->code[1] = 0xff & (opcode >>  8);
-               cmp->code[2] = 0xff & (opcode >> 16);
-               cmp->code[3] = 0xff & (opcode >> 24);
+               int ret = f->iops->cmp_update(c, f, cmp);
+               if (ret < 0) {
+                       scf_loge("\n");
+                       return ret;
+               }
        }
 
        int ret = risc_bb_load_dn(color, dn, c, bb, f);
index 9bc864869a3f9c70f0766364e6306dc96d3c80eb..912475079fd1b5641ef75dd54da40360106cc953 100644 (file)
@@ -174,7 +174,9 @@ struct scf_inst_ops_s
        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 (*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);
 
        void (*set_jmp_offset)(scf_instruction_t* inst, int32_t bytes);
 };
index 0766f2f2ec14f3bd5d22385028e199ef6c14fde9..10395df8b675a2c1bdc426e7103a7372480e90dd 100644 (file)
@@ -53,6 +53,10 @@ CFILES += ../elf/scf_dwarf_abbrev.c
 CFILES += ../elf/scf_dwarf_info.c
 CFILES += ../elf/scf_dwarf_line.c
 
+CFILES += ../vm/scf_vm.c
+CFILES += ../vm/scf_vm_naja.c
+CFILES += ../vm/scf_vm_naja_asm.c
+
 CFILES += ../core/scf_lex_word.c
 CFILES += ../core/scf_type.c
 CFILES += ../core/scf_variable.c
@@ -156,11 +160,12 @@ CFLAGS += -I../core
 CFLAGS += -I../lex
 CFLAGS += -I../parse
 CFLAGS += -I../elf
+CFLAGS += -I../vm
 CFLAGS += -I../native
 CFLAGS += -I../native/x64
 CFLAGS += -I../native/risc
 
-LDFLAGS +=
+LDFLAGS += -ldl
 
 all:
        gcc $(CFLAGS) $(CFILES) $(LDFLAGS) -o scf
diff --git a/vm/Makefile b/vm/Makefile
new file mode 100644 (file)
index 0000000..9d1be3e
--- /dev/null
@@ -0,0 +1,40 @@
+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_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_naja.c
+CFILES += ../elf/scf_elf_naja_so.c
+CFILES += ../elf/scf_dwarf.c
+CFILES += ../elf/scf_dwarf_abbrev.c
+CFILES += ../elf/scf_dwarf_info.c
+CFILES += ../elf/scf_dwarf_line.c
+
+CFILES += ../vm/scf_vm.c
+CFILES += ../vm/scf_vm_naja.c
+CFILES += ../vm/scf_vm_naja_asm.c
+CFILES += ../vm/scf_vm_test.c
+
+CFLAGS += -g
+#CFLAGS += -Wall 
+CFLAGS += -I../util
+CFLAGS += -I../core
+CFLAGS += -I../lex
+CFLAGS += -I../parse
+CFLAGS += -I../elf
+CFLAGS += -I../vm
+CFLAGS += -I../native
+CFLAGS += -I../native/x64
+CFLAGS += -I../native/risc
+
+LDFLAGS += -ldl
+
+all:
+       gcc $(CFLAGS) $(CFILES) $(LDFLAGS) -o nvm
+
+clean:
+       rm *.o
diff --git a/vm/scf_vm.c b/vm/scf_vm.c
new file mode 100644 (file)
index 0000000..48a2be6
--- /dev/null
@@ -0,0 +1,99 @@
+#include"scf_vm.h"
+
+extern scf_vm_ops_t  vm_ops_naja;
+extern scf_vm_ops_t  vm_ops_naja_asm;
+
+static scf_vm_ops_t* vm_ops_array[] =
+{
+       &vm_ops_naja,
+       &vm_ops_naja_asm,
+
+       NULL,
+};
+
+int scf_vm_open(scf_vm_t** pvm, const char* arch)
+{
+       scf_vm_ops_t* ops = NULL;
+       scf_vm_t*     vm;
+
+       int  i;
+       for (i = 0; vm_ops_array[i]; i++) {
+
+               if (!strcmp(vm_ops_array[i]->name, arch)) {
+                       ops =   vm_ops_array[i];
+                       break;
+               }
+       }
+
+       if (!ops) {
+               scf_loge("\n");
+               return -EINVAL;
+       }
+
+       vm = calloc(1, sizeof(scf_vm_t));
+       if (!vm)
+               return -ENOMEM;
+
+       vm->ops = ops;
+
+       if (vm->ops->open) {
+               int ret = vm->ops->open(vm);
+               if (ret < 0)
+                       return ret;
+       }
+
+       *pvm = vm;
+       return 0;
+}
+
+int scf_vm_clear(scf_vm_t* vm)
+{
+       if (!vm)
+               return -EINVAL;
+
+       if (vm->elf) {
+               scf_elf_close(vm->elf);
+               vm->elf = NULL;
+       }
+
+       if (vm->sofiles) {
+               int  i;
+
+               for (i = 0; i < vm->sofiles->size; i++)
+                       dlclose(vm->sofiles->data[i]);
+
+               scf_vector_free(vm->sofiles);
+               vm->sofiles = NULL;
+       }
+
+       vm->text = NULL;
+       vm->rodata = NULL;
+       vm->data = NULL;
+
+       return 0;
+}
+
+int scf_vm_close(scf_vm_t* vm)
+{
+       if (vm) {
+               scf_vm_clear(vm);
+
+               if (vm->ops && vm->ops->close)
+                       vm->ops->close(vm);
+
+               free(vm);
+               vm = NULL;
+       }
+
+       return 0;
+}
+
+int scf_vm_run(scf_vm_t* vm, const char* path, const char* sys)
+{
+       if (vm  && vm->ops && vm->ops->run && path)
+               return vm->ops->run(vm, path, sys);
+
+       scf_loge("\n");
+       return -EINVAL;
+}
+
diff --git a/vm/scf_vm.h b/vm/scf_vm.h
new file mode 100644 (file)
index 0000000..23ea753
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef SCF_VM_H
+#define SCF_VM_H
+
+#include"scf_elf.h"
+#include<dlfcn.h>
+
+typedef struct scf_vm_s       scf_vm_t;
+typedef struct scf_vm_ops_s   scf_vm_ops_t;
+
+struct  scf_vm_s
+{
+       scf_elf_context_t*        elf;
+
+       scf_vector_t*             sofiles;
+       scf_vector_t*             phdrs;
+
+       scf_elf_phdr_t*           text;
+       scf_elf_phdr_t*           rodata;
+       scf_elf_phdr_t*           data;
+
+       scf_elf_phdr_t*           dynamic;
+       Elf64_Rela*               jmprel;
+       uint64_t                  jmprel_addr;
+       uint64_t                  jmprel_size;
+       Elf64_Sym*                dynsym;
+       uint64_t*                 pltgot;
+       uint8_t*                  dynstr;
+
+       scf_vm_ops_t*             ops;
+       void*                     priv;
+};
+
+struct scf_vm_ops_s
+{
+       const char* name;
+
+       int  (*open )(scf_vm_t* vm);
+       int  (*close)(scf_vm_t* vm);
+
+       int  (*run  )(scf_vm_t* vm, const char* path, const char* sys);
+};
+
+#define  SCF_VM_Z   0
+#define  SCF_VM_NZ  1
+#define  SCF_VM_GE  2
+#define  SCF_VM_GT  3
+#define  SCF_VM_LE  4
+#define  SCF_VM_LT  5
+
+typedef struct {
+       uint64_t  regs[32];
+
+       uint64_t  ip;
+       uint64_t  flags;
+
+#define STACK_INC 16
+       uint8_t*  stack;
+       int64_t   size;
+
+       uint64_t  _start;
+
+} scf_vm_naja_t;
+
+#define NAJA_ADD        0
+#define NAJA_SUB        1
+#define NAJA_MUL        2
+#define NAJA_DIV        3
+#define NAJA_LDR_DISP   4
+#define NAJA_STR_DISP   5
+#define NAJA_AND        6
+#define NAJA_OR         7
+#define NAJA_JMP_DISP   8
+#define NAJA_CMP        9
+#define NAJA_JMP_REG   10
+#define NAJA_SETCC     11
+#define NAJA_LDR_SIB   12
+#define NAJA_STR_SIB   13
+#define NAJA_TEQ       14
+#define NAJA_MOV       15
+
+#define NAJA_CALL_DISP 24
+#define NAJA_CALL_REG  26
+#define NAJA_ADRP      42
+#define NAJA_RET       56
+
+typedef int (*naja_opcode_pt)(scf_vm_t* vm, uint32_t inst);
+
+int scf_vm_open (scf_vm_t** pvm, const char* arch);
+int scf_vm_close(scf_vm_t*   vm);
+int scf_vm_clear(scf_vm_t*   vm);
+
+int scf_vm_run  (scf_vm_t*   vm, const char* path, const char* sys);
+
+int naja_vm_open(scf_vm_t* vm);
+int naja_vm_close(scf_vm_t* vm);
+int naja_vm_init(scf_vm_t* vm, const char* path, const char* sys);
+
+#endif
+
diff --git a/vm/scf_vm_naja.c b/vm/scf_vm_naja.c
new file mode 100644 (file)
index 0000000..9656fa4
--- /dev/null
@@ -0,0 +1,1673 @@
+#include"scf_vm.h"
+
+#define NAJA_REG_FP   29
+#define NAJA_REG_LR   30
+#define NAJA_REG_SP   31
+
+static const char* somaps[][3] =
+{
+       {"x64", "/lib/ld-linux-aarch64.so.1",       "/lib64/ld-linux-x86-64.so.2"},
+       {"x64", "/lib/aarch64-linux-gnu/libc.so.6", "/lib/x86_64-linux-gnu/libc.so.6"},
+};
+
+typedef int64_t (*naja_dyn_func_pt)(uint64_t r0,
+               uint64_t r1,
+               uint64_t r2,
+               uint64_t r3,
+               uint64_t r4,
+               uint64_t r5,
+               uint64_t r6,
+               uint64_t r7);
+
+int naja_vm_open(scf_vm_t* vm)
+{
+       if (!vm)
+               return -EINVAL;
+
+       scf_vm_naja_t* naja = calloc(1, sizeof(scf_vm_naja_t));
+       if (!naja)
+               return -ENOMEM;
+
+       vm->priv = naja;
+       return 0;
+}
+
+int naja_vm_close(scf_vm_t* vm)
+{
+       if (vm) {
+               if (vm->priv) {
+                       free(vm->priv);
+                       vm->priv = NULL;
+               }
+       }
+
+       return 0;
+}
+
+static int naja_vm_dynamic_link(scf_vm_t* vm)
+{
+       naja_dyn_func_pt  f    = NULL;
+       scf_vm_naja_t*    naja = vm->priv;
+
+       int64_t  sp = naja->regs[NAJA_REG_SP];
+
+       uint64_t r30 = *(uint64_t*)(naja->stack - (sp +  8));
+       uint64_t r16 = *(uint64_t*)(naja->stack - (sp + 16));
+
+       scf_logw("sp: %ld, r16: %#lx, r30: %#lx, vm->jmprel_size: %ld\n", sp, r16, r30, vm->jmprel_size);
+
+       if (r16  > (uint64_t)vm->data->data) {
+               r16 -= (uint64_t)vm->data->data;
+               r16 +=           vm->data->addr;
+       }
+
+       scf_logw("r16: %#lx, text: %p, rodata: %p, data: %p\n", r16, vm->text->data, vm->rodata->data, vm->data->data);
+
+       int i;
+       for (i = 0; i < vm->jmprel_size / sizeof(Elf64_Rela); i++) {
+
+               if (r16  == vm->jmprel[i].r_offset) {
+
+                       int   j     = ELF64_R_SYM(vm->jmprel[i].r_info);
+
+                       char* fname = vm->dynstr + vm->dynsym[j].st_name;
+
+                       scf_logw("j: %d, %s\n", j, fname);
+
+                       int k;
+                       for (k = 0; k < vm->sofiles->size; k++) {
+
+                               f = dlsym(vm->sofiles->data[k], fname);
+                               if (f)
+                                       break;
+                       }
+
+                       if (f) {
+                               int64_t offset = vm->jmprel[i].r_offset - vm->data->addr;
+
+                               if (offset < 0 || offset > vm->data->len) {
+                                       scf_loge("\n");
+                                       return -1;
+                               }
+
+                               *(void**)(vm->data->data + offset) = f;
+
+                               naja->regs[0] = f(naja->regs[0],
+                                               naja->regs[1],
+                                               naja->regs[2],
+                                               naja->regs[3],
+                                               naja->regs[4],
+                                               naja->regs[5],
+                                               naja->regs[6],
+                                               naja->regs[7]);
+
+                               naja->regs[NAJA_REG_SP] += 16;
+                               return 0;
+                       }
+                       break;
+               }
+       }
+
+       return -1;
+}
+
+int naja_vm_init(scf_vm_t* vm, const char* path, const char* sys)
+{
+       if (!vm || !path)
+               return -EINVAL;
+
+       if (vm->elf)
+               scf_vm_clear(vm);
+
+       if (vm->priv)
+               memset(vm->priv, 0, sizeof(scf_vm_naja_t));
+       else {
+               vm->priv = calloc(1, sizeof(scf_vm_naja_t));
+               if (!vm->priv)
+                       return -ENOMEM;
+       }
+
+       if (vm->phdrs)
+               scf_vector_clear(vm->phdrs, (void (*)(void*) )free);
+       else {
+               vm->phdrs = scf_vector_alloc();
+               if (!vm->phdrs)
+                       return -ENOMEM;
+       }
+
+       if (vm->sofiles)
+               scf_vector_clear(vm->phdrs, (void (*)(void*) )dlclose);
+       else {
+               vm->sofiles = scf_vector_alloc();
+               if (!vm->sofiles)
+                       return -ENOMEM;
+       }
+
+       int ret = scf_elf_open(&vm->elf, "naja", path, "rb");
+       if (ret < 0) {
+               scf_loge("\n");
+               return ret;
+       }
+
+       ret = scf_elf_read_phdrs(vm->elf, vm->phdrs);
+       if (ret < 0) {
+               scf_loge("\n");
+               return ret;
+       }
+
+       scf_elf_phdr_t* ph;
+       int i;
+       for (i = 0; i < vm->phdrs->size; i++) {
+               ph =        vm->phdrs->data[i];
+
+               if (PT_LOAD ==  ph->ph.p_type) {
+
+                       ph->addr = (ph->ph.p_vaddr + ph->ph.p_memsz) & ~(ph->ph.p_align - 1);
+                       ph->len  = (ph->ph.p_vaddr + ph->ph.p_memsz) - ph->addr;
+
+                       ph->data = calloc(1, ph->len);
+                       if (!ph->data)
+                               return -ENOMEM;
+
+                       fseek(vm->elf->fp, 0, SEEK_SET);
+
+                       ret = fread(ph->data, ph->len, 1, vm->elf->fp);
+                       if (1 != ret) {
+                               scf_loge("\n");
+                               return -1;
+                       }
+
+                       scf_loge("i: %d, ph->p_offset: %#lx, ph->p_filesz: %#lx\n", i, ph->ph.p_offset, ph->ph.p_filesz);
+
+                       scf_loge("i: %d, ph->addr: %#lx, ph->len: %#lx, %#lx, ph->flags: %#x\n", i, ph->addr, ph->len, ph->ph.p_memsz, ph->ph.p_flags);
+
+                       if ((PF_X | PF_R) == ph->ph.p_flags)
+                               vm->text   =  ph;
+
+                       else if ((PF_W | PF_R) == ph->ph.p_flags)
+                               vm->data   = ph;
+
+                       else if (PF_R == ph->ph.p_flags)
+                               vm->rodata =  ph;
+                       else {
+                               scf_loge("\n");
+                               return -1;
+                       }
+
+               } else if (PT_DYNAMIC == ph->ph.p_type) {
+                       ph->addr = ph->ph.p_vaddr;
+                       ph->len  = ph->ph.p_memsz;
+
+                       vm->dynamic = ph;
+
+                       scf_loge("ph->addr: %#lx, ph->len: %#lx, %#lx, ph->p_offset: %#lx\n", ph->addr, ph->len, ph->ph.p_memsz, ph->ph.p_offset);
+               }
+       }
+
+       scf_loge("\n\n");
+
+       if (vm->dynamic) {
+               Elf64_Dyn* d = (Elf64_Dyn*)(vm->data->data + vm->dynamic->ph.p_offset);
+
+               vm->jmprel = NULL;
+               for (i = 0; i < vm->dynamic->ph.p_filesz / sizeof(Elf64_Dyn); i++) {
+
+                       switch (d[i].d_tag) {
+
+                               case DT_STRTAB:
+                                       scf_loge("dynstr: %#lx\n", d[i].d_un.d_ptr);
+                                       vm->dynstr = d[i].d_un.d_ptr - vm->text->addr + vm->text->data;
+                                       break;
+
+                               case DT_SYMTAB:
+                                       scf_loge("dynsym: %#lx\n", d[i].d_un.d_ptr);
+                                       vm->dynsym = (Elf64_Sym*)(d[i].d_un.d_ptr - vm->text->addr + vm->text->data);
+                                       break;
+
+                               case DT_JMPREL:
+                                       scf_loge("JMPREL: %#lx\n", d[i].d_un.d_ptr);
+                                       vm->jmprel      = (Elf64_Rela*)(d[i].d_un.d_ptr - vm->text->addr + vm->text->data);
+                                       vm->jmprel_addr = d[i].d_un.d_ptr;
+                                       break;
+
+                               case DT_PLTGOT:
+                                       scf_loge("PLTGOT: %#lx\n", d[i].d_un.d_ptr);
+                                       vm->pltgot = (uint64_t*)(d[i].d_un.d_ptr - vm->data->addr + vm->data->data);
+                                       break;
+
+                               default:
+                                       break;
+                       };
+               }
+
+               for (i = 0; i < vm->dynamic->ph.p_filesz / sizeof(Elf64_Dyn); i++) {
+
+                       if (DT_NEEDED == d[i].d_tag) {
+
+                               uint8_t* name = d[i].d_un.d_ptr + vm->dynstr;
+
+                               int j;
+                               for (j = 0; j < sizeof(somaps) / sizeof(somaps[0]); j++) {
+
+                                       if (!strcmp(somaps[j][0], sys)
+                                                       && !strcmp(somaps[j][1], name)) {
+                                               name  = somaps[j][2];
+                                               break;
+                                       }
+                               }
+
+                               scf_loge("needed: %s\n", name);
+
+                               void* so = dlopen(name, RTLD_LAZY);
+                               if (!so) {
+                                       scf_loge("dlopen error, so: %s\n", name);
+                                       return -1;
+                               }
+
+                               if (scf_vector_add(vm->sofiles, so) < 0) {
+                                       dlclose(so);
+                                       return -ENOMEM;
+                               }
+                       }
+               }
+
+               vm->pltgot[2] = (uint64_t)naja_vm_dynamic_link;
+       }
+
+       return 0;
+}
+
+static int __naja_add(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               naja->regs[rd]  = naja->regs[rs0] + uimm15;
+
+               printf("add    r%d, r%d, %lu\n", rd, rs0, uimm15);
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh) {
+                       naja->regs[rd]  = naja->regs[rs0] + (naja->regs[rs1] << uimm8);
+
+                       printf("add    r%d, r%d, r%d << %lu\n", rd, rs0, rs1, uimm8);
+
+               } else if (1 == sh) {
+                       naja->regs[rd]  = naja->regs[rs0] + (naja->regs[rs1] >> uimm8);
+
+                       printf("add    r%d, r%d, r%d LSR %lu\n", rd, rs0, rs1, uimm8);
+
+               } else {
+                       naja->regs[rd]  = naja->regs[rs0] + (((int64_t)naja->regs[rs1]) >> uimm8);
+
+                       printf("add    r%d, r%d, r%d ASR %lu\n", rd, rs0, rs1, uimm8);
+               }
+       }
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_sub(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               naja->regs[rd]  = naja->regs[rs0] - uimm15;
+
+               printf("sub    r%d, r%d, %lu\n", rd, rs0, uimm15);
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh) {
+                       naja->regs[rd]  = naja->regs[rs0] - (naja->regs[rs1] << uimm8);
+
+                       printf("sub    r%d, r%d, r%d << %lu\n", rd, rs0, rs1, uimm8);
+
+               } else if (1 == sh) {
+                       naja->regs[rd]  = naja->regs[rs0] - (naja->regs[rs1] >> uimm8);
+
+                       printf("sub    r%d, r%d, r%d LSR %lu\n", rd, rs0, rs1, uimm8);
+
+               } else {
+                       naja->regs[rd]  = naja->regs[rs0] - (((int64_t)naja->regs[rs1]) >> uimm8);
+
+                       printf("sub    r%d, r%d, r%d ASR %lu\n", rd, rs0, rs1, uimm8);
+               }
+       }
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_cmp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       int ret = 0;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               ret = naja->regs[rs0] - uimm15;
+
+               printf("cmp    r%d, %ld,  rs0: %lx, ret: %d\n", rs0, uimm15, naja->regs[rs0], ret);
+
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh) {
+                       ret = naja->regs[rs0] - (naja->regs[rs1] << uimm8);
+
+                       printf("cmp    r%d, r%d LSL %ld,  rs0: %#lx, rs1: %#lx, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+
+               } else if (1 == sh) {
+                       ret = naja->regs[rs0] - (naja->regs[rs1] >> uimm8);
+
+                       printf("cmp    r%d, r%d LSR %ld,  rs0: %#lx, rs1: %#lx, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+
+               } else {
+                       ret = naja->regs[rs0] - (((int64_t)naja->regs[rs1]) >> uimm8);
+
+                       printf("cmp    r%d, r%d ASR %ld,  rs0: %#lx, rs1: %ld, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+               }
+       }
+
+       if (0 == ret)
+               naja->flags = 0x1;
+       else if (ret > 0)
+               naja->flags = 0x4;
+       else
+               naja->flags = 0x2;
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_mul(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rs1 = (inst >>  5) & 0x1f;
+       int rs2 = (inst >> 10) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int S   = (inst >> 20) & 0x1;
+       int opt = (inst >> 15) & 0x3;
+
+       scf_logw("\n");
+       if (S)
+               naja->regs[rd] = (int64_t)naja->regs[rs0] * (int64_t)naja->regs[rs1];
+       else
+               naja->regs[rd] = naja->regs[rs0] * naja->regs[rs1];
+
+       if (0 == opt)
+               naja->regs[rd] += naja->regs[rs2];
+       else if (1 == opt)
+               naja->regs[rd]  = naja->regs[rs2] - naja->regs[rd];
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_div(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rs1 = (inst >>  5) & 0x1f;
+       int rs2 = (inst >> 10) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int S   = (inst >> 20) & 0x1;
+       int opt = (inst >> 15) & 0x3;
+
+       scf_logw("\n");
+       if (S)
+               naja->regs[rd] = (int64_t)naja->regs[rs0] / (int64_t)naja->regs[rs1];
+       else
+               naja->regs[rd] = naja->regs[rs0] / naja->regs[rs1];
+
+       if (0 == opt)
+               naja->regs[rd] += naja->regs[rs2];
+       else if (1 == opt)
+               naja->regs[rd]  = naja->regs[rs2] - naja->regs[rd];
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_ldr_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int A   = (inst >> 20) & 0x1;
+       int ext = (inst >> 17) & 0x7;
+       int s12 = (inst >>  5) & 0xfff;
+
+       if (s12  & 0x800)
+               s12 |= 0xfffff000;
+
+       scf_logd("rd: %d, rb: %d, s12: %d, ext: %d\n", rd, rb, s12, ext);
+
+       int64_t  addr   = naja->regs[rb];
+       int64_t  offset = 0;
+       uint8_t* data;
+
+       if (addr >= (int64_t)vm->data->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->data->data + vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->rodata->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->rodata->data + vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->text->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->text->data + vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr  >= 0x800000) {
+               data   = vm->data->data;
+               offset = addr - vm->data->addr;
+
+               if (offset >= vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x600000) {
+               data   = vm->rodata->data;
+               offset = addr - vm->rodata->addr;
+
+               if (offset >= vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x400000) {
+               data   = vm->text->data;
+               offset = addr - vm->text->addr;
+
+               if (offset >= vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else {
+               data   = naja->stack;
+               offset = addr;
+       }
+
+       if (!A)
+               offset += s12 << (ext & 0x3);
+
+       if (data   == naja->stack) {
+               offset = -offset;
+
+               scf_logd("offset0: %ld, size: %ld\n", offset, naja->size);
+               assert(offset >= 0);
+
+               if (naja->size < offset) {
+                       scf_loge("offset: %ld, size: %ld\n", offset, naja->size);
+                       return -EINVAL;
+               }
+
+               offset -= 1 << (ext & 0x3);
+       }
+
+       switch (ext) {
+               case 0:
+                       naja->regs[rd] = *(uint8_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12;
+                               printf("ldrb   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       } else
+                               printf("ldrb   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 1:
+                       naja->regs[rd] = *(uint16_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12 << 1;
+                               printf("ldrw   r%d, [r%d, %d]!\n", rd, rb, s12 << 1);
+                       } else
+                               printf("ldrw   r%d, [r%d, %d]\n", rd, rb, s12 << 1);
+                       break;
+
+               case 2:
+                       naja->regs[rd] = *(uint32_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12 << 2;
+                               printf("ldrl   r%d, [r%d, %d]!\n", rd, rb, s12 << 2);
+                       } else
+                               printf("ldrl   r%d, [r%d, %d],  %ld, %p\n", rd, rb, s12 << 2, naja->regs[rd], data + offset);
+                       break;
+
+               case 3:
+                       naja->regs[rd] = *(uint64_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12 << 3;
+                               printf("ldr    r%d, [r%d, %d]!, rd: %#lx, rb: %ld, %p\n", rd, rb, s12 << 3, naja->regs[rd], naja->regs[rb], data + offset);
+                       } else
+                               printf("ldr    r%d, [r%d, %d]\n", rd, rb, s12 << 3);
+                       break;
+
+               case 4:
+                       naja->regs[rd] = *(int8_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12;
+                               printf("ldrsb  r%d, [r%d, %d]!\n", rd, rb, s12);
+                       } else
+                               printf("ldrsb  r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 5:
+                       naja->regs[rd] = *(int16_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12 << 1;
+                               printf("ldrsw  r%d, [r%d, %d]!\n", rd, rb, s12 << 1);
+                       } else
+                               printf("ldrsw  r%d, [r%d, %d]\n", rd, rb, s12 << 1);
+                       break;
+
+               case 6:
+                       naja->regs[rd] = *(int32_t*)(data + offset);
+                       if (A) {
+                               naja->regs[rb] += s12 << 2;
+                               printf("ldrsl  r%d, [r%d, %d]!\n", rd, rb, s12 << 2);
+                       } else
+                               printf("ldrsl  r%d, [r%d, %d]\n", rd, rb, s12 << 2);
+                       break;
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_ldr_sib(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int ri  = (inst >>  5) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int ext = (inst >> 17) & 0x7;
+       int u7  = (inst >> 10) & 0x7f;
+
+       int64_t  addr   = naja->regs[rb];
+       uint64_t offset;
+       uint8_t* data;
+
+       scf_logd("ldr   r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+       scf_logd("rd: %#lx\n", naja->regs[rd]);
+       scf_logd("rb: %#lx\n", naja->regs[rb]);
+       scf_logd("ri: %#lx\n", naja->regs[ri]);
+
+       if (addr >= (int64_t)vm->data->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->data->data + vm->data->len) {
+                       scf_loge("addr: %#lx, %#lx\n", addr, (int64_t)vm->data->data + vm->data->len);
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->rodata->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->rodata->data + vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->text->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->text->data + vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr  >= 0x800000) {
+               data   = vm->data->data;
+               offset = addr - vm->data->addr;
+
+               if (offset >= vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x600000) {
+               data   = vm->rodata->data;
+               offset = addr - vm->rodata->addr;
+
+               if (offset >= vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x400000) {
+               data   = vm->text->data;
+               offset = addr - vm->text->addr;
+
+               if (offset >= vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else {
+               data   = naja->stack;
+               offset = addr;
+       }
+
+       offset += (naja->regs[ri] << u7);
+
+       if (data   == naja->stack) {
+               offset = -offset;
+
+               assert(offset >= 0);
+
+               if (naja->size < offset) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+               offset -= 1 << (ext & 0x3);
+       }
+
+       switch (ext) {
+               case 0:
+                       printf("ldrb  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(uint8_t*)(data + offset);
+                       break;
+
+               case 1:
+                       printf("ldrw  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(uint16_t*)(data + offset);
+                       break;
+
+               case 2:
+                       printf("ldrl  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(uint32_t*)(data + offset);
+                       break;
+
+               case 3:
+                       printf("ldr   r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(uint64_t*)(data + offset);
+                       break;
+
+               case 4:
+                       printf("ldrsb r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(int8_t*)(data + offset);
+                       break;
+
+               case 5:
+                       printf("ldrsw r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(int16_t*)(data + offset);
+                       break;
+
+               case 6:
+                       printf("ldrsl r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       naja->regs[rd] = *(int32_t*)(data + offset);
+                       break;
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_str_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int A   = (inst >> 20) & 0x1;
+       int ext = (inst >> 17) & 0x3;
+       int s12 = (inst >>  5) & 0xfff;
+
+       if (s12  & 0x800)
+               s12 |= 0xfffff000;
+
+       int64_t  addr   = naja->regs[rb];
+       int64_t  offset = 0;
+       uint8_t* data;
+
+       if (addr >= (int64_t)vm->data->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->data->data + vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->rodata->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->rodata->data + vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->text->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->text->data + vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr  >= 0x800000) {
+               data   = vm->data->data;
+               offset = addr - vm->data->addr;
+
+               scf_loge("rb: %d, offset: %ld, addr: %#lx, %#lx\n", rb, offset, addr, vm->data->addr);
+
+               if (offset >= vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x600000) {
+               data   = vm->rodata->data;
+               offset = addr - vm->rodata->addr;
+
+               if (offset >= vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x400000) {
+               data   = vm->text->data;
+               offset = addr - vm->text->addr;
+
+               if (offset >= vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else {
+               data   = naja->stack;
+               offset = addr;
+       }
+
+       offset += s12 << ext;
+
+       if (data   == naja->stack) {
+               offset = -offset;
+
+               scf_logd("offset0: %ld, size: %ld\n", offset, naja->size);
+
+               assert(offset > 0);
+
+               if (naja->size < offset) {
+                       data = realloc(naja->stack, offset + STACK_INC);
+                       if (!data)
+                               return -ENOMEM;
+
+                       naja->stack = data;
+                       naja->size  = offset + STACK_INC;
+               }
+
+               offset -= 1 << ext;
+       }
+
+       switch (ext) {
+               case 0:
+                       *(uint8_t*)(data + offset) = naja->regs[rd];
+                       if (A) {
+                               naja->regs[rb] += s12;
+                               printf("strb   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       } else
+                               printf("strb   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 1:
+                       *(uint16_t*)(data + offset) = naja->regs[rd];
+                       if (A) {
+                               naja->regs[rb] += s12 << 1;
+                               printf("strw   r%d, [r%d, %d]!\n", rd, rb, s12 << 1);
+                       } else
+                               printf("strw   r%d, [r%d, %d]\n", rd, rb, s12 << 1);
+                       break;
+
+               case 2:
+                       *(uint32_t*)(data + offset) = naja->regs[rd];
+                       if (A) {
+                               naja->regs[rb] += s12 << 2;
+                               printf("strl   r%d, [r%d, %d]!\n", rd, rb, s12 << 2);
+                       } else
+                               printf("strl   r%d, [r%d, %d],  %d, %p\n", rd, rb, s12 << 2, *(uint32_t*)(data + offset), data + offset);
+                       break;
+
+               case 3:
+                       *(uint64_t*)(data + offset) = naja->regs[rd];
+                       if (A) {
+                               naja->regs[rb] += s12 << 3;
+                               printf("str    r%d, [r%d, %d]!, rd: %#lx, rb: %ld, %p\n", rd, rb, s12 << 3, naja->regs[rd], naja->regs[rb], data + offset);
+                       } else
+                               printf("str    r%d, [r%d, %d]\n", rd, rb, s12 << 3);
+                       break;
+
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_str_sib(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int ri  = (inst >>  5) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int ext = (inst >> 17) & 0x3;
+       int u7  = (inst >> 10) & 0x7f;
+
+       uint64_t addr   = naja->regs[rb];
+       uint64_t offset = 0;
+       uint8_t* data;
+
+       if (addr >= (int64_t)vm->data->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->data->data + vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->rodata->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->rodata->data + vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= (int64_t)vm->text->data) {
+               data  = (uint8_t*)addr;
+
+               if (addr >= (int64_t)vm->text->data + vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr  >= 0x800000) {
+               data   = vm->data->data;
+               offset = addr - vm->data->addr;
+
+               if (offset >= vm->data->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x600000) {
+               data   = vm->rodata->data;
+               offset = addr - vm->rodata->addr;
+
+               if (offset >= vm->rodata->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else if (addr >= 0x400000) {
+               data   = vm->text->data;
+               offset = addr - vm->text->addr;
+
+               if (offset >= vm->text->len) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+       } else {
+               data   = naja->stack;
+               offset = addr;
+       }
+
+       offset += naja->regs[ri] << u7;
+
+       if (data   == naja->stack) {
+               offset = -offset;
+
+               assert(offset >= 0);
+
+               if (naja->size < offset) {
+                       scf_loge("\n");
+                       return -1;
+               }
+
+               offset -= 1 << ext;
+       }
+
+       switch (ext) {
+               case 0:
+                       printf("strb  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       *(uint8_t*)(data + offset) = naja->regs[rd];
+                       break;
+
+               case 1:
+                       printf("strw  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       *(uint16_t*)(data + offset) = naja->regs[rd];
+                       break;
+
+               case 2:
+                       printf("strl  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       *(uint32_t*)(data + offset) = naja->regs[rd];
+                       break;
+
+               case 3:
+                       printf("str   r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+
+                       *(uint64_t*)(data + offset) = naja->regs[rd];
+                       break;
+
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_and(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       scf_logw("\n");
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               naja->regs[rd]  = naja->regs[rs0] & uimm15;
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               uint64_t rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       naja->regs[rd]  = naja->regs[rs0] & (naja->regs[rs1] << uimm8);
+               else if (1 == sh)
+                       naja->regs[rd]  = naja->regs[rs0] & (naja->regs[rs1] >> uimm8);
+               else
+                       naja->regs[rd]  = naja->regs[rs0] & (((int64_t)naja->regs[rs1]) >> uimm8);
+       }
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_teq(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       scf_logw("\n");
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               naja->flags = naja->regs[rs0] & uimm15;
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               uint64_t rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       naja->flags = naja->regs[rs0] & (naja->regs[rs1] << uimm8);
+               else if (1 == sh)
+                       naja->flags = naja->regs[rs0] & (naja->regs[rs1] >> uimm8);
+               else
+                       naja->flags = naja->regs[rs0] & (((int64_t)naja->regs[rs1]) >> uimm8);
+       }
+
+       naja->flags = !naja->flags;
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_or(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       scf_logw("\n");
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               naja->regs[rd]  = naja->regs[rs0] | uimm15;
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               uint64_t rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       naja->regs[rd]  = naja->regs[rs0] | (naja->regs[rs1] << uimm8);
+               else if (1 == sh)
+                       naja->regs[rd]  = naja->regs[rs0] | (naja->regs[rs1] >> uimm8);
+               else
+                       naja->regs[rd]  = naja->regs[rs0] | (((int64_t)naja->regs[rs1]) >> uimm8);
+       }
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_jmp_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int simm26 = inst & 0x3ffffff;
+
+       if (simm26  & 0x2000000)
+               simm26 |= 0xfc000000;
+
+       naja->ip += simm26 << 2;
+       printf("jmp    %#lx\n", naja->ip);
+       return 0;
+}
+
+static int __naja_call_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int simm26 = inst & 0x3ffffff;
+
+       if (simm26  & 0x2000000)
+               simm26 |= 0xfc000000;
+
+       naja->regs[NAJA_REG_LR] = naja->ip + 4;
+
+       naja->ip += simm26 << 2;
+
+       printf("call   %#lx\n", naja->ip);
+       return 0;
+}
+
+static int __naja_jmp_reg(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       if (inst & 0x1) {
+
+               int cc  = (inst >> 1) & 0xf;
+               int s21 = (inst >> 5) & 0x1fffff;
+
+               if (s21  & 0x100000)
+                       s21 |= 0xffe00000;
+
+               s21 <<= 2;
+
+               if (0 == (cc & naja->flags))
+                       naja->ip  += s21;
+               else
+                       naja->ip  += 4;
+
+               if (0 == cc)
+                       printf("jz     %#lx, flags: %#lx\n", naja->ip, naja->flags);
+
+               else if (1 == cc)
+                       printf("jnz    %#lx, flags: %#lx\n", naja->ip, naja->flags);
+
+               else if (2 == cc)
+                       printf("jge    %#lx, flags: %#lx\n", naja->ip, naja->flags);
+
+               else if (3 == cc)
+                       printf("jgt    %#lx, flags: %#lx\n", naja->ip, naja->flags);
+
+               else if (4 == cc)
+                       printf("jle    %#lx, flags: %#lx\n", naja->ip, naja->flags);
+
+               else if (5 == cc)
+                       printf("jlt    %#lx, flags: %#lx\n", naja->ip, naja->flags);
+               else {
+                       scf_loge("\n");
+                       return -EINVAL;
+               }
+
+       } else {
+               int rd = (inst >> 21) & 0x1f;
+
+               if (naja_vm_dynamic_link == (void*)naja->regs[rd]) {
+
+                       printf("\033[36mjmp    r%d, %#lx@plt\033[0m\n", rd, naja->regs[rd]);
+
+                       int ret = naja_vm_dynamic_link(vm);
+                       if (ret < 0) {
+                               scf_loge("\n");
+                               return ret;
+                       }
+
+                       naja->ip = naja->regs[NAJA_REG_LR];
+
+               } else if (naja->regs[rd] < vm->text->addr
+                               || naja->regs[rd] > vm->text->addr + vm->text->len) {
+
+                       printf("\033[36mjmp    r%d, %#lx@plt\033[0m\n", rd, naja->regs[rd]);
+
+                       naja_dyn_func_pt pt = (naja_dyn_func_pt) naja->regs[rd];
+
+                       naja->regs[0] = pt(naja->regs[0],
+                                       naja->regs[1],
+                                       naja->regs[2],
+                                       naja->regs[3],
+                                       naja->regs[4],
+                                       naja->regs[5],
+                                       naja->regs[6],
+                                       naja->regs[7]);
+
+                       naja->ip = naja->regs[NAJA_REG_LR];
+               } else {
+                       naja->ip = naja->regs[rd];
+
+                       printf("jmp    r%d, %#lx\n", rd, naja->regs[rd]);
+               }
+       }
+
+       return 0;
+}
+
+
+static int __naja_call_reg(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd = (inst >> 21) & 0x1f;
+
+       naja->regs[NAJA_REG_LR]   = naja->ip + 4;
+
+       if (naja_vm_dynamic_link == (void*)naja->regs[rd]) {
+
+               printf("\033[36mcall  r%d, %#lx@plt\033[0m\n", rd, naja->regs[rd]);
+
+               int ret = naja_vm_dynamic_link(vm);
+               if (ret < 0) {
+                       scf_loge("\n");
+                       return ret;
+               }
+
+               naja->ip = naja->regs[NAJA_REG_LR];
+
+       } else if (naja->regs[rd] < vm->text->addr
+                       || naja->regs[rd] > vm->text->addr + vm->text->len) {
+
+               printf("\033[36mcall  r%d, %#lx@plt\033[0m\n", rd, naja->regs[rd]);
+
+               naja_dyn_func_pt pt = (naja_dyn_func_pt) naja->regs[rd];
+
+               naja->regs[0] = pt(naja->regs[0],
+                                          naja->regs[1],
+                                          naja->regs[2],
+                                          naja->regs[3],
+                                          naja->regs[4],
+                                          naja->regs[5],
+                                          naja->regs[6],
+                                          naja->regs[7]);
+
+               naja->ip = naja->regs[NAJA_REG_LR];
+       } else {
+               printf("call  r%d, %#lx\n", rd, naja->regs[rd]);
+               naja->ip = naja->regs[rd];
+       }
+
+       return 0;
+}
+
+static int __naja_adrp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd  = (inst >> 21) & 0x1f;
+       int s21 =  inst & 0x1fffff;
+
+       if (s21  & 0x100000)
+               s21 |= ~0x1fffff;
+
+       naja->regs[rd] = (naja->ip + ((int64_t)s21 << 15)) & ~0x7fffULL;
+
+       if (naja->regs[rd] >= 0x800000)
+               naja->regs[rd]  = naja->regs[rd] - vm->data->addr + (uint64_t)vm->data->data;
+
+       else if (naja->regs[rd] >= 0x600000)
+               naja->regs[rd]  = naja->regs[rd] - vm->rodata->addr + (uint64_t)vm->rodata->data;
+
+       else if (naja->regs[rd] >= 0x400000)
+               naja->regs[rd]  = naja->regs[rd] - vm->text->addr + (uint64_t)vm->text->data;
+
+       printf("adrp   r%d, [rip, %d],  %#lx\n", rd, s21, naja->regs[rd]);
+
+       naja->ip += 4;
+       return 0;
+}
+
+static int __naja_ret(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       naja->ip   =  naja->regs[NAJA_REG_LR];
+       int64_t sp = -naja->regs[NAJA_REG_SP];
+
+       assert (sp >= 0);
+
+       if (naja->size > sp + STACK_INC) {
+
+               void* p = realloc(naja->stack, sp + STACK_INC);
+               if (!p) {
+                       scf_loge("\n");
+                       return -ENOMEM;
+               }
+
+               naja->stack = p;
+               naja->size  = sp + STACK_INC;
+       }
+
+       printf("ret,   %#lx, sp: %ld, stack->size: %ld\n", naja->ip, sp, naja->size);
+       return 0;
+}
+
+static int __naja_setcc(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd = (inst >> 21) & 0x1f;
+       int cc = (inst >> 17) & 0xf;
+
+       naja->regs[rd] = 0 == (cc & naja->flags);
+
+       if (SCF_VM_Z == cc)
+               printf("setz   r%d\n", rd);
+
+       else if (SCF_VM_NZ == cc)
+               printf("setnz  r%d\n", rd);
+
+       else if (SCF_VM_GE == cc)
+               printf("setge  r%d\n", rd);
+
+       else if (SCF_VM_GT == cc)
+               printf("setgt  r%d\n", rd);
+
+       else if (SCF_VM_LT == cc)
+               printf("setlt  r%d\n", rd);
+
+       else if (SCF_VM_LE == cc)
+               printf("setle  r%d\n", rd);
+       else {
+               scf_loge("inst: %#x\n", inst);
+               return -EINVAL;
+       }
+
+       naja->ip  += 4;
+       return 0;
+}
+
+static int __naja_mov(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+       int X   = (inst >> 19) & 0x1;
+       int opt = (inst >> 16) & 0x7;
+
+       if (I) {
+               if (0 == opt) {
+                       naja->regs[rd]  = inst & 0xffff;
+
+                       if (X && (inst & 0x8000)) {
+                               naja->regs[rd] |= ~0xffffULL;
+                               printf("movsb  r%d, %d\n", rd, inst & 0xffff);
+                       } else {
+                               printf("mov    r%d, %d\n", rd, inst & 0xffff);
+                       }
+
+               } else if (1 == opt) {
+                       naja->regs[rd] |= (inst & 0xffffULL) << 16;
+
+                       printf("mov    r%d, %d << 16\n", rd, inst & 0xffff);
+
+               } else if (2 == opt) {
+                       naja->regs[rd] |= (inst & 0xffffULL) << 32;
+
+                       printf("mov    r%d, %d << 32\n", rd, inst & 0xffff);
+
+               } else if (3 == opt) {
+                       naja->regs[rd] |= (inst & 0xffffULL) << 48;
+
+                       printf("mov    r%d, %d << 48\n", rd, inst & 0xffff);
+
+               } else if (7 == opt) {
+                       naja->regs[rd] = ~(inst & 0xffffULL);
+
+                       printf("mvn    r%d, %d\n", rd, inst & 0xffff);
+               }
+
+       } else {
+               int rs  =  inst & 0x1f;
+               int rs1 = (inst >> 5) & 0x1f;
+               int u11 = (inst >> 5) & 0x7ff;
+
+               if (0 == opt) {
+                       if (X) {
+                               printf("mov    r%d, r%d LSL r%d\n", rd, rs, rs1);
+
+                               naja->regs[rd] = naja->regs[rs] << naja->regs[rs1];
+                       } else {
+                               naja->regs[rd] = naja->regs[rs] << u11;
+
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d LSL %d\n", rd, rs, u11);
+                       }
+
+               } else if (1 == opt) {
+                       if (X) {
+                               printf("mov    r%d, r%d LSR r%d\n", rd, rs, rs1);
+
+                               naja->regs[rd] = naja->regs[rs] >> naja->regs[rs1];
+                       } else {
+                               naja->regs[rd] = naja->regs[rs] >> u11;
+
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d LSR %d\n", rd, rs, u11);
+                       }
+               } else if (2 == opt) {
+                       if (X) {
+                               printf("mov    r%d, r%d ASR r%d\n", rd, rs, rs1);
+
+                               naja->regs[rd] = (int64_t)naja->regs[rs] >> naja->regs[rs1];
+                       } else {
+                               naja->regs[rd] = (int64_t)naja->regs[rs] >> u11;
+
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d ASR %d\n", rd, rs, u11);
+                       }
+               } else if (3 == opt) {
+                       printf("NOT    r%d, r%d\n", rd, rs);
+
+                       naja->regs[rd] = ~naja->regs[rs];
+               } else if (4 == opt) {
+                       naja->regs[rd] = -naja->regs[rs];
+
+                       printf("NEG    r%d, r%d\n", rd, rs);
+
+               } else if (5 == opt) {
+                       if (X) {
+                               printf("movsb  r%d, r%d\n", rd, rs);
+
+                               naja->regs[rd] = (int8_t)naja->regs[rs];
+                       } else {
+                               naja->regs[rd] = (uint8_t)naja->regs[rs];
+
+                               printf("movzb  r%d, r%d\n", rd, rs);
+                       }
+               } else if (6 == opt) {
+                       if (X) {
+                               printf("movsw  r%d, r%d\n", rd, rs);
+
+                               naja->regs[rd] = (int16_t)naja->regs[rs];
+                       } else {
+                               naja->regs[rd] = (uint16_t)naja->regs[rs];
+
+                               printf("movzw  r%d, r%d\n", rd, rs);
+                       }
+               } else if (7 == opt) {
+                       if (X) {
+                               printf("movsl  r%d, r%d\n", rd, rs);
+
+                               naja->regs[rd] = (int32_t)naja->regs[rs];
+                       } else {
+                               naja->regs[rd] = (uint32_t)naja->regs[rs];
+
+                               printf("movzl  r%d, r%d\n", rd, rs);
+                       }
+               }
+       }
+
+       naja->ip += 4;
+       return 0;
+}
+
+static naja_opcode_pt  naja_opcodes[64] =
+{
+       __naja_add,      // 0
+       __naja_sub,      // 1
+       __naja_mul,      // 2
+       __naja_div,      // 3
+       __naja_ldr_disp, // 4
+       __naja_str_disp, // 5
+       __naja_and,      // 6
+       __naja_or,       // 7
+       __naja_jmp_disp, // 8
+       __naja_cmp,      // 9
+       __naja_jmp_reg,  //10
+       __naja_setcc,    //11
+       __naja_ldr_sib,  //12
+       __naja_str_sib,  //13
+       __naja_teq,      //14
+       __naja_mov,      //15
+
+       NULL,            //16
+       NULL,            //17
+       NULL,            //18
+       NULL,            //19
+       NULL,            //20
+       NULL,            //21
+       NULL,            //22
+       NULL,            //23
+       __naja_call_disp,//24
+       NULL,            //25
+       __naja_call_reg, //26
+       NULL,            //27
+       NULL,            //28
+       NULL,            //29
+       NULL,            //30
+       NULL,            //31
+
+       NULL,            //32
+       NULL,            //33
+       NULL,            //34
+       NULL,            //35
+       NULL,            //36
+       NULL,            //37
+       NULL,            //38
+       NULL,            //39
+       NULL,            //40
+       NULL,            //41
+       __naja_adrp,     //42
+       NULL,            //43
+       NULL,            //44
+       NULL,            //45
+       NULL,            //46
+       NULL,            //47
+
+       NULL,            //48
+       NULL,            //49
+       NULL,            //50
+       NULL,            //51
+       NULL,            //52
+       NULL,            //53
+       NULL,            //54
+       NULL,            //55
+       __naja_ret,      //56
+       NULL,            //57
+       NULL,            //58
+       NULL,            //59
+       NULL,            //60
+       NULL,            //61
+       NULL,            //62
+       NULL,            //63
+};
+
+static void __naja_vm_exit()
+{
+}
+
+static int __naja_vm_run(scf_vm_t* vm, const char* path, const char* sys)
+{
+       scf_vm_naja_t* naja = vm->priv;
+       Elf64_Ehdr     eh;
+       Elf64_Shdr     sh;
+
+       fseek(vm->elf->fp, 0, SEEK_SET);
+
+       int ret  = fread(&eh, sizeof(Elf64_Ehdr), 1, vm->elf->fp);
+       if (ret != 1)
+               return -1;
+
+       if (vm->jmprel) {
+               fseek(vm->elf->fp, eh.e_shoff, SEEK_SET);
+
+               int i;
+               for (i = 0; i < eh.e_shnum; i++) {
+
+                       ret = fread(&sh, sizeof(Elf64_Shdr), 1, vm->elf->fp);
+                       if (ret != 1)
+                               return -1;
+
+                       if (vm->jmprel_addr == sh.sh_addr) {
+                               vm->jmprel_size  = sh.sh_size;
+                               break;
+                       }
+               }
+
+               if (i == eh.e_shnum) {
+                       scf_loge("\n");
+                       return -1;
+               }
+       }
+
+       naja->stack  = calloc(STACK_INC, sizeof(uint64_t));
+       if (!naja->stack)
+               return -ENOMEM;
+
+       naja->size   = STACK_INC;
+       naja->_start = eh.e_entry;
+       naja->ip     = eh.e_entry;
+
+       naja->regs[NAJA_REG_LR] = (uint64_t)__naja_vm_exit;
+
+       int n = 0;
+       while ((uint64_t)__naja_vm_exit != naja->ip) {
+
+               int64_t offset = naja->ip - vm->text->addr;
+
+               if (offset >= vm->text->len) {
+                       scf_loge("naja->ip: %#lx, %p\n", naja->ip, __naja_vm_exit);
+                       return -1;
+               }
+
+               uint32_t inst = *(uint32_t*)(vm->text->data + offset);
+
+               naja_opcode_pt pt = naja_opcodes[(inst >> 26) & 0x3f];
+
+               if (!pt) {
+                       scf_loge("inst: %d, %#x\n", (inst >> 26) & 0x3f, inst);
+                       return -EINVAL;
+               }
+
+               printf("%4d, %#lx: ", n++, naja->ip);
+               ret = pt(vm, inst);
+               if (ret < 0) {
+                       scf_loge("\n");
+                       return ret;
+               }
+
+               usleep(50 * 1000);
+       }
+
+       scf_logw("r0: %ld\n", naja->regs[0]);
+       return naja->regs[0];
+}
+
+static int naja_vm_run(scf_vm_t* vm, const char* path, const char* sys)
+{
+       int ret = naja_vm_init(vm, path, sys);
+       if (ret < 0) {
+               scf_loge("\n");
+               return ret;
+       }
+
+       return __naja_vm_run(vm, path, sys);
+}
+
+scf_vm_ops_t  vm_ops_naja =
+{
+       .name  = "naja",
+       .open  = naja_vm_open,
+       .close = naja_vm_close,
+       .run   = naja_vm_run,
+};
+
diff --git a/vm/scf_vm_naja_asm.c b/vm/scf_vm_naja_asm.c
new file mode 100644 (file)
index 0000000..828096e
--- /dev/null
@@ -0,0 +1,808 @@
+#include"scf_vm.h"
+
+#define NAJA_REG_FP   29
+#define NAJA_REG_LR   30
+#define NAJA_REG_SP   31
+
+static int __naja_add(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+               printf("add    r%d, r%d, %lu\n", rd, rs0, uimm15);
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("add    r%d, r%d, r%d LSL %lu\n", rd, rs0, rs1, uimm8);
+               else if (1 == sh)
+                       printf("add    r%d, r%d, r%d LSR %lu\n", rd, rs0, rs1, uimm8);
+               else
+                       printf("add    r%d, r%d, r%d ASR %lu\n", rd, rs0, rs1, uimm8);
+       }
+
+       return 0;
+}
+
+static int __naja_sub(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+               printf("sub    r%d, r%d, %lu\n", rd, rs0, uimm15);
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("sub    r%d, r%d, r%d << %lu\n", rd, rs0, rs1, uimm8);
+               else if (1 == sh)
+                       printf("sub    r%d, r%d, r%d LSR %lu\n", rd, rs0, rs1, uimm8);
+               else
+                       printf("sub    r%d, r%d, r%d ASR %lu\n", rd, rs0, rs1, uimm8);
+       }
+
+       return 0;
+}
+
+static int __naja_cmp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       int ret = 0;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+               printf("cmp    r%d, %ld,  rs0: %lx, ret: %d\n", rs0, uimm15, naja->regs[rs0], ret);
+       } else {
+               uint64_t sh     = (inst >> 18) & 0x3;
+               uint64_t uimm8  = (inst >> 10) & 0xff;
+               int      rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("cmp    r%d, r%d LSL %ld,  rs0: %#lx, rs1: %#lx, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+               else if (1 == sh)
+                       printf("cmp    r%d, r%d LSR %ld,  rs0: %#lx, rs1: %#lx, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+               else
+                       printf("cmp    r%d, r%d ASR %ld,  rs0: %#lx, rs1: %ld, ret: %d\n", rs0, rs1, uimm8, naja->regs[rs0], naja->regs[rs1], ret);
+       }
+
+       return 0;
+}
+
+static int __naja_mul(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rs1 = (inst >>  5) & 0x1f;
+       int rs2 = (inst >> 10) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int S   = (inst >> 20) & 0x1;
+       int opt = (inst >> 15) & 0x3;
+
+       if (S) {
+               if (0 == opt)
+                       printf("smadd  r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else if (1 == opt)
+                       printf("smsub  r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else
+                       printf("smul   r%d, r%d, r%d\n", rd, rs0, rs1);
+       } else {
+               if (0 == opt)
+                       printf("madd   r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else if (1 == opt)
+                       printf("msub   r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else
+                       printf("mul    r%d, r%d, r%d\n", rd, rs0, rs1);
+       }
+
+       return 0;
+}
+
+static int __naja_div(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rs1 = (inst >>  5) & 0x1f;
+       int rs2 = (inst >> 10) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int S   = (inst >> 20) & 0x1;
+       int opt = (inst >> 15) & 0x3;
+
+       if (S) {
+               if (0 == opt)
+                       printf("sdadd  r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else if (1 == opt)
+                       printf("sdsub  r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else
+                       printf("sdiv   r%d, r%d, r%d\n", rd, rs0, rs1);
+       } else {
+               if (0 == opt)
+                       printf("dadd   r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else if (1 == opt)
+                       printf("dsub   r%d, r%d, r%d, r%d\n", rd, rs2, rs0, rs1);
+               else
+                       printf("div    r%d, r%d, r%d\n", rd, rs0, rs1);
+       }
+
+       return 0;
+}
+
+static int __naja_ldr_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int A   = (inst >> 20) & 0x1;
+       int ext = (inst >> 17) & 0x7;
+       int s12 = (inst >>  5) & 0xfff;
+
+       if (s12  & 0x800)
+               s12 |= 0xfffff000;
+
+       switch (ext) {
+               case 0:
+                       if (A)
+                               printf("ldrb   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       else
+                               printf("ldrb   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 1:
+                       if (A)
+                               printf("ldrw   r%d, [r%d, %d]!\n", rd, rb, s12 << 1);
+                       else
+                               printf("ldrw   r%d, [r%d, %d]\n", rd, rb, s12 << 1);
+                       break;
+
+               case 2:
+                       if (A)
+                               printf("ldrl   r%d, [r%d, %d]!\n", rd, rb, s12 << 2);
+                       else
+                               printf("ldrl   r%d, [r%d, %d]\n", rd, rb, s12 << 2);
+                       break;
+
+               case 3:
+                       if (A)
+                               printf("ldr    r%d, [r%d, %d]!\n", rd, rb, s12 << 3);
+                       else
+                               printf("ldr    r%d, [r%d, %d]\n", rd, rb, s12 << 3);
+                       break;
+
+               case 4:
+                       if (A)
+                               printf("ldrsb  r%d, [r%d, %d]!\n", rd, rb, s12);
+                       else
+                               printf("ldrsb  r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 5:
+                       if (A)
+                               printf("ldrsw  r%d, [r%d, %d]!\n", rd, rb, s12 << 1);
+                       else
+                               printf("ldrsw  r%d, [r%d, %d]\n", rd, rb, s12 << 1);
+                       break;
+
+               case 6:
+                       if (A)
+                               printf("ldrsl  r%d, [r%d, %d]!\n", rd, rb, s12 << 2);
+                       else
+                               printf("ldrsl  r%d, [r%d, %d]\n", rd, rb, s12 << 2);
+                       break;
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __naja_ldr_sib(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int ri  = (inst >>  5) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int ext = (inst >> 17) & 0x7;
+       int u7  = (inst >> 10) & 0x7f;
+
+       switch (ext) {
+               case 0:
+                       printf("ldrb  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 1:
+                       printf("ldrw  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 2:
+                       printf("ldrl  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 3:
+                       printf("ldr   r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 4:
+                       printf("ldrsb r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 5:
+                       printf("ldrsw r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 6:
+                       printf("ldrsl r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __naja_str_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int A   = (inst >> 20) & 0x1;
+       int ext = (inst >> 17) & 0x3;
+       int s12 = (inst >>  5) & 0xfff;
+
+       if (s12  & 0x800)
+               s12 |= 0xfffff000;
+
+       switch (ext) {
+               case 0:
+                       if (A)
+                               printf("strb   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       else
+                               printf("strb   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 1:
+                       if (A)
+                               printf("strw   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       else
+                               printf("strw   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 2:
+                       if (A)
+                               printf("strl   r%d, [r%d, %d]!\n", rd, rb, s12);
+                       else
+                               printf("strl   r%d, [r%d, %d]\n", rd, rb, s12);
+                       break;
+
+               case 3:
+                       if (A)
+                               printf("str    r%d, [r%d, %d]!\n", rd, rb, s12 << 3);
+                       else
+                               printf("str    r%d, [r%d, %d]\n", rd, rb, s12 << 3);
+                       break;
+
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __naja_str_sib(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rb  =  inst        & 0x1f;
+       int ri  = (inst >>  5) & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int ext = (inst >> 17) & 0x7;
+       int u7  = (inst >> 10) & 0x7f;
+
+       switch (ext) {
+               case 0:
+                       printf("strb  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 1:
+                       printf("strw  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 2:
+                       printf("strl  r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               case 3:
+                       printf("str   r%d, [r%d, r%d, %d]\n", rd, rb, ri, u7);
+                       break;
+
+               default:
+                       scf_loge("\n");
+                       return -1;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __naja_and(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               printf("and   r%d, r%d, %#lx\n", rd, rs0, uimm15);
+       } else {
+               int sh     = (inst >> 18) & 0x3;
+               int uimm8  = (inst >> 10) & 0xff;
+               int rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("and   r%d, r%d, r%d LSL %#x\n", rd, rs0, rs1, uimm8);
+               else if (1 == sh)
+                       printf("and   r%d, r%d, r%d LSR %#x\n", rd, rs0, rs1, uimm8);
+               else
+                       printf("and   r%d, r%d, r%d ASR %#x\n", rd, rs0, rs1, uimm8);
+       }
+
+       return 0;
+}
+
+static int __naja_teq(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               printf("teq   r%d, %#lx\n", rs0, uimm15);
+       } else {
+               int sh     = (inst >> 18) & 0x3;
+               int uimm8  = (inst >> 10) & 0xff;
+               int rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("teq   r%d, r%d LSL %#x\n", rs0, rs1, uimm8);
+               else if (1 == sh)
+                       printf("teq   r%d, r%d LSR %#x\n", rs0, rs1, uimm8);
+               else
+                       printf("teq   r%d, r%d ASR %#x\n", rs0, rs1, uimm8);
+       }
+
+       return 0;
+}
+
+static int __naja_or(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rs0 =  inst        & 0x1f;
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+
+       if (I) {
+               uint64_t uimm15 = (inst >> 5) & 0x7fff;
+
+               printf("or    r%d, r%d, %#lx\n", rd, rs0, uimm15);
+       } else {
+               int sh     = (inst >> 18) & 0x3;
+               int uimm8  = (inst >> 10) & 0xff;
+               int rs1    = (inst >>  5) & 0x1f;
+
+               if (0 == sh)
+                       printf("or    r%d, r%d, r%d LSL %#x\n", rd, rs0, rs1, uimm8);
+               else if (1 == sh)
+                       printf("or    r%d, r%d, r%d LSR %#x\n", rd, rs0, rs1, uimm8);
+               else
+                       printf("or    r%d, r%d, r%d ASR %#x\n", rd, rs0, rs1, uimm8);
+       }
+
+       return 0;
+}
+
+static int __naja_jmp_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int simm26 = inst & 0x3ffffff;
+
+       if (simm26  & 0x2000000)
+               simm26 |= 0xfc000000;
+
+       uint64_t ip = naja->ip + (simm26 << 2);
+       printf("jmp    %#lx\n", ip);
+       return 0;
+}
+
+static int __naja_call_disp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int simm26 = inst & 0x3ffffff;
+
+       if (simm26  & 0x2000000)
+               simm26 |= 0xfc000000;
+
+       uint64_t ip = naja->ip + (simm26 << 2);
+       printf("call   %#lx\n", ip);
+       return 0;
+}
+
+static int __naja_jmp_reg(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       if (inst & 0x1) {
+
+               int cc  = (inst >> 1) & 0xf;
+               int s21 = (inst >> 5) & 0x1fffff;
+
+               if (s21  & 0x100000)
+                       s21 |= 0xffe00000;
+
+               s21 <<= 2;
+
+               uint64_t ip = naja->ip + s21;
+
+               if (0 == cc)
+                       printf("jz     %#lx\n", ip);
+
+               else if (1 == cc)
+                       printf("jnz    %#lx\n", ip);
+
+               else if (2 == cc)
+                       printf("jge    %#lx\n", ip);
+
+               else if (3 == cc)
+                       printf("jgt    %#lx\n", ip);
+
+               else if (4 == cc)
+                       printf("jle    %#lx\n", ip);
+
+               else if (5 == cc)
+                       printf("jlt    %#lx\n", ip);
+               else {
+                       scf_loge("\n");
+                       return -EINVAL;
+               }
+
+       } else {
+               int rd = (inst >> 21) & 0x1f;
+
+               printf("jmp    *r%d\n", rd);
+       }
+       return 0;
+}
+
+
+static int __naja_call_reg(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd = (inst >> 21) & 0x1f;
+
+       printf("call  r%d\n", rd);
+
+       return 0;
+}
+
+static int __naja_adrp(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd  = (inst >> 21) & 0x1f;
+       int s21 =  inst & 0x1fffff;
+
+       if (s21  & 0x100000)
+               s21 |= ~0x1fffff;
+
+       printf("adrp   r%d, [rip, %d]\n", rd, s21);
+
+       return 0;
+}
+
+static int __naja_ret(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       printf("ret\n");
+       return 0;
+}
+
+static int __naja_setcc(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd = (inst >> 21) & 0x1f;
+       int cc = (inst >> 17) & 0xf;
+
+       if (SCF_VM_Z == cc)
+               printf("setz   r%d\n", rd);
+
+       else if (SCF_VM_NZ == cc)
+               printf("setnz  r%d\n", rd);
+
+       else if (SCF_VM_GE == cc)
+               printf("setge  r%d\n", rd);
+
+       else if (SCF_VM_GT == cc)
+               printf("setgt  r%d\n", rd);
+
+       else if (SCF_VM_LT == cc)
+               printf("setlt  r%d\n", rd);
+
+       else if (SCF_VM_LE == cc)
+               printf("setle  r%d\n", rd);
+       else {
+               scf_loge("inst: %#x\n", inst);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int __naja_mov(scf_vm_t* vm, uint32_t inst)
+{
+       scf_vm_naja_t* naja = vm->priv;
+
+       int rd  = (inst >> 21) & 0x1f;
+       int I   = (inst >> 20) & 0x1;
+       int X   = (inst >> 19) & 0x1;
+       int opt = (inst >> 16) & 0x7;
+
+       if (I) {
+               if (0 == opt) {
+                       if (X && (inst & 0x8000))
+                               printf("movsb  r%d, %d\n", rd, inst & 0xffff);
+                       else
+                               printf("mov    r%d, %d\n", rd, inst & 0xffff);
+
+               } else if (1 == opt)
+                       printf("mov    r%d, %d << 16\n", rd, inst & 0xffff);
+               else if (2 == opt)
+                       printf("mov    r%d, %d << 32\n", rd, inst & 0xffff);
+               else if (3 == opt)
+                       printf("mov    r%d, %d << 48\n", rd, inst & 0xffff);
+               else if (7 == opt)
+                       printf("mvn    r%d, %d\n", rd, inst & 0xffff);
+
+       } else {
+               int rs  =  inst & 0x1f;
+               int rs1 = (inst >> 5) & 0x1f;
+               int u11 = (inst >> 5) & 0x7ff;
+
+               if (0 == opt) {
+                       if (X)
+                               printf("mov    r%d, r%d LSL r%d\n", rd, rs, rs1);
+                       else {
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d LSL %d\n", rd, rs, u11);
+                       }
+               } else if (1 == opt) {
+                       if (X)
+                               printf("mov    r%d, r%d LSR r%d\n", rd, rs, rs1);
+                       else {
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d LSR %d\n", rd, rs, u11);
+                       }
+
+               } else if (2 == opt) {
+                       if (X)
+                               printf("mov    r%d, r%d ASR r%d\n", rd, rs, rs1);
+                       else {
+                               if (0 == u11)
+                                       printf("mov    r%d, r%d\n", rd, rs);
+                               else
+                                       printf("mov    r%d, r%d ASR %d\n", rd, rs, u11);
+                       }
+
+               } else if (3 == opt)
+                       printf("NOT    r%d, r%d\n", rd, rs);
+               else if (4 == opt)
+                       printf("NEG    r%d, r%d\n", rd, rs);
+
+               else if (5 == opt) {
+                       if (X)
+                               printf("movsb  r%d, r%d\n", rd, rs);
+                       else
+                               printf("movzb  r%d, r%d\n", rd, rs);
+
+               } else if (6 == opt) {
+                       if (X)
+                               printf("movsw  r%d, r%d\n", rd, rs);
+                       else
+                               printf("movzw  r%d, r%d\n", rd, rs);
+
+               } else if (7 == opt) {
+                       if (X)
+                               printf("movsl  r%d, r%d\n", rd, rs);
+                       else
+                               printf("movzl  r%d, r%d\n", rd, rs);
+               }
+       }
+
+       return 0;
+}
+
+static naja_opcode_pt  naja_opcodes[64] =
+{
+       __naja_add,      // 0
+       __naja_sub,      // 1
+       __naja_mul,      // 2
+       __naja_div,      // 3
+       __naja_ldr_disp, // 4
+       __naja_str_disp, // 5
+       __naja_and,      // 6
+       __naja_or,       // 7
+       __naja_jmp_disp, // 8
+       __naja_cmp,      // 9
+       __naja_jmp_reg,  //10
+       __naja_setcc,    //11
+       __naja_ldr_sib,  //12
+       __naja_str_sib,  //13
+       __naja_teq,      //14
+       __naja_mov,      //15
+
+       NULL,            //16
+       NULL,            //17
+       NULL,            //18
+       NULL,            //19
+       NULL,            //20
+       NULL,            //21
+       NULL,            //22
+       NULL,            //23
+       __naja_call_disp,//24
+       NULL,            //25
+       __naja_call_reg, //26
+       NULL,            //27
+       NULL,            //28
+       NULL,            //29
+       NULL,            //30
+       NULL,            //31
+
+       NULL,            //32
+       NULL,            //33
+       NULL,            //34
+       NULL,            //35
+       NULL,            //36
+       NULL,            //37
+       NULL,            //38
+       NULL,            //39
+       NULL,            //40
+       NULL,            //41
+       __naja_adrp,     //42
+       NULL,            //43
+       NULL,            //44
+       NULL,            //45
+       NULL,            //46
+       NULL,            //47
+
+       NULL,            //48
+       NULL,            //49
+       NULL,            //50
+       NULL,            //51
+       NULL,            //52
+       NULL,            //53
+       NULL,            //54
+       NULL,            //55
+       __naja_ret,      //56
+       NULL,            //57
+       NULL,            //58
+       NULL,            //59
+       NULL,            //60
+       NULL,            //61
+       NULL,            //62
+       NULL,            //63
+};
+
+static int __naja_vm_run(scf_vm_t* vm, const char* path, const char* sys)
+{
+       scf_elf_sym_t* s;
+       scf_vm_naja_t* naja = vm->priv;
+       scf_vector_t*  syms = scf_vector_alloc();
+       if (!syms)
+               return -ENOMEM;
+
+       int ret = scf_elf_read_syms(vm->elf, syms, ".symtab");
+       if (ret < 0)
+               return ret;
+
+       int i;
+       for (i = 0; i < syms->size; i++) {
+               s  =        syms->data[i];
+
+               if (ELF64_ST_TYPE(s->st_info) != STT_FUNC)
+                       continue;
+
+               int64_t offset = s->st_value - vm->text->addr;
+
+               if (offset >= vm->text->len)
+                       return -1;
+
+               printf("\n%s: \n", s->name);
+               int j;
+               for (j = 0; j < s->st_size; j+= 4) {
+
+                       uint32_t inst = *(uint32_t*)(vm->text->data + offset + j);
+
+                       naja_opcode_pt pt = naja_opcodes[(inst >> 26) & 0x3f];
+
+                       if (!pt) {
+                               scf_loge("inst: %d, %#x\n", (inst >> 26) & 0x3f, inst);
+                               continue;
+                       }
+
+                       naja->ip = vm->text->addr + offset + j;
+
+                       printf("%4d, %#lx: ", j, naja->ip);
+
+                       ret = pt(vm, inst);
+                       if (ret < 0) {
+                               scf_loge("\n");
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int naja_vm_run(scf_vm_t* vm, const char* path, const char* sys)
+{
+       int ret = naja_vm_init(vm, path, sys);
+       if (ret < 0) {
+               scf_loge("\n");
+               return ret;
+       }
+
+       return __naja_vm_run(vm, path, sys);
+}
+
+scf_vm_ops_t  vm_ops_naja_asm =
+{
+       .name  = "naja_asm",
+       .open  = naja_vm_open,
+       .close = naja_vm_close,
+       .run   = naja_vm_run,
+};
+
diff --git a/vm/scf_vm_test.c b/vm/scf_vm_test.c
new file mode 100644 (file)
index 0000000..d9c02b0
--- /dev/null
@@ -0,0 +1,22 @@
+#include"scf_vm.h"
+
+int main()
+{
+       scf_vm_t* vm = NULL;
+
+       int ret = scf_vm_open(&vm, "naja");
+       if (ret < 0) {
+               scf_loge("\n");
+               return -1;
+       }
+
+       ret = scf_vm_run(vm, "../parse/1.out", "x64");
+       if (ret < 0) {
+               scf_loge("\n");
+               return -1;
+       }
+
+       printf("main ok\n");
+       return 0;
+}
+