纯php网站,宿迁经济技术开发区,企业门户模板,wordpress网站网页加密继上一篇文章简单代码分析后#xff0c;本文主要调研如何实现对指令的解析运行。
调试配置
使用 gdb 工具跟踪调试运行。 c_cpp_properties.json 项目配置#xff1a;
{name: QtRvSim,includePath: [${workspaceFolder}/**本文主要调研如何实现对指令的解析运行。
调试配置
使用 gdb 工具跟踪调试运行。 c_cpp_properties.json 项目配置
{name: QtRvSim,includePath: [${workspaceFolder}/**],defines: [],compilerPath: /usr/bin/clang,cStandard: c11,cppStandard: c17,intelliSenseMode: gcc-x64,configurationProvider: ms-vscode.cmake-tools}launch.json
{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息请访问: https://go.microsoft.com/fwlink/?linkid830387version: 0.2.0,configurations: [{name: (gdb) Launch,type: cppdbg,request: launch,// program: ${fileDirname}/${fileBasenameNoExtension},program: ${command:cmake.launchTargetPath},args: [/home/jingqing3948/Develop/qtrvsim-test/sum2vars-riscv],stopAtEntry: false,cwd: ${workspaceFolder},environment: [{name: PATH,value:${env:PATH):${command:cmake.getLaunchTargetDirectory]}],externalConsole: true,MIMode: gdb,setupCommands: [{description: Enable pretty-printing for gdb,text: -enable-pretty-printing,ignoreFailures: true}],//preLaunchTask: Tutorial, miDebuggerPath: /usr/bin/gdb}]
}程序解析流程
由于我的毕设任务主要是实现 F 扩展因此我集中精力于对于指令集的解码、执行、写回过程对于取指过程不同扩展区别不大暂不过多关注。
程序执行流程跟踪分析
//main.cppint main(int argc, char *argv[]) {//省略一系列预配置在 machine.play() 函数中执行程序machine.play();}void Machine::play() {//set status//start execute each instructionsstep_internal(true);
}void Machine::step_internal(bool skip_break) {//set statustry {QTime start_time QTime::currentTime();do {//execute one step cr-step(skip_break);} while (time_chunk ! 0 stat ST_BUSY !skip_break start_time.msecsTo(QTime::currentTime()) (int)time_chunk);} catch (SimulatorException e) {//set trapped status}if (regs-read_pc() program_end) {//set exit status} else {//set status as the previous status}
}//core.cpp//step(): wrapper of do_step() function
void Core::step(bool skip_break) {//pcstate.cycle_count;do_step(skip_break);emit step_done(state);
}void CoreSingle::do_step(bool skip_break) {Pipeline p state.pipeline;p.fetch fetch(pc_if, skip_break);p.decode decode(p.fetch.final);p.execute execute(p.decode.final);p.memory memory(p.execute.final);p.writeback writeback(p.memory.final);regs-write_pc(mem_wb.computed_next_inst_addr);if (mem_wb.excause ! EXCAUSE_NONE) {handle_exception(mem_wb.excause, mem_wb.inst, mem_wb.inst_addr, regs-read_pc(), prev_inst_addr,mem_wb.mem_addr);return;}prev_inst_addr mem_wb.inst_addr;
}
由此可见对于F扩展的实现除去新硬件的实现主要需要补充的就是 Pipeline.decode() , Pipeline.execute() , Pipeline.memory() , Pipeline.writeback() 以上内容。
首先我需要先实现 F 指令集的 decode。单条指令解码由
//core.cppDecodeState Core::decode(const FetchInterstage dt) {InstructionFlags flags;bool w_operation this-xlen ! Xlen::_64;AluCombinedOp alu_op {};AccessControl mem_ctl;ExceptionCause excause dt.excause;// decode后把结果存在flags alu_op mem_ctl结构体里也就是说指令解码具体实现由 instructions.cpp 的 flags_alu_op_mem_ctl 函数实现dt.inst.flags_alu_op_mem_ctl(flags, alu_op, mem_ctl);//flags结构体通过位域操作识别rs rd op等信息并返回
}//instructions.cppvoid Instruction::flags_alu_op_mem_ctl(InstructionFlags flags,AluCombinedOp alu_op,AccessControl mem_ctl) const {//通过 InstructionMapFind 函数查找指令表const struct InstructionMap im InstructionMapFind(dt);flags (enum InstructionFlags)im.flags;alu_op im.alu;mem_ctl im.mem_ctl;
}static inline const struct InstructionMap InstructionMapFind(uint32_t code) {const struct InstructionMap *im C_inst_map[instruction_map_opcode_field.decode(code)];//递归解码和指令集在程序中的存储方式有关while (im-subclass ! nullptr) {im im-subclass[im-subfield.decode(code)];}if ((code ^ im-code) im-mask) {return C_inst_unknown;}return *im;
}也就是说对于一条指令首先需要根据 instruction_map_opcode_field.decode(code) 判断其操作码类型然后用对应操作码的解码表 C_inst_map 元素进行解码。并且解码是递归进行的因为解码表的存储方式是递归存储先大类后小类比如 I_inst_map 下的 load 指令全部属于 LOAD_map 包括 lb lh lw 等。
C_inst_map 解码表目前只包含了 i 扩展的指令集对于 F 扩展实现从 C_inst_map 开始参照 I 扩展逐层实现。
static const struct InstructionMap C_inst_map[] {IM_UNKNOWN,IM_UNKNOWN,IM_UNKNOWN,{i, IT_UNKNOWN, NOALU, NOMEM, I_inst_map, {}, 0x3, 0x3, { .subfield {5, 2} }, nullptr},
};static const struct InstructionMap I_inst_map[] {{load, IT_I, NOALU, NOMEM, LOAD_map, {}, 0x03, 0x7f, { .subfield {3, 12} }, nullptr}, // LOADIM_UNKNOWN, // LOAD-FPIM_UNKNOWN, // custom-0{misc-mem, IT_I, NOALU, NOMEM, MISC_MEM_map, {}, 0x0f, 0x7f, { .subfield {3, 12} }, nullptr}, // MISC-MEM{op-imm, IT_I, NOALU, NOMEM, OP_IMM_map, {}, 0x13, 0x7f, { .subfield {3, 12} }, nullptr}, // OP-IMM{auipc, IT_U, { .alu_opAluOp::ADD }, NOMEM, nullptr, {d, u}, 0x17, 0x7f, { .flags IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_PC_TO_ALU }, nullptr}, // AUIPC{op-imm-32, IT_I, NOALU, NOMEM, OP_IMM_32_map, {}, 0x1b, 0x7f, { .subfield {3, 12} }, nullptr}, // OP-IMM-32 IM_UNKNOWN, // OP-IMM-32IM_UNKNOWN, // 48b{store, IT_I, NOALU, NOMEM, STORE_map, {}, 0x23, 0x7f, { .subfield {3, 12} }, nullptr}, // STOREIM_UNKNOWN, // STORE-FPIM_UNKNOWN, // custom-1{amo, IT_R, NOALU, NOMEM, AMO_map, {}, 0x2f, 0x7f, { .subfield {3, 12} }, nullptr}, // OP-32{op, IT_R, NOALU, NOMEM, OP_map, {}, 0x33, 0x7f, { .subfield {1, 25} }, nullptr}, // OP{lui, IT_U, { .alu_opAluOp::ADD }, NOMEM, nullptr, {d, u}, 0x37, 0x7f, { .flags IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE }, nullptr}, // LUI{op-32, IT_R, NOALU, NOMEM, OP_32_map, {}, 0x3b, 0x7f, { .subfield {1, 25} }, nullptr}, // OP-32IM_UNKNOWN, // 64bIM_UNKNOWN, // MADDIM_UNKNOWN, // MSUBIM_UNKNOWN, // NMSUBIM_UNKNOWN, // NMADDIM_UNKNOWN, // OP-FPIM_UNKNOWN, // reservedIM_UNKNOWN, // custom-2/rv128IM_UNKNOWN, // 48b{branch, IT_B, NOALU, NOMEM, BRANCH_map, {}, 0x63, 0x7f, { .subfield {3, 12} }, nullptr}, // BRANCH{jalr, IT_I, { .alu_opAluOp::ADD }, NOMEM, nullptr, {d, o(s)}, 0x67, 0x7f, { .flags
IMF_SUPPORTED | IMF_REGWRITE | IMF_BRANCH_JALR | IMF_ALUSRC | IMF_ALU_REQ_RS }, inst_aliases_jalr}, // JALRIM_UNKNOWN, // reserved{jal, IT_J, { .alu_opAluOp::ADD }, NOMEM, nullptr, {d, a}, 0x6f, 0x7f, { .flags
IMF_SUPPORTED |
IMF_REGWRITE | IMF_JUMP | IMF_PC_TO_ALU | IMF_ALUSRC }, inst_aliases_jal}, // JAL{system, IT_I, NOALU, NOMEM, SYSTEM_map, {}, 0x73, 0x7f, { .subfield {3, 12} }, nullptr}, // SYSTEMIM_UNKNOWN, // reservedIM_UNKNOWN, // custom-3/rv128IM_UNKNOWN, // 80b
};下一步目标从最基础的 F load, F store 指令开始实现。先达成能成功识别指令的目标。