diff --git a/ARMv8/ARMv8.cpp b/ARMv8/ARMv8.cpp index 32ea621..4192bd2 100644 --- a/ARMv8/ARMv8.cpp +++ b/ARMv8/ARMv8.cpp @@ -17,7 +17,7 @@ void RunLoop() { } void Dump() { - for (int r = 0; r < 32; r++) { + for (int r = 0; r < GPR_DUMMY; r++) { if (!X(r)) continue; if (r == GPR_LR) diff --git a/ARMv8/Disassembler.cpp b/ARMv8/Disassembler.cpp index abfda30..137439d 100644 --- a/ARMv8/Disassembler.cpp +++ b/ARMv8/Disassembler.cpp @@ -780,7 +780,7 @@ static void DisasLdstRegRoffset(uint32_t insn, DisasCallback *cb, is_extended = (size < 3) && extract32(opc, 0, 1); } bool sf = DisasLdstCompute64bit (size, is_signed, opc); - cb->ExtendReg (rm, rm, opt, sf); + cb->ExtendReg (rm, rm, opt, sf); //FIXME: When rm == GPR_ZERO, it should be handled as GPR_SP cb->ShiftReg (rm, rm, ShiftType_LSL, shift ? size : 0, sf); if (is_store) { cb->StoreReg (rt, rn, rm, size, is_extended, false, sf); diff --git a/ARMv8/Interpreter.cpp b/ARMv8/Interpreter.cpp index 07d7079..4f947a1 100644 --- a/ARMv8/Interpreter.cpp +++ b/ARMv8/Interpreter.cpp @@ -6,6 +6,7 @@ IntprCallback *Interpreter::disas_cb = nullptr; int Interpreter::SingleStep() { uint32_t inst = byte_swap32_uint (ARMv8::ReadInst (PC)); + X(GPR_ZERO) = 0; //Reset Zero register debug_print ("Run Code: 0x%lx: 0x%08lx\n", PC, inst); Disassembler::DisasA64 (inst, disas_cb); PC += sizeof(uint32_t); @@ -39,6 +40,11 @@ enum OpType{ const char *OpStrs[] = { "<<", ">>", ">>", "ROR", "+", "-", "&", "|", "^" }; +/* See: C6.1.3 Use of the stack pointer */ +static inline unsigned int HandleAsSP(unsigned r_idx) { + return r_idx == GPR_ZERO ? GPR_SP : r_idx; +} + static bool CondHold(unsigned int cond) { cond >>= 1; if (cond == 0x0) @@ -193,6 +199,10 @@ void IntprCallback::CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned /* Add/Sub with Immediate value */ void IntprCallback::AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) { char regc = bit64? 'X': 'W'; + if (!setflags) { + rd_idx = HandleAsSP (rd_idx); + rn_idx = HandleAsSP (rn_idx); + } debug_print ("Add: %c[%u] = %c[%u] + 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no"); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), imm, setflags, bit64, AL_TYPE_ADD); @@ -201,6 +211,10 @@ void IntprCallback::AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t im } void IntprCallback::SubI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) { char regc = bit64? 'X': 'W'; + if (!setflags) { + rd_idx = HandleAsSP (rd_idx); + rn_idx = HandleAsSP (rn_idx); + } debug_print ("Sub: %c[%u] = %c[%u] - 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, imm, setflags? "update": "no"); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), imm, setflags, bit64, AL_TYPE_SUB); @@ -268,6 +282,7 @@ void IntprCallback::SubcReg(unsigned int rd_idx, unsigned int rn_idx, unsigned i /* AND/OR/EOR... with Immediate value */ void IntprCallback::AndI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool setflags, bool bit64) { char regc = bit64? 'X': 'W'; + rd_idx = HandleAsSP (rd_idx); debug_print ("And: %c[%u] = %c[%u] & 0x%lx (flag: %s)\n", regc, rd_idx, regc, rn_idx, wmask, setflags? "update": "no"); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), wmask, setflags, bit64, AL_TYPE_AND); @@ -277,6 +292,7 @@ void IntprCallback::AndI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm } void IntprCallback::OrrI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) { char regc = bit64? 'X': 'W'; + rd_idx = HandleAsSP (rd_idx); debug_print ("Or: %c[%u] = %c[%u] | 0x%lx \n", regc, rd_idx, regc, rn_idx, wmask); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), wmask, false, bit64, AL_TYPE_OR); @@ -285,6 +301,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) { char regc = bit64? 'X': 'W'; + rd_idx = HandleAsSP (rd_idx); debug_print ("Eor: %c[%u] = %c[%u] ^ 0x%lx \n", regc, rd_idx, regc, rn_idx, wmask); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), wmask, false, bit64, AL_TYPE_EOR); @@ -293,6 +310,7 @@ void IntprCallback::EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wm } void IntprCallback::ShiftI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int shift_type, unsigned int shift_amount, bool bit64) { char regc = bit64? 'X': 'W'; + rd_idx = HandleAsSP (rd_idx); debug_print ("Shift: %c[%u] = %c[%u] %s 0x%lx \n", regc, rd_idx, regc, rn_idx, OpStrs[shift_type], shift_amount); if (bit64) ArithmeticLogic (rd_idx, X(rn_idx), shift_amount, false, bit64, (OpType)shift_type); @@ -381,7 +399,8 @@ void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned bool extend, bool post, bool bit64) { char regc = bit64? 'X': 'W'; char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X'); - debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx); + base_idx = HandleAsSP (base_idx); + debug_print ("Load(%d): %c[%u] <= [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx); uint64_t addr; if (bit64) { if (post) @@ -400,6 +419,7 @@ void IntprCallback::LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned void IntprCallback::LoadRegI64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post) { char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X'); + base_idx = HandleAsSP (base_idx); debug_print ("Load(%d): %c[%u] <= [X[%u], 0x%lx]\n", size, regdc, rd_idx, base_idx, offset); uint64_t addr; if (post) @@ -412,6 +432,7 @@ void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigne bool extend, bool post, bool bit64) { char regc = bit64? 'X': 'W'; char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X'); + base_idx = HandleAsSP (base_idx); debug_print ("Store(%d): %c[%u] => [%c[%u], %c[%u]]\n", size, regdc, rd_idx, regc, base_idx, regc, rm_idx); uint64_t addr; if (bit64) { @@ -431,6 +452,7 @@ void IntprCallback::StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigne void IntprCallback::StoreRegI64(unsigned int rd_idx, unsigned int base_idx, uint64_t offset, int size, bool extend, bool post) { char regdc = size >= 4 ? 'Q' : (size < 3 ? 'W' : 'X'); + base_idx = HandleAsSP (base_idx); debug_print ("Store(%d): %c[%u] => [X[%u], 0x%lx]\n", size, regdc, rd_idx, base_idx, offset); uint64_t addr; if (post) @@ -515,15 +537,9 @@ void IntprCallback::CntLeadSign(unsigned int rd_idx, unsigned int rn_idx, bool b void IntprCallback::CondCmpI64(unsigned int rn_idx, unsigned int imm, unsigned int nzcv, unsigned int cond, unsigned int op, bool bit64) { if (CondHold (cond)) { if (op) { - if (bit64) - ArithmeticLogic (GPR_DUMMY, X(rn_idx), imm, true, bit64, AL_TYPE_SUB); - else - ArithmeticLogic (GPR_DUMMY, W(rn_idx), imm, true, bit64, AL_TYPE_SUB); + SubI64 (GPR_ZERO, rn_idx, imm, true, bit64); } else { - if (bit64) - ArithmeticLogic (GPR_DUMMY, X(rn_idx), imm, true, bit64, AL_TYPE_ADD); - else - ArithmeticLogic (GPR_DUMMY, W(rn_idx), imm, true, bit64, AL_TYPE_ADD); + AddI64 (GPR_ZERO, rn_idx, imm, true, bit64); } } else { /* Set new nzcv */ @@ -534,15 +550,9 @@ void IntprCallback::CondCmpI64(unsigned int rn_idx, unsigned int imm, unsigned i void IntprCallback::CondCmpReg(unsigned int rn_idx, unsigned int rm_idx, unsigned int nzcv, unsigned int cond, unsigned int op, bool bit64) { if (CondHold (cond)) { if (op) { - if (bit64) - ArithmeticLogic (GPR_DUMMY, X(rn_idx), X(rm_idx), true, bit64, AL_TYPE_SUB); - else - ArithmeticLogic (GPR_DUMMY, W(rn_idx), W(rm_idx), true, bit64, AL_TYPE_SUB); + SubReg (GPR_ZERO, rn_idx, rm_idx, true, bit64); } else { - if (bit64) - ArithmeticLogic (GPR_DUMMY, X(rn_idx), X(rm_idx), true, bit64, AL_TYPE_ADD); - else - ArithmeticLogic (GPR_DUMMY, W(rn_idx), W(rm_idx), true, bit64, AL_TYPE_ADD); + AddReg (GPR_ZERO, rn_idx, rm_idx, true, bit64); } } else { /* Set new nzcv */ @@ -589,5 +599,6 @@ void IntprCallback::SetPCReg(unsigned int rt_idx) { /* Super Visor Call */ void IntprCallback::SVC(unsigned int svc_num) { - debug_print ("SVC: %u\n", svc_num); + //debug_print ("SVC: %u\n", svc_num); + ns_print ("SVC: %u\n", svc_num); } diff --git a/include/ARMv8/ARMv8.hpp b/include/ARMv8/ARMv8.hpp index 01c4069..bf64c8e 100644 --- a/include/ARMv8/ARMv8.hpp +++ b/include/ARMv8/ARMv8.hpp @@ -21,7 +21,7 @@ struct ARMv8State { * x0 - x31 (x30 is usually "link regsiter" and x31 is "stack pointer" or "zero register" ) * NOTE: In nsemu, 'PC' register is respresented as x32 internally. */ - reg_t gpr[34]; + reg_t gpr[35]; /* v0 - v31 (128 bit vector register, sometime treated as set of smaller size regs) */ vreg_t vreg[32]; @@ -32,10 +32,13 @@ struct ARMv8State { extern ARMv8State arm_state; #define GPR_LR 30 -#define GPR_SP 31 -#define GPR_ZERO 31 -#define PC_IDX 32 // XXX: bit tricky -#define GPR_DUMMY 33 +/* Zero register share the same encoding as SP register. + * In emulator, it's not necessary to follow it. + */ +#define GPR_ZERO 31 +#define GPR_SP 32 +#define PC_IDX 33 // XXX: bit tricky +#define GPR_DUMMY PC_IDX #define GPR(r) ARMv8::arm_state.gpr[r] #define VREG(r) ARMv8::arm_state.vreg[r] diff --git a/include/Util.hpp b/include/Util.hpp index 0b61123..cc366e0 100644 --- a/include/Util.hpp +++ b/include/Util.hpp @@ -13,7 +13,8 @@ enum RunLevel { RUN_LEVEL_DEBUG, }; -static RunLevel curlevel = RUN_LEVEL_DEBUG; +//static RunLevel curlevel = RUN_LEVEL_DEBUG; +static RunLevel curlevel = RUN_LEVEL_RELEASE; static void util_print(RunLevel level, const char *format, ...) { if (curlevel >= level) { diff --git a/test/test/test_bsd.c b/test/test/test_bsd.c index fb5e11a..25c6dfb 100644 --- a/test/test/test_bsd.c +++ b/test/test/test_bsd.c @@ -4,13 +4,12 @@ int main() { svcSleepThread(100000000); - result_t r; if((r = sm_init()) != RESULT_OK) { dbg_printf("failed to init sm: 0x%x", r); return 1; } - +svcSleepThread(100000000); if((r = bsd_init()) != RESULT_OK) { dbg_printf("failed to init bsd: 0x%x, %d", r, bsd_errno); goto err_only_sm; diff --git a/test/test/test_simple_disas.S b/test/test/test_simple_disas.S index 7892521..a07e8fb 100644 --- a/test/test/test_simple_disas.S +++ b/test/test/test_simple_disas.S @@ -8,4 +8,12 @@ main: sub x3, x1, #0x431 // x3 = 0xbabe movk x4, 0xcafe, lsl 16 // x4 = 0xcafe0000 orr x3, x3, x4 // x3 = 0xcafebabe + cmp w9, 0 + subs wzr, w9, #0 + subs w31, w9, #0 + cmp x9, 0 + subs xzr, x9, #0 + subs x31, x9, #0 + //subs sp, x9, #0 assembler error! + sub sp, x9, #0 b main