Add debug rom code.
authorTim Newsome <tim@sifive.com>
Fri, 22 Apr 2016 22:08:35 +0000 (15:08 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:10 +0000 (12:12 -0700)
debug_rom/Makefile [new file with mode: 0644]
debug_rom/debug_rom.S [new file with mode: 0755]
debug_rom/link.ld [new file with mode: 0644]

diff --git a/debug_rom/Makefile b/debug_rom/Makefile
new file mode 100644 (file)
index 0000000..a6da5a8
--- /dev/null
@@ -0,0 +1,17 @@
+# Recursive make is bad, but in this case we're cross compiling which is a
+# pretty unusual use case.
+
+CC = $(RISCV)/bin/riscv64-unknown-elf-gcc
+OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy
+
+%.o:   %.S
+       $(CC) -c $<
+
+debug_rom:     debug_rom.o
+       $(CC) -nostdlib -nostartfiles -Tlink.ld -o $@ $^
+
+debug_rom.raw: debug_rom
+       $(OBJCOPY) -O binary --only-section .text debug_rom debug_rom.raw
+
+clean:
+       rm -f debug_rom debug_rom.o debug_rom.raw
diff --git a/debug_rom/debug_rom.S b/debug_rom/debug_rom.S
new file mode 100755 (executable)
index 0000000..230f4b4
--- /dev/null
@@ -0,0 +1,105 @@
+# This code should be functional. Doesn't have to be optimal.
+# I'm writing it to prove that it can be done.
+
+# 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 MCPUID                  0xf00
+#define MHARTID                 0xf10
+
+#define DEBUG_RAM               0x400
+#define DEBUG_RAM_SIZE          64
+
+#define SETHALTNOT              0x100
+#define CLEARHALTNOT            0x104
+#define CLEARDEBINT             0x108
+
+        .global entry
+        .global resume
+
+        # 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.
+resume:
+        # Clear debug interrupt.
+clear_debint:
+        csrr    s1, MHARTID
+        sw      s1, CLEARDEBINT(zero)
+clear_debint_loop:
+        csrr    s1, DCSR
+        andi    s1, s1, (1<<DCSR_DEBUGINT_OFFSET)
+        bnez    s1, wait_for_interrupt
+
+        # Restore s1.
+        csrr    s1, MCPUID
+        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)
+
+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
+        eret
+
+
+_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, MCPUID
+        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, MHARTID
+        sw      s0, SETHALTNOT(zero)
+        csrsi   DCSR, DCSR_HALT_OFFSET
+
+wait_for_interrupt:
+        csrr    s0, DCSR
+        andi    s0, s0, (1<<DCSR_DEBUGINT_OFFSET)
+        beqz    s0, wait_for_interrupt
+
+        j       jdebugram
diff --git a/debug_rom/link.ld b/debug_rom/link.ld
new file mode 100644 (file)
index 0000000..356099c
--- /dev/null
@@ -0,0 +1,11 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY( entry )
+SECTIONS
+{
+    . = 0xfffff800;     /* TODO: 0x800 */
+    .text :
+    {
+        *(.text)
+    }
+    _end = .;
+}