2, lexer: support "\033" in string, so printf() can print with color.
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)
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;
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);
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);
}
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 &= 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:
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");
.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,
#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
};
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];
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);
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);
}
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;
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;
Elf64_Shdr sh_null;
scf_vector_t* sections;
+ scf_vector_t* phdrs;
Elf64_Shdr sh_symtab;
scf_vector_t* symbols;
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);
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;
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]) {
}
}
+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",
.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,
};
return -EINVAL;
}
- offset >> 1;
+ offset >>= 1;
SIZE = 1;
} else if (4 == size) {
return -EINVAL;
}
- offset >> 2;
+ offset >>= 2;
SIZE = 2;
} else if (8 == size) {
return -EINVAL;
}
- offset >> 3;
+ offset >>= 3;
SIZE = 3;
} else
return -EINVAL;
return -EINVAL;
}
- offset >> 1;
+ offset >>= 1;
SIZE = 1;
} else if (4 == size) {
return -EINVAL;
}
- offset >> 2;
+ offset >>= 2;
SIZE = 2;
} else if (8 == size) {
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 {
return -EINVAL;
}
- offset >> 1;
+ offset >>= 1;
SIZE = 1;
} else if (4 == size) {
return -EINVAL;
}
- offset >> 2;
+ offset >>= 2;
SIZE = 2;
} else if (8 == size) {
return -EINVAL;
}
- offset >> 3;
+ offset >>= 3;
SIZE = 3;
} else
return -EINVAL;
}
- offset >> 1;
+ offset >>= 1;
SIZE = 1;
} else if (4 == size) {
return -EINVAL;
}
- offset >> 2;
+ offset >>= 2;
SIZE = 2;
} else if (8 == size) {
return -EINVAL;
}
- offset >> 3;
+ offset >>= 3;
SIZE = 3;
} else
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;
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;
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;
} else if (bytes < 0 && bytes > -(0x1 << 20)) {
bytes >>= 2;
- bytes &= 0x7ffff;
+ bytes &= 0x1fffff;
bytes <<= 5;
} else
assert(0);
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;
}
}
+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",
.ADRSIB2G = naja_inst_ADRSIB2G,
.set_jmp_offset = naja_set_jmp_offset,
+ .cmp_update = naja_cmp_update,
};
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);
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);
};
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
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
--- /dev/null
+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
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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
+
--- /dev/null
+#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,
+};
+
--- /dev/null
+#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,
+};
+
--- /dev/null
+#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;
+}
+