Merge pull request #212 from riscv/hartsel
[riscv-isa-sim.git] / debug_rom / debug_rom.S
index e7e99d0b4305994d708d7aa7801d90a2d7e44a64..28c7076fda5c17dc2f46d1cf2fead993ba92b6f5 100755 (executable)
-# This code should be functional. Doesn't have to be optimal.
-# I'm writing it to prove that it can be done.
+// See LICENSE.SiFive for license details.
 
 #include "riscv/encoding.h"
+#include "riscv/debug_rom_defines.h"
 
-# TODO: Update these constants once they're finalized in the doc.
-
-#define DCSR                    0x790
-#define DCSR_CAUSE_DEBINT       3
-#define DCSR_HALT_OFFSET        3
-#define DCSR_DEBUGINT_OFFSET    10
-
-#define DSCRATCH                0x792
-
-#define DEBUG_RAM               0x400
-#define DEBUG_RAM_SIZE          64
-
-#define SETHALTNOT              0x100
-#define CLEARDEBINT             0x108
-
+        .option norvc
         .global entry
-        .global resume
         .global exception
 
-        # Automatically called when Debug Mode is first entered.
-entry:  j       _entry
-        # Should be called by Debug RAM code that has finished execution and
-        # wants to return to Debug Mode.
+        // Entry location on ebreak, Halt, or Breakpoint
+        // It is the same for all harts. They branch when 
+        // their GO or RESUME bit is set.
+
+entry:
+       jal zero, _entry
 resume:
-        j       _resume
+       jal zero, _resume
 exception:
-        # Set the last word of Debug RAM to all ones, to indicate that we hit
-        # an exception.
-        li      s0, ~0
-        j       _resume2
+       jal zero, _exception
 
-_resume:
-        li      s0, 0
-_resume2:
-        # Clear debug interrupt.
-        csrr    s1, CSR_MHARTID
-        sw      s1, CLEARDEBINT(zero)
+_entry:
+        // This fence is required because the execution may have written something
+        // into the Abstract Data or Program Buffer registers.
         fence
+        csrw CSR_DSCRATCH, s0  // Save s0 to allow signaling MHARTID
+
+        // We continue to let the hart know that we are halted in order that
+        // a DM which was reset is still made aware that a hart is halted.
+        // We keep checking both whether there is something the debugger wants
+        // us to do, or whether we should resume.
+entry_loop:
+        csrr s0, CSR_MHARTID
+        sw   s0, DEBUG_ROM_HALTED(zero)
+        lbu  s0, DEBUG_ROM_FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
+        andi s0, s0, (1 << DEBUG_ROM_FLAG_GO)
+        bnez s0, going
+        csrr s0, CSR_MHARTID
+        lbu  s0, DEBUG_ROM_FLAGS(s0) // multiple harts can resume  here
+        andi s0, s0, (1 << DEBUG_ROM_FLAG_RESUME)
+        bnez s0, resume
+        jal  zero, entry_loop
+
+_exception:
+        sw      zero, DEBUG_ROM_EXCEPTION(zero) // Let debug module know you got an exception.
+        ebreak
+
+going:
+        csrr s0, CSR_DSCRATCH            // Restore s0 here
+        sw zero, DEBUG_ROM_GOING(zero)   // When debug module sees this write, the GO flag is reset.
+        fence
+        fence.i
+        jalr zero, zero, %lo(whereto)    // Debug module will put different instructions and data in the RAM, 
+                                         // so we use fence and fence.i for safety. (rocket-chip doesn't have this
+                                         // because jalr is special there)
 
-        # Restore s1.
-        csrr    s1, CSR_MISA
-        bltz    s1, restore_not_32
-restore_32:
-        lw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-        j       check_halt
-restore_not_32:
-        slli    s1, s1, 1
-        bltz    s1, restore_128
-restore_64:
-        ld      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
-        j       check_halt
-restore_128:
-        nop     #lq      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
-
-        # s0 contains ~0 if we got here through an exception, and 0 otherwise.
-        # Store this to the last word in Debug RAM so the debugger can tell if
-        # an exception occurred.
-        sw      s0, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-
-check_halt:
-        csrr    s0, DCSR
-        andi    s0, s0, (1<<DCSR_HALT_OFFSET)
-        beqz    s0, exit
-        j       wait_for_interrupt
-
-exit:
-        # Restore s0.
-        csrr    s0, DSCRATCH
+_resume:
+        csrr s0, CSR_MHARTID
+        sw   s0, DEBUG_ROM_RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
+        csrr s0, CSR_DSCRATCH   // Restore s0
         dret
 
-
-_entry:
-        # Save s0 in DSCRATCH
-        csrw    DSCRATCH, s0
-
-        # Check why we're here
-        csrr    s0, DCSR
-        # cause is in bits 2:0 of dcsr
-        andi    s0, s0, 7
-        addi    s0, s0, -DCSR_CAUSE_DEBINT
-        bnez    s0, spontaneous_halt
-
-jdebugram:
-        # Save s1 so that the debug program can use two registers.
-        csrr    s0, CSR_MISA
-        bltz    s0, save_not_32
-save_32:
-        sw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-        jr      zero, DEBUG_RAM
-save_not_32:
-        slli    s0, s0, 1
-        bltz    s0, save_128
-save_64:
-        sd      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
-        jr      zero, DEBUG_RAM
-save_128:
-        nop     #sq      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
-        jr      zero, DEBUG_RAM
-
-spontaneous_halt:
-        csrr    s0, CSR_MHARTID
-        sw      s0, SETHALTNOT(zero)
-        csrsi   DCSR, (1<<DCSR_HALT_OFFSET)
-
-wait_for_interrupt:
-        csrr    s0, DCSR
-        andi    s0, s0, (1<<DCSR_DEBUGINT_OFFSET)
-        beqz    s0, wait_for_interrupt
-
-        j       jdebugram
+        // END OF ACTUAL "ROM" CONTENTS. BELOW IS JUST FOR LINKER SCRIPT.
+
+.section .whereto
+whereto:
+        nop
+        // Variable "ROM" This is : jal x0 abstract, jal x0 program_buffer,
+        //                or jal x0 resume, as desired.
+        //                Debug Module state machine tracks what is 'desired'.
+        //                We don't need/want to use jalr here because all of the
+        //                Variable ROM contents are set by
+        //                Debug Module before setting the OK_GO byte.