Add Unconditional branch op support to Disassembler

This commit is contained in:
rkx1209 2018-01-02 03:55:24 +09:00
parent cf23eabba3
commit b00aea1a31
9 changed files with 91 additions and 15 deletions

View file

@ -47,7 +47,8 @@ static void DisasPCRelAddr(uint32_t insn, DisasCallback *cb) {
offset = sextract64 (insn, 5, 19);
offset = offset << 2 | sextract64 (insn, 29, 2);
rd = extract32 (insn, 0, 5);
base = PC - 4;
//base = PC - 4;
base = PC;
if (page) {
base &= ~0xfff;
@ -258,6 +259,49 @@ static void DisasDataProcImm(uint32_t insn, DisasCallback *cb) {
}
}
static void DisasUncondBrImm(uint32_t insn, DisasCallback *cb) {
uint64_t addr = PC + sextract32(insn, 0, 26) * 4 - 4;
if (insn & (1U << 31)) {
/* BL Branch with link */
cb->MoviI64(GPR_LR, addr, false, true);
}
/* B Branch / BL Branch with link */
cb->GotoI64(addr);
}
static void DisasBranchExcSys(uint32_t insn, DisasCallback *cb) {
switch (extract32(insn, 25, 7)) {
case 0x0a: case 0x0b:
case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
DisasUncondBrImm(insn, cb);
break;
case 0x1a: case 0x5a: /* Compare & branch (immediate) */
break;
case 0x1b: case 0x5b: /* Test & branch (immediate) */
break;
case 0x2a: /* Conditional branch (immediate) */
break;
case 0x6a: /* Exception generation / System */
if (insn & (1 << 24)) {
} else {
}
break;
case 0x6b: /* Unconditional branch (register) */
break;
default:
UnallocatedOp (insn);
break;
}
}
void DisasA64(uint32_t insn, DisasCallback *cb) {
switch (extract32 (insn, 25, 4)) {
case 0x0: case 0x1: case 0x2: case 0x3: // Unallocated
@ -267,6 +311,7 @@ void DisasA64(uint32_t insn, DisasCallback *cb) {
DisasDataProcImm (insn, cb);
break;
case 0xa: case 0xb: /* Branch, exception generation and system insns */
DisasBranchExcSys (insn, cb);
break;
case 0x4:
case 0x6:

View file

@ -5,18 +5,21 @@ Interpreter *Interpreter::inst = nullptr;
IntprCallback *Interpreter::disas_cb = nullptr;
int Interpreter::SingleStep() {
uint32_t inst = ARMv8::ReadInst (PC);
debug_print ("Run Code: 0x%08lx\n", inst);
PC += sizeof(uint32_t);
uint32_t inst = byte_swap(ARMv8::ReadInst (PC));
debug_print ("Run Code: 0x%lx: 0x%08lx\n", PC, inst);
Disassembler::DisasA64 (inst, disas_cb);
PC += sizeof(uint32_t);
return 0;
}
void Interpreter::Run() {
debug_print ("Running with Interpreter\n");
while (Cpu::GetState () == Cpu::State::Running) {
/*while (Cpu::GetState () == Cpu::State::Running) {
SingleStep ();
}
}*/
int test_max = 3;
for (int i = 0; i < test_max; i++)
SingleStep();
}
void IntprCallback::MoviI64(unsigned int reg_idx, uint64_t imm, bool unchanged, bool bit64) {
@ -38,3 +41,7 @@ void IntprCallback::OrrI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm
void IntprCallback::EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) {}
void IntprCallback::SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {}
void IntprCallback::UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) {}
void IntprCallback::GotoI64(uint64_t imm) {
debug_print ("Goto: 0x%016lx\n", imm + 4);
PC = imm;
}

View file

@ -110,6 +110,6 @@ printUsage:
#endif
}
nsemu->BootUp (parse.nonOption (0));
Nsemu ::destroy ();
Nsemu::destroy ();
return 0;
}

View file

@ -10,9 +10,13 @@ struct ARMv8State {
extern ARMv8State arm_state;
#define LR ARMv8 ::arm_state.gpr[30]
#define SP ARMv8 ::arm_state.gpr[31]
#define ZERO ARMv8 ::arm_state.gpr[31]
#define GPR_LR 30
#define GPR_SP 31
#define GPR_ZERO 31
#define LR ARMv8 ::arm_state.gpr[GPR_LR]
#define SP ARMv8 ::arm_state.gpr[GPR_SP]
#define ZERO ARMv8 ::arm_state.gpr[GPR_ZERO]
#define PC ARMv8 ::arm_state.pc
#define GPR(x) ARMv8 ::arm_state.gpr[x]

View file

@ -14,6 +14,8 @@ virtual void EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bo
/* Bitfield Signed/Unsigned Extract... with Immediate value */
virtual void SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0;
virtual void UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0;
/* Go to Immediate address */
virtual void GotoI64(uint64_t imm) = 0;
};

View file

@ -14,7 +14,8 @@ void EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64
/* Bitfield Signed/Unsigned Extract... with Immediate value */
void SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64);
void UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64);
/* Go to Immediate address */
void GotoI64(uint64_t imm);
};
/* Global Interpreter singleton class .*/

View file

@ -47,6 +47,10 @@ inline void bindump(uint8_t *ptr, size_t size) {
}
}
inline uint32_t byte_swap(uint32_t b) {
return ((b >> 24) & 0xff) | ((b << 8) & 0xff0000) | ((b >> 8) & 0xff00) | ((b << 24) & 0xff000000);
}
inline int32_t host_order32(const char *b) {
return ((b[3]) << 24) | ((b[2]) << 16) | ((b[1]) << 8) | (b[0]);
}
@ -56,6 +60,11 @@ static inline uint32_t extract32(uint32_t bitfield, int from, int len) {
return (bitfield >> from) & (~0U >> (32 - len));
}
static inline int32_t sextract32(uint64_t bitfield, int from, int len) {
assert (from >= 0 && len > 0 && from + len <= 32);
return ((int32_t) (bitfield << (32 - from - len))) >> (32 - len);
}
static inline int64_t sextract64(uint64_t bitfield, int from, int len) {
assert (from >= 0 && len > 0 && from + len <= 64);
return ((int64_t) (bitfield << (64 - from - len))) >> (64 - len);

View file

@ -8,7 +8,7 @@ PYTHON2 := python2
MEPHISTO := ctu
RUBY := ruby
libtransistor_TESTS := malloc bsd_ai_packing bsd sfdnsres
NSEMU_TESTS := simple_disas malloc bsd_ai_packing bsd sfdnsres
libtransistor_OBJECTS := build/lib/svc.o build/lib/ipc.o build/lib/tls.o build/lib/util.o build/lib/ipc/sm.o build/lib/ipc/bsd.o
@ -21,7 +21,7 @@ export CC_FOR_TARGET = clang -g -fPIC -ffreestanding -fexceptions -target aarch6
.SUFFIXES: # disable built-in rules
all: build/lib/libtransistor.nro.a build/lib/libtransistor.nso.a $(addprefix build/test/test_,$(addsuffix .nro,$(libtransistor_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso,$(libtransistor_TESTS))) $(addprefix build/test/test_,$(addsuffix .nro.so,$(libtransistor_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso.so,$(libtransistor_TESTS)))
all: build/lib/libtransistor.nro.a build/lib/libtransistor.nso.a $(addprefix build/test/test_,$(addsuffix .nro,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nro.so,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso.so,$(NSEMU_TESTS)))
run_tests: run_malloc_test run_bsd_ai_packing_test run_bsd_test run_sfdnsres_test
@ -38,6 +38,10 @@ build/test/%.o: test/%.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) -c -o $@ $<
build/test/%.o: test/%.S
mkdir -p $(@D)
$(AS) $(AS_FLAGS) $< -filetype=obj -o $@
build/lib/%.o: lib/%.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) -c -o $@ $<
@ -54,11 +58,11 @@ build/test/%.nso: build/test/%.nso.so
mkdir -p $(@D)
$(PYTHON2) ./tools/elf2nxo.py $< $@ nso
build/test/%.nro.so: build/test/%.o build/lib/libtransistor.nro.a newlib/aarch64-none-switch/newlib/libc.a
build/test/%.nro.so: build/test/%.o build/lib/libtransistor.nro.a newlib/aarch64-none-switch/newlib/libc.a
mkdir -p $(@D)
$(LD) $(LD_FLAGS) -o $@ $< --whole-archive build/lib/libtransistor.nro.a --no-whole-archive newlib/aarch64-none-switch/newlib/libc.a
build/test/%.nso.so: build/test/%.o build/lib/libtransistor.nso.a newlib/aarch64-none-switch/newlib/libc.a
build/test/%.nso.so: build/test/%.o build/lib/libtransistor.nso.a newlib/aarch64-none-switch/newlib/libc.a
mkdir -p $(@D)
$(LD) $(LD_FLAGS) -o $@ $< --whole-archive build/lib/libtransistor.nso.a --no-whole-archive newlib/aarch64-none-switch/newlib/libc.a

View file

@ -0,0 +1,4 @@
.section .text, "e"
.global main
main:
adr x5, 0x1000