def gen_kernel_sections(self, hart): if(rcs.SATP_MODE != "BARE"): self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart)) self.instr_stream.append(".text") self.gen_all_trap_handler(hart) for mode in rcs.supported_privileged_mode: self.gen_interrupt_handler_section(mode, hart) self.instr_stream.append(pkg_ins.get_label("kernel_instr_end: nop", hart)) self.gen_kernel_stack_section(hart)
def trap_vector_init(self, hart): instr = [] for items in rcs.supported_privileged_mode: if(items == "MACHINE_MODE"): trap_vec_reg = privileged_reg_t.MTVEC elif(items == "SUPERVISOR_MODE"): trap_vec_reg = privileged_reg_t.STVEC elif(items == "USER_MODE"): trap_vec_reg = privileged_reg_t.UTVEC else: logging.critical( "[riscv_asm_program_gen] Unsupported privileged_mode {}".format(items)) if(items == "USER_MODE" and not (rcs.support_umode_trap)): continue if(items < cfg.init_privileged_mode.name): continue tvec_name = trap_vec_reg.name tvec_name = tvec_name.lower() instr.append("la x{}, {}{}_handler".format( cfg.gpr[0].value, pkg_ins.hart_prefix(hart), tvec_name)) if(rcs.SATP_MODE != "BARE" and items != "MACHINE_MODE"): instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0].value, cfg.gpr[0].value, rcs.XLEN - 20) + "srli x{}, x{}, {}".format(cfg.gpr[0].value, cfg.gpr[0].value, rcs.XLEN - 20)) instr.append("ori x{}, x{}, {}".format( cfg.gpr[0].value, cfg.gpr[0].value, cfg.mtvec_mode.value)) instr.append("csrw {}, x{} # {}".format( hex(trap_vec_reg.value), cfg.gpr[0].value, trap_vec_reg.name)) self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
def trap_vector_init(self, hart): instr = [] for mode in rcs.supported_privileged_mode: if mode == privileged_mode_t.MACHINE_MODE: trap_vec_reg = privileged_reg_t.MTVEC elif mode == privileged_mode_t.SUPERVISOR_MODE: trap_vec_reg = privileged_reg_t.STVEC elif mode == privileged_mode_t.USER_MODE: trap_vec_reg = privileged_reg_t.UTVEC else: logging.critical("Unsupported privileged_mode {}".format(mode.name)) sys.exit(1) if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)): continue if mode < cfg.init_privileged_mode: continue tvec_name = trap_vec_reg.name tvec_name = tvec_name.lower() instr.append("la x{}, {}{}_handler".format( cfg.gpr[0], pkg_ins.hart_prefix(hart), tvec_name)) if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE): instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20) + "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20)) instr.append("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode)) instr.append("csrw {}, x{} # {}".format( hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name)) self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc, scratch, status, ie, ip): is_interrupt = 1 tvec_name = "" instr = [] if (cfg.mtvec_mode == mtvec_mode_t.VECTORED): self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr) else: # Push user mode GPR to kernel stack before executing exception handling, # this is to avoid exception handling routine modify user program state # unexpectedly # TODO pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) # The trap handler will occupy one 4KB page, it will be allocated one entry in # the page table with a specific privileged mode. if (rcs.SATP_MODE != "BARE"): self.instr_stream.append(".align 12") else: self.instr_stream.append(".align {}".format(cfg.tvec_alignment)) tvec_name = tvec.name self.gen_section( pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr)
def pre_enter_privileged_mode(self, hart): instr = [] string = [] string.append("la x{}, {}kernel_stack_end".format(cfg.tp.value, pkg_ins.hart_prefix(hart))) self.gen_section(pkg_ins.get_label("kernel_sp", hart), string) if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE): self.gen_delegation(hart) self.trap_vector_init(hart) self.setup_pmp(hart) if(cfg.virtual_addr_translation_on): self.page_table_list.process_page_table(instr) self.gen_section(pkg_ins.get_label("process_pt", hart), instr) self.setup_epc(hart) self.gen_privileged_mode_switch_routine(hart)
def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc, scratch, status, ie, ip): is_interrupt = 1 tvec_name = "" instr = [] if cfg.mtvec_mode == mtvec_mode_t.VECTORED: self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr) else: # Push user mode GPR to kernel stack before executing exception handling, # this is to avoid exception handling routine modify user program state # unexpectedly # TODO pkg_ins.push_gpr_to_kernel_stack( status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) # Checking xStatus can be optional if ISS (like spike) has different implementation of # certain fields compared with the RTL processor. if cfg.check_xstatus: instr.append("csrr x{}, {} # {}".format( cfg.gpr[0], hex(status), status.name)) instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(cause), cause.name) + "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 1) + "{}bne x{}, x0, {}{}mode_intr_handler".format(pkg_ins.indent, cfg.gpr[0], pkg_ins.hart_prefix(hart), mode)) # The trap handler will occupy one 4KB page, it will be allocated one entry in # the page table with a specific privileged mode. if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align {}".format(cfg.tvec_alignment)) tvec_name = tvec.name self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr) # TODO Exception handler instr = [] if cfg.mtvec_mode == mtvec_mode_t.VECTORED: pkg_ins.push_gpr_to_kernel_stack( status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
def gen_ecall_handler(self, hart): string = "" string = pkg_ins.format_string(pkg_ins.get_label( "ecall_handler:", hart), pkg_ins.LABEL_STR_LEN) self.instr_stream.append(string) self.dump_perf_stats() self.gen_register_dump() string = pkg_ins.format_string(" ", pkg_ins.LABEL_STR_LEN) string = string + "j write_tohost" self.instr_stream.append(string)
def setup_epc(self, hart): instr = [] instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart))) # if(cfg.virtual_addr_translation_on): # instr.append("slli x{}, x{}") # TODO mode_name = cfg.init_privileged_mode instr.append("csrw mepc, x{}".format(cfg.gpr[0].value)) if(not rcs.support_pmp): # TODO instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.name.lower())) self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
def gen_kernel_stack_section(self, hart): hart_prefix_string = pkg_ins.hart_prefix(hart) if(cfg.use_push_data_section): self.instr_stream.append( ".pushsection .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string)) else: self.instr_stream.append( ".section .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string)) if(rcs.SATP_MODE != "BARE"): self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart)) self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1)) self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) self.instr_stream.append(".endr") self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart)) self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) if (cfg.use_push_data_section): self.instr_stream.push_back(".popsection;")
def setup_epc(self, hart): instr = [] instr.append("la x{}, {}init".format(cfg.gpr[0], pkg_ins.hart_prefix(hart))) if cfg.virtual_addr_translation_on: # For supervisor and user mode, use virtual address instead of physical address. # Virtual address starts from address 0x0, here only the lower 12 bits are kept # as virtual address offset. instr.append("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12) + "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12)) mode_name = cfg.init_privileged_mode.name instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0])) if not rcs.support_pmp: instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower())) self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
def gen_interrupt_vector_table(self, hart, mode, status, cause, ie, ip, scratch, instr): '''In vector mode, the BASE address is shared between interrupt 0 and exception handling. When vectored interrupts are enabled, interrupt cause 0, which corresponds to user-mode software interrupts, are vectored to the same location as synchronous exceptions. This ambiguity does not arise in practice, since user-mode software interrupts are either disabled or delegated''' instr.extend( (".option norvc;", "j {}{}mode_exception_handler".format(pkg_ins.hart_prefix(hart), mode))) # Redirect the interrupt to the corresponding interrupt handler for i in range(1, rcs.max_interrupt_vector_num): instr.append("j {}{}mode_intr_vector_{}".format( pkg_ins.hart_prefix(hart), mode, i)) if not cfg.disable_compressed_instr: instr.append(".option rvc;") for i in range(1, rcs.max_interrupt_vector_num): intr_handler = [] pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, intr_handler) self.gen_signature_handshake( instr=intr_handler, signature_type=signature_type_t.CORE_STATUS, core_status=core_status_t.HANDLING_IRQ) intr_handler.extend(( "csrr x{}, {} # {}".format(cfg.gpr[0], hex(cause), cause.name), # Terminate the test if xCause[31] != 0 (indicating exception) "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], hex(rcs.XLEN - 1)), "beqz x{}, 1f".format(cfg.gpr[0]))) csr_list = [status, cause, ie, ip] for csr_t in csr_list: self.gen_signature_handshake( instr=intr_handler, signature_type=signature_type_t.WRITE_CSR, csr=csr_t) # Jump to commmon interrupt handling routine intr_handler.extend( ("j {}{}mode_intr_handler".format(pkg_ins.hart_prefix(hart), mode), "1: la x{}, test_done".format(cfg.scratch_reg), "jalr x0, x{}, 0".format(cfg.scratch_reg))) self.gen_section( pkg_ins.get_label("{}mode_intr_vector_{}".format(mode, i), hart), intr_handler)
def gen_init_section(self, hart): string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN) self.instr_stream.append(string) if cfg.enable_floating_point: self.init_floating_point_gpr() self.init_gpr() # Init stack pointer to point to the end of the user stack string = "{}la x{}, {}user_stack_end".format( pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart)) self.instr_stream.append(string) if cfg.enable_vector_extension: self.init_vector_engine() self.core_is_initialized() self.gen_dummy_csr_write() if rcs.support_pmp: string = pkg_ins.indent + "j main" self.instr_stream.append(string)
def gen_illegal_instr_handler(self, hart): instr = [] self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, core_status_t.ILLEGAL_INSTR_EXCEPTION) self.gen_signature_handshake(instr, signature_type_t.WRITE_CSR, privileged_reg_t.MCAUSE) instr.extend(("csrr x{}, {}".format(cfg.gpr[0], hex(privileged_reg_t.MEPC)), "addi x{}, x{}, 4".format(cfg.gpr[0], cfg.gpr[0]), "csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0]))) pkg_ins.pop_gpr_from_kernel_stack(privileged_reg_t.MSTATUS, privileged_reg_t.MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) instr.append("mret") self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart), instr)
def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc, scratch, status, ie, ip): # is_interrupt = 1 tvec_name = "" instr = [] if cfg.mtvec_mode == mtvec_mode_t.VECTORED: self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr) else: # Push user mode GPR to kernel stack before executing exception handling, # this is to avoid exception handling routine modify user program state # unexpectedly # TODO pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) # Checking xStatus can be optional if ISS (like spike) has different implementation of # certain fields compared with the RTL processor. if cfg.check_xstatus: instr.append("csrr x{}, {} # {}".format( cfg.gpr[0], hex(status), status.name)) instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex( cause), cause.name) + "{}srli x{}, x{}, {}\n".format( pkg_ins.indent, cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 1) + "{}bne x{}, x0, {}{}mode_intr_handler".format( pkg_ins.indent, cfg.gpr[0], pkg_ins.hart_prefix(hart), mode)) # The trap handler will occupy one 4KB page, it will be allocated one entry in # the page table with a specific privileged mode. if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align {}".format(cfg.tvec_alignment)) tvec_name = tvec.name self.gen_section( pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr) # TODO Exception handlers instr = [] if cfg.mtvec_mode == mtvec_mode_t.VECTORED: pkg_ins.push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, core_status_t.HANDLING_EXCEPTION) # The trap is caused by an exception, read back xCAUSE, xEPC to see if these # CSR values are set properly. The checking is done by comparing against the log # generated by ISA simulator (spike). instr.extend(( "csrr x{}, 0x{} # {}".format(cfg.gpr[0], epc, epc.name), "csrr x{}, 0x{} # {}".format(cfg.gpr[0], cause, cause.name), # Illegal instruction exception "li x{}, {} # ILLEGAL_INSTRUCTION".format( cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)), "beq x{}, x{}, {}illegal_instr_handler".format( cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)), # Skip checking tval for illegal instruction as it's implementation specific "csrr x{}, {} # {}".format(cfg.gpr[1], hex(tval), tval.name), # use JALR to jump to test_done. "1: la x{}, test_done".format(cfg.scratch_reg), "jalr x1, x{}, 0".format(cfg.scratch_reg))) self.gen_section( pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr)
def gen_program(self): # Generate program header self.instr_stream.clear() self.gen_program_header() for hart in range(cfg.num_of_harts): # Commenting out for now # sub_program_name = [] self.instr_stream.append(f"h{int(hart)}_start:") if(not(cfg.bare_program_mode)): self.setup_misa() # Create all page tables self.create_page_table(hart) # Setup privileged mode registers and enter target privileged mode self.pre_enter_privileged_mode(hart) # Init section self.gen_init_section(hart) # To DO ''' If PMP is supported, we want to generate the associated trap handlers and the test_done section at the start of the program so we can allow access through the pmpcfg0 CSR ''' if(rcs.support_pmp and not(cfg.bare_program_mode)): self.gen_trap_handlers(hart) # Ecall handler self.gen_ecall_handler(hart) # Instruction fault handler self.gen_instr_fault_handler(hart) # Load fault handler self.gen_load_fault_handler(hart) # Store fault handler self.gen_store_fault_handler(hart) self.gen_test_done() # Generate main program gt_lbl_str = pkg_ins.get_label("main", hart) gt_lbl_str = riscv_instr_sequence() self.main_program.append(gt_lbl_str) self.main_program[hart].instr_cnt = cfg.main_program_instr_cnt self.main_program[hart].is_debug_program = 0 self.main_program[hart].label_name = "main" self.main_program[hart].gen_instr(is_main_program = 1, no_branch = cfg.no_branch_jump) self.main_program[hart].generate_instr_stream() logging.info("Generating main program instruction stream...done") self.instr_stream.extend(self.main_program[hart].instr_string_list) """ If PMP is supported, need to jump from end of main program to test_done section at the end of main_program, as the test_done will have moved to the beginning of the program """ self.instr_stream.append("{}j test_done".format(pkg_ins.indent)) ''' Test done section If PMP isn't supported, generate this in the normal location ''' if(hart == 0 and not(rcs.support_pmp)): self.gen_test_done() logging.info("Main/sub program generation...done") # program end self.gen_program_end(hart) for hart in range(cfg.num_of_harts): self.gen_data_page_begin(hart) if(cfg.no_data_page): self.gen_data_page() if((hart == 0) and ("RV32A" in rcs.supported_isa)): self.gen_data_page(hart, amo = 1) self.gen_stack_section(hart) if(not cfg.bare_program_mode): self.gen_kernel_sections(hart)
def gen_interrupt_handler_section(self, mode, hart): interrupt_handler_instr = [] ls_unit = "w" if (rcs.XLEN == 32) else "d" # TODO # if(mode.value < cfg.init_privileged_mode): # return if(mode is privileged_mode_t.USER_MODE.name and not (rcs.support_umode_trap)): return if(mode == privileged_mode_t.MACHINE_MODE.name): mode_prefix = "m" status = privileged_reg_t.MSTATUS ip = privileged_reg_t.MIP ie = privileged_reg_t.MIE scratch = privileged_reg_t.MSCRATCH elif(mode is privileged_mode_t.SUPERVISOR_MODE.name): mode_prefix = "s" status = privileged_reg_t.SSTATUS ip = privileged_reg_t.SIP ie = privileged_reg_t.SIE scratch = privileged_reg_t.SSCRATCH elif(mode == privileged_mode_t.USER_MODE.name): mode_prefix = "u" status = privileged_reg_t.USTATUS ip = privileged_reg_t.UIP ie = privileged_reg_t.UIE scratch = privileged_reg_t.USCRATCH else: logging.critical("Unsupported mode: %0s" % (mode)) if(cfg.enable_nested_interrupt): interrupt_handler_instr.append("csrr x%0d, 0x%0x" % (cfg.gpr[0].value, scratch.value)) interrupt_handler_instr.append("bgtz x%0d, 1f" % (cfg.gpr[0].value)) interrupt_handler_instr.append("csrwi 0x%0x, 0x1" % (scratch.value)) if(status == privileged_reg_t.MSTATUS): interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 8)) elif(status == privileged_reg_t.SSTATUS): interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 2)) elif(status == privileged_reg_t.USTATUS): interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 1)) else: logging.critical("Unsupported status %0s" % (status.value)) interrupt_handler_instr.append("1: csrwi 0x%0x,0" % (scratch.value)) to_extend_interrupt_hanlder_instr = ["csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value, status.value, status.name), "csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value, ie.value, ie.name), "csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value, ip.value, ip.name), "csrrc x%0d, 0x%0x, x%0d # %0s;" % (cfg.gpr[0].value, ip.value, cfg.gpr[0].value, ip.name)] interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr) self.gen_plic_section(interrupt_handler_instr) pkg_ins.pop_gpr_from_kernel_stack(status.name, scratch.name, cfg.mstatus_mprv, cfg.sp, cfg.tp, interrupt_handler_instr) interrupt_handler_instr.append("%0sret;" % (mode_prefix)) if(rcs.SATP_MODE != "BARE"): self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") self.gen_section(pkg_ins.get_label("%0smode_intr_handler" % (mode_prefix), hart), interrupt_handler_instr)
def gen_interrupt_handler_section(self, mode, hart): interrupt_handler_instr = [] # ls_unit = "w" if rcs.XLEN == 32 else "d" if mode < cfg.init_privileged_mode: return if (mode is privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)): return if mode == privileged_mode_t.MACHINE_MODE: mode_prefix = "m" status = privileged_reg_t.MSTATUS ip = privileged_reg_t.MIP ie = privileged_reg_t.MIE scratch = privileged_reg_t.MSCRATCH elif mode is privileged_mode_t.SUPERVISOR_MODE: mode_prefix = "s" status = privileged_reg_t.SSTATUS ip = privileged_reg_t.SIP ie = privileged_reg_t.SIE scratch = privileged_reg_t.SSCRATCH elif mode == privileged_mode_t.USER_MODE: mode_prefix = "u" status = privileged_reg_t.USTATUS ip = privileged_reg_t.UIP ie = privileged_reg_t.UIE scratch = privileged_reg_t.USCRATCH else: logging.critical("Unsupported mode: {}".format(mode.name)) sys.exit(1) if cfg.enable_nested_interrupt: interrupt_handler_instr.append("csrr x{}, {}".format( cfg.gpr[0], hex(scratch))) interrupt_handler_instr.append("bgtz x{}, 1f".format(cfg.gpr[0])) interrupt_handler_instr.append("csrwi {}, 0x1".format( hex(scratch))) if status == privileged_reg_t.MSTATUS: interrupt_handler_instr.append("csrsi {}, {}".format( hex(status), hex(8))) elif status == privileged_reg_t.SSTATUS: interrupt_handler_instr.append("csrsi {}, {}".format( hex(status), hex(2))) elif status == privileged_reg_t.USTATUS: interrupt_handler_instr.append("csrsi {}, {}".format( hex(status), hex(1))) else: logging.critical("Unsupported status {}".format(status.name)) sys.exit(1) interrupt_handler_instr.append("1: csrwi {},0".format( hex(scratch))) to_extend_interrupt_hanlder_instr = [ "csrr x{}, {} # {};".format(cfg.gpr[0], hex(status), status.name), "csrr x{}, {} # {};".format(cfg.gpr[0], hex(ie), ie.name), "csrr x{}, {} # {};".format(cfg.gpr[0], hex(ip), ip.name), "csrrc x{}, {}, x{} # {};".format(cfg.gpr[0], hex(ip), cfg.gpr[0], ip.name) ] interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr) self.gen_plic_section(interrupt_handler_instr) pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, interrupt_handler_instr) interrupt_handler_instr.append("{}ret;".format(mode_prefix)) if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") self.gen_section( pkg_ins.get_label("%0smode_intr_handler" % (mode_prefix), hart), interrupt_handler_instr)