From 5656f36cbe5083dda099c48827925cae874472d8 Mon Sep 17 00:00:00 2001 From: Recolic Keghart <root@recolic.net> Date: Wed, 25 Dec 2019 02:28:37 +0800 Subject: [PATCH] > Manual commit: [DO NOT BUILD] debugging U201614531 recolic Linux RECOLICPC 5.4.2-arch1-1 #1 SMP PREEMPT Thu, 05 Dec 2019 12:29:40 +0000 x86_64 GNU/Linux 02:28:37 up 2 days, 7:36, 1 user, load average: 1.26, 1.14, 0.98 891cd7f6081506f251fda067a38894cb71507ef --- nemu/include/common.h | 2 ++ nemu/include/cpu/decode.h | 4 ++++ nemu/include/cpu/rtl.h | 12 ++++++++++-- nemu/include/macro.h | 6 ++++++ nemu/src/cpu/decode/decode.cc | 2 +- nemu/src/cpu/exec/all-instr.h | 7 +++++++ nemu/src/cpu/exec/control.cc | 32 ++++++++++++++++++++++++++++++-- nemu/src/cpu/exec/data-mov.cc | 20 ++++++++++++++++++-- nemu/src/cpu/exec/exec.cc | 6 +++--- nemu/src/memory/memory.cc | 2 ++ 10 files changed, 83 insertions(+), 10 deletions(-) diff --git a/nemu/include/common.h b/nemu/include/common.h index b6e40c4..d765817 100644 --- a/nemu/include/common.h +++ b/nemu/include/common.h @@ -37,4 +37,6 @@ inline std::string num2hex(uint32_t n) { return ss.str(); } +#include <rlib/stdio.hpp> + #endif diff --git a/nemu/include/cpu/decode.h b/nemu/include/cpu/decode.h index e8c6191..df6a347 100644 --- a/nemu/include/cpu/decode.h +++ b/nemu/include/cpu/decode.h @@ -22,6 +22,10 @@ typedef struct { char str[OP_STR_SIZE]; } Operand; +inline std::ostream & operator<< (std::ostream &os, const Operand &operand) { + return os << "Operand{type=" << operand.type << ",width=" << operand.width << ",union{reg/addr/imm/simm}=" << std::hex << operand.reg << ",val=" << operand.val << std::dec << ",str=" << operand.str << "}"; +} + typedef struct { uint32_t opcode; vaddr_t seq_eip; // sequential eip diff --git a/nemu/include/cpu/rtl.h b/nemu/include/cpu/rtl.h index dd2b41a..1352785 100644 --- a/nemu/include/cpu/rtl.h +++ b/nemu/include/cpu/rtl.h @@ -21,6 +21,10 @@ static inline void interpret_rtl_mv(rtlreg_t* dest, const rtlreg_t *src1) { *dest = *src1; } +// TODO: Optimize: change rtlreg_t* to rtlreg_t&, which barries the compiler optimization. + +// TODO: Optimize: DO NOT use `at` register in `addi`/subi... instructions. It's unnecessarily slow. + #define make_rtl_arith_logic(name) \ static inline void concat(interpret_rtl_, name) (rtlreg_t* dest, const rtlreg_t* src1, const rtlreg_t* src2) { \ *dest = concat(c_, name) (*src1, *src2); \ @@ -158,16 +162,20 @@ static inline void rtl_sext(rtlreg_t* dest, const rtlreg_t* src1, int width) { TODO(); } +template <int OperandBytes> static inline void rtl_push(const rtlreg_t* src1) { // esp <- esp - 4 // M[esp] <- src1 - TODO(); + rtl_subi(&cpu.esp, &cpu.esp, OperandBytes); + interpret_rtl_sm(&cpu.esp, src1, OperandBytes); } +template <int OperandBytes> static inline void rtl_pop(rtlreg_t* dest) { // dest <- M[esp] // esp <- esp + 4 - TODO(); + interpret_rtl_lm(dest, &cpu.esp, OperandBytes); + rtl_addi(&cpu.esp, &cpu.esp, OperandBytes); } static inline void rtl_setrelopi(uint32_t relop, rtlreg_t *dest, diff --git a/nemu/include/macro.h b/nemu/include/macro.h index a08559b..68b9399 100644 --- a/nemu/include/macro.h +++ b/nemu/include/macro.h @@ -9,4 +9,10 @@ #define concat4(x, y, z, w) concat3(concat(x, y), z, w) #define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w) +#ifdef DEBUG +#define RLIB_MACRO_DEBUG_ASSERT(expr) assert(expr) +#else +#define RLIB_MACRO_DEBUG_ASSERT(expr) +#endif + #endif diff --git a/nemu/src/cpu/decode/decode.cc b/nemu/src/cpu/decode/decode.cc index 036c330..ecd0665 100644 --- a/nemu/src/cpu/decode/decode.cc +++ b/nemu/src/cpu/decode/decode.cc @@ -42,7 +42,7 @@ static inline make_DopHelper(SI) { * op->simm = ??? */ - TODO(); + op->simm = instr_fetch(eip, op->width); rtl_li(&op->val, op->simm); diff --git a/nemu/src/cpu/exec/all-instr.h b/nemu/src/cpu/exec/all-instr.h index 613d8f2..d63f2ec 100644 --- a/nemu/src/cpu/exec/all-instr.h +++ b/nemu/src/cpu/exec/all-instr.h @@ -6,3 +6,10 @@ make_EHelper(operand_size); make_EHelper(inv); make_EHelper(nemu_trap); + +make_EHelper(ret); +make_EHelper(call); +make_EHelper(push); +make_EHelper(pop); +//make_EHelper(); +//make_EHelper(); diff --git a/nemu/src/cpu/exec/control.cc b/nemu/src/cpu/exec/control.cc index 676a2bd..f58ec10 100644 --- a/nemu/src/cpu/exec/control.cc +++ b/nemu/src/cpu/exec/control.cc @@ -26,13 +26,41 @@ make_EHelper(jmp_rm) { make_EHelper(call) { // the target address is calculated at the decode stage - TODO(); + const bool near = true; + if(near) { + if(decoding.is_operand_size_16) { + throw std::runtime_error("call operand size 16 not implemented."); + } + else { + // operand size 32b + rlib::println("debug: call touched.", std::hex); + rtl_push<4>(&cpu.eip); + rlib::println("debug: idsrc.val=", id_src->val, "eip from=", cpu.eip); + rtl_add(&cpu.eip, &cpu.eip, &id_src->val); + rlib::println("debug: idsrc.val=", id_src->val, "eip to=", cpu.eip); + } + } + // TODO: support far call + // TODO(); print_asm("call %x", decoding.jmp_eip); } make_EHelper(ret) { - TODO(); + const bool near = true; + if(near) { + if(decoding.is_operand_size_16) { + throw std::runtime_error("call operand size 16 not implemented."); + } + else { + // operand size 32b + rtl_pop<4>(&cpu.eip); + } + rlib::println("debug: decoding.src=", decoding.src); + } + + // TODO: support far ret + // TODO(); print_asm("ret"); } diff --git a/nemu/src/cpu/exec/data-mov.cc b/nemu/src/cpu/exec/data-mov.cc index 49ba2f1..9bf9883 100644 --- a/nemu/src/cpu/exec/data-mov.cc +++ b/nemu/src/cpu/exec/data-mov.cc @@ -6,13 +6,29 @@ make_EHelper(mov) { } make_EHelper(push) { - TODO(); + static_assert(sizeof(paddr_t) * 8 == 32); + if(decoding.is_operand_size_16) { + // 16b push + rtl_push<2>(&id_src->val); + } + else { + // 32b push + rtl_push<4>(&id_src->val); + } print_asm_template1(push); } make_EHelper(pop) { - TODO(); + static_assert(sizeof(paddr_t) * 8 == 32); + if(decoding.is_operand_size_16) { + // 16b + rtl_pop<2>(&id_src->val); + } + else { + // 32b + rtl_pop<4>(&id_src->val); + } print_asm_template1(pop); } diff --git a/nemu/src/cpu/exec/exec.cc b/nemu/src/cpu/exec/exec.cc index 373d4c3..f05726b 100644 --- a/nemu/src/cpu/exec/exec.cc +++ b/nemu/src/cpu/exec/exec.cc @@ -4,7 +4,7 @@ typedef struct { DHelper decode; EHelper execute; - int width; + int width; // ByteWidth. If width is 0, using its default value: OperandSize (2Byte or 4Byte) } opcode_entry; #define IDEXW(id, ex, w) {make_DHelper_funcname(id), make_EHelper_funcname(ex), w} @@ -120,7 +120,7 @@ opcode_entry opcode_table [512] = { /* 0xb4 */ IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), /* 0xb8 */ IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), /* 0xbc */ IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), IDEX(mov_I2r, mov), - /* 0xc0 */ IDEXW(gp2_Ib2E, gp2, 1), IDEX(gp2_Ib2E, gp2), EMPTY, EMPTY, + /* 0xc0 */ IDEXW(gp2_Ib2E, gp2, 1), IDEX(gp2_Ib2E, gp2), IDEX(I, ret), EX(ret), /* 0xc4 */ EMPTY, EMPTY, IDEXW(mov_I2E, mov, 1), IDEX(mov_I2E, mov), /* 0xc8 */ EMPTY, EMPTY, EMPTY, EMPTY, /* 0xcc */ EMPTY, EMPTY, EMPTY, EMPTY, @@ -130,7 +130,7 @@ opcode_entry opcode_table [512] = { /* 0xdc */ EMPTY, EMPTY, EMPTY, EMPTY, /* 0xe0 */ EMPTY, EMPTY, EMPTY, EMPTY, /* 0xe4 */ EMPTY, EMPTY, EMPTY, EMPTY, - /* 0xe8 */ EMPTY, EMPTY, EMPTY, EMPTY, + /* 0xe8 */ IDEX(J, call), EMPTY, EMPTY, EMPTY, /* 0xec */ EMPTY, EMPTY, EMPTY, EMPTY, /* 0xf0 */ EMPTY, EMPTY, EMPTY, EMPTY, /* 0xf4 */ EMPTY, EMPTY, IDEXW(E, gp3, 1), IDEX(E, gp3), diff --git a/nemu/src/memory/memory.cc b/nemu/src/memory/memory.cc index 2637056..0206211 100644 --- a/nemu/src/memory/memory.cc +++ b/nemu/src/memory/memory.cc @@ -19,10 +19,12 @@ void paddr_write(paddr_t addr, uint32_t data, int len) { memcpy(guest_to_host(addr), &data, len); } +// len is Bytes. uint32_t vaddr_read(vaddr_t addr, int len) { return paddr_read(addr, len); } +// len is Bytes. void vaddr_write(vaddr_t addr, uint32_t data, int len) { paddr_write(addr, data, len); } -- GitLab