summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTharo <17233964+Thar0@users.noreply.github.com>2025-08-19 19:46:43 +0100
committerGitHub <noreply@github.com>2025-08-19 14:46:43 -0400
commit1d97f2ea08527a9f2f716add03322656b625e7bb (patch)
tree4de8b10a225169f97a6cd73cc93d7397259784c6
parent28b60fc00cd13f9e4780b88cddbad4b4f2be4cca (diff)
Handwritten asm: OS functions, libm_vals (#1821)
* Handwritten asm: OS functions, libm_vals * rm hardware_regs.ld * andi -> and, addiu -> addu * CACHE macro
-rw-r--r--include/PR/rdb.h80
-rw-r--r--linker_scripts/final/hardware_regs.ld111
-rw-r--r--spec/spec18
-rw-r--r--src/libultra/gu/libm_vals.s8
-rw-r--r--src/libultra/os/getintmask.s6
-rw-r--r--src/libultra/os/interrupt.s45
-rw-r--r--src/libultra/os/invaldcache.s80
-rw-r--r--src/libultra/os/invalicache.s44
-rw-r--r--src/libultra/os/maptlbrdb.s31
-rw-r--r--src/libultra/os/probetlb.s83
-rw-r--r--src/libultra/os/unmaptlball.s25
-rw-r--r--src/libultra/os/writebackdcache.s54
-rw-r--r--src/libultra/os/writebackdcacheall.s19
-rw-r--r--tools/warnings_count/warnings_build_current.txt1
14 files changed, 482 insertions, 123 deletions
diff --git a/include/PR/rdb.h b/include/PR/rdb.h
new file mode 100644
index 000000000..5d41b035a
--- /dev/null
+++ b/include/PR/rdb.h
@@ -0,0 +1,80 @@
+#ifndef PR_RDB_H
+#define PR_RDB_H
+
+/* U64 side address */
+#define RDB_BASE_REG 0xC0000000
+#define RDB_WRITE_INTR_REG (RDB_BASE_REG + 0x8)
+#define RDB_READ_INTR_REG (RDB_BASE_REG + 0xC)
+#define RDB_BASE_VIRTUAL_ADDR 0x80000000
+
+/* packet type Have six bits, so can have up to 63 types */
+#define RDB_TYPE_INVALID 0
+#define RDB_TYPE_GtoH_PRINT 1
+#define RDB_TYPE_GtoH_FAULT 2
+#define RDB_TYPE_GtoH_LOG_CT 3
+#define RDB_TYPE_GtoH_LOG 4
+#define RDB_TYPE_GtoH_READY_FOR_DATA 5
+#define RDB_TYPE_GtoH_DATA_CT 6
+#define RDB_TYPE_GtoH_DATA 7
+#define RDB_TYPE_GtoH_DEBUG 8
+#define RDB_TYPE_GtoH_RAMROM 9
+#define RDB_TYPE_GtoH_DEBUG_DONE 10
+#define RDB_TYPE_GtoH_DEBUG_READY 11
+#define RDB_TYPE_GtoH_KDEBUG 12
+#define RDB_TYPE_GtoH_PROF_DATA 22
+
+
+#define RDB_TYPE_HtoG_LOG_DONE 13
+#define RDB_TYPE_HtoG_DEBUG 14
+#define RDB_TYPE_HtoG_DEBUG_CT 15
+#define RDB_TYPE_HtoG_DATA 16
+#define RDB_TYPE_HtoG_DATA_DONE 17
+#define RDB_TYPE_HtoG_REQ_RAMROM 18
+#define RDB_TYPE_HtoG_FREE_RAMROM 19
+#define RDB_TYPE_HtoG_KDEBUG 20
+#define RDB_TYPE_HtoG_PROF_SIGNAL 21
+
+
+#define RDB_PROF_ACK_SIG 1
+#define RDB_PROF_FLUSH_SIG 2
+#define PROF_BLOCK_SIZE 2048
+
+#define RDB_LOG_MAX_BLOCK_SIZE 0x8000
+#define RDB_DATA_MAX_BLOCK_SIZE 0x8000
+
+
+/* GIO side address */
+#define GIO_RDB_BASE_REG 0xBF480000
+#define GIO_RDB_WRITE_INTR_REG (GIO_RDB_BASE_REG + 0x8)
+#define GIO_RDB_READ_INTR_REG (GIO_RDB_BASE_REG + 0xC)
+
+/* minor device number */
+#define GIO_RDB_PRINT_MINOR 1
+#define GIO_RDB_DEBUG_MINOR 2
+
+/* interrupt bit */
+#define GIO_RDB_WRITE_INTR_BIT 0x80000000
+#define GIO_RDB_READ_INTR_BIT 0x40000000
+
+/* debug command */
+#define DEBUG_COMMAND_NULL 0
+#define DEBUG_COMMAND_MEMORY 1
+#define DEBUG_COMMAND_REGISTER 2
+#define DEBUG_COMMAND_INVALID 255
+
+/* debug state */
+#define DEBUG_STATE_NULL 0
+#define DEBUG_STATE_RECEIVE 1
+#define DEBUG_STATE_INVALID 255
+
+#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
+
+typedef struct {
+ unsigned type : 6; /* 0: invalid, 1: print, 2: debug */
+ unsigned length : 2; /* 1, 2, or 3 */
+ char buf[3]; /* character buffer */
+} rdbPacket;
+
+#endif
+
+#endif
diff --git a/linker_scripts/final/hardware_regs.ld b/linker_scripts/final/hardware_regs.ld
deleted file mode 100644
index 3e7ad405a..000000000
--- a/linker_scripts/final/hardware_regs.ld
+++ /dev/null
@@ -1,111 +0,0 @@
-// libultra OS symbols
-
-D_80000000 = 0x80000000; // __osExceptionPreamble
-D_80000004 = 0x80000004; // __osExceptionPreamble
-D_80000008 = 0x80000008; // __osExceptionPreamble
-D_8000000C = 0x8000000C; // __osExceptionPreamble
-D_80000010 = 0x80000010; //
-D_80000020 = 0x80000020; //
-
-/// OS hardware registers
-
-// Signal Processor Registers
-
-D_A4040000 = 0xA4040000; // SP_MEM_ADDR_REG
-D_A4040004 = 0xA4040004; // SP_DRAM_ADDR_REG
-D_A4040008 = 0xA4040008; // SP_RD_LEN_REG
-D_A404000C = 0xA404000C; // SP_WR_LEN_REG
-D_A4040010 = 0xA4040010; // SP_STATUS_REG
-D_A4040014 = 0xA4040014; // SP_DMA_FULL_REG
-D_A4040018 = 0xA4040018; // SP_DMA_BUSY_REG
-D_A404001C = 0xA404001C; // SP_SEMAPHORE_REG
-
-D_A4080000 = 0xA4080000; // SP PC
-
-// Display Processor Command Registers / Rasterizer Interface
-
-D_A4100000 = 0xA4100000; // DPC_START_REG
-D_A4100004 = 0xA4100004; // DPC_END_REG
-D_A4100008 = 0xA4100008; // DPC_CURRENT_REG
-D_A410000C = 0xA410000C; // DPC_STATUS_REG
-D_A4100010 = 0xA4100010; // DPC_CLOCK_REG
-D_A4100014 = 0xA4100014; // DPC_BUFBUSY_REG
-D_A4100018 = 0xA4100018; // DPC_PIPEBUSY_REG
-D_A410001C = 0xA410001C; // DPC_TMEM_REG
-
-// Display Processor Span Registers
-
-D_A4200000 = 0xA4200000; // DPS_TBIST_REG / DP_TMEM_BIST
-D_A4200004 = 0xA4200004; // DPS_TEST_MODE_REG
-D_A4200008 = 0xA4200008; // DPS_BUFTEST_ADDR_REG
-D_A420000C = 0xA420000C; // DPS_BUFTEST_DATA_REG
-
-// MIPS Interface Registers
-
-D_A4300000 = 0xA4300000; // MI_MODE_REG / MI_INIT_MODE_REG
-D_A4300004 = 0xA4300004; // MI_VERSION_REG
-D_A4300008 = 0xA4300008; // MI_INTR_REG
-D_A430000C = 0xA430000C; // MI_INTR_MASK_REG
-
-// Video Interface Registers
-
-D_A4400000 = 0xA4400000; // VI_STATUS_REG / VI_CONTROL_REG
-D_A4400004 = 0xA4400004; // VI_DRAM_ADDR_REG / VI_ORIGIN_REG
-D_A4400008 = 0xA4400008; // VI_WIDTH_REG
-D_A440000C = 0xA440000C; // VI_INTR_REG
-D_A4400010 = 0xA4400010; // VI_CURRENT_REG
-D_A4400014 = 0xA4400014; // VI_BURST_REG / VI_TIMING_REG
-D_A4400018 = 0xA4400018; // VI_V_SYNC_REG
-D_A440001C = 0xA440001C; // VI_H_SYNC_REG
-D_A4400020 = 0xA4400020; // VI_LEAP_REG
-D_A4400024 = 0xA4400024; // VI_H_START_REG
-D_A4400028 = 0xA4400028; // VI_V_START_REG
-D_A440002C = 0xA440002C; // VI_V_BURST_REG
-D_A4400030 = 0xA4400030; // VI_X_SCALE_REG
-D_A4400034 = 0xA4400034; // VI_Y_SCALE_REG
-
-// Audio Interface Registers
-
-D_A4500000 = 0xA4500000; // AI_DRAM_ADDR_REG
-D_A4500004 = 0xA4500004; // AI_LEN_REG
-D_A4500008 = 0xA4500008; // AI_CONTROL_REG
-D_A450000C = 0xA450000C; // AI_STATUS_REG
-D_A4500010 = 0xA4500010; // AI_DACRATE_REG
-D_A4500014 = 0xA4500014; // AI_BITRATE_REG
-
-// Peripheral/Parallel Interface Registers
-
-D_A4600000 = 0xA4600000; // PI_DRAM_ADDR_REG
-D_A4600004 = 0xA4600004; // PI_CART_ADDR_REG
-D_A4600008 = 0xA4600008; // PI_RD_LEN_REG
-D_A460000C = 0xA460000C; // PI_WR_LEN_REG
-D_A4600010 = 0xA4600010; // PI_STATUS_REG
-D_A4600014 = 0xA4600014; // PI_BSD_DOM1_LAT_REG // PI dom1 latency
-D_A4600018 = 0xA4600018; // PI_BSD_DOM1_PWD_REG // PI dom1 pulse width
-D_A460001C = 0xA460001C; // PI_BSD_DOM1_PGS_REG // PI dom1 page size
-D_A4600020 = 0xA4600020; // PI_BSD_DOM1_RLS_REG // PI dom1 release
-D_A4600024 = 0xA4600024; // PI_BSD_DOM2_LAT_REG // PI dom2 latency
-D_A4600028 = 0xA4600028; // PI_BSD_DOM2_LWD_REG // PI dom2 pulse width
-D_A460002C = 0xA460002C; // PI_BSD_DOM2_PGS_REG // PI dom2 page size
-D_A4600030 = 0xA4600030; // PI_BSD_DOM2_RLS_REG // PI dom2 release
-
-// RDRAM Interface Registers
-
-D_A4700000 = 0xA4700000; // RI_MODE_REG
-D_A4700004 = 0xA4700004; // RI_CONFIG_REG
-D_A4700008 = 0xA4700008; // RI_CURRENT_LOAD_REG
-D_A470000C = 0xA470000C; // RI_SELECT_REG
-D_A4700010 = 0xA4700010; // RI_REFRESH_REG
-D_A4700014 = 0xA4700014; // RI_LATENCY_REG
-D_A4700018 = 0xA4700018; // RI_RERROR_REG
-D_A470001C = 0xA470001C; // RI_WERROR_REG
-
-// Serial Interface Registers
-
-D_A4800000 = 0xA4800000; // SI_DRAM_ADDR_REG
-D_A4800004 = 0xA4800004; // SI_PIF_ADDR_RD64B_REG
-D_A4800008 = 0xA4800008; // reserved
-D_A480000C = 0xA480000C; // reserved
-D_A4800010 = 0xA4800010; // SI_PIF_ADDR_WR64B_REG
-D_A4800014 = 0xA4800014; // reserved
-D_A4800018 = 0xA4800018; // SI_STATUS_REG
diff --git a/spec/spec b/spec/spec
index c477c5846..bf203f357 100644
--- a/spec/spec
+++ b/spec/spec
@@ -79,7 +79,7 @@ beginseg
include "$(BUILD_DIR)/src/libultra/os/virtualtophysical.o"
include "$(BUILD_DIR)/src/libultra/os/getsr.o"
include "$(BUILD_DIR)/src/libultra/os/setsr.o"
- include "$(BUILD_DIR)/asm/boot/writebackdcache.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/writebackdcache.o"
include "$(BUILD_DIR)/src/libultra/os/initialize.o"
include "$(BUILD_DIR)/src/libultra/debug/kdebugserver.o"
include "$(BUILD_DIR)/src/libultra/os/parameters.o"
@@ -101,7 +101,7 @@ beginseg
include "$(BUILD_DIR)/src/libultra/gu/lookat.o"
include "$(BUILD_DIR)/src/libultra/io/pfsallocatefile.o"
include "$(BUILD_DIR)/src/libultra/os/stoptimer.o"
- include "$(BUILD_DIR)/asm/boot/probetlb.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/probetlb.o"
include "$(BUILD_DIR)/src/libultra/io/pimgr.o"
include "$(BUILD_DIR)/src/libultra/io/piacs.o"
include "$(BUILD_DIR)/src/libultra/io/devmgr.o"
@@ -119,14 +119,14 @@ beginseg
include "$(BUILD_DIR)/src/libultra/gu/lookathil.o"
include "$(BUILD_DIR)/src/libultra/libc/xprintf.o"
include "$(BUILD_DIR)/src/libultra/voice/voicecleardictionary.o"
- include "$(BUILD_DIR)/asm/boot/unmaptlball.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/unmaptlball.o"
include "$(BUILD_DIR)/src/libultra/io/epidma.o"
include "$(BUILD_DIR)/src/libultra/voice/voicecontread2.o"
include "$(BUILD_DIR)/src/libultra/voice/voicecrc.o"
include "$(BUILD_DIR)/src/libultra/libc/string.o"
include "$(BUILD_DIR)/src/libultra/os/createmesgqueue.o"
- include "$(BUILD_DIR)/asm/boot/invalicache.text.o"
- include "$(BUILD_DIR)/asm/boot/invaldcache.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/invalicache.o"
+ include "$(BUILD_DIR)/src/libultra/os/invaldcache.o"
include "$(BUILD_DIR)/src/libultra/os/timerintr.o"
include "$(BUILD_DIR)/src/libultra/voice/voicecontread36.o"
include "$(BUILD_DIR)/src/libultra/io/sp.o"
@@ -161,7 +161,7 @@ beginseg
include "$(BUILD_DIR)/src/libultra/os/resetglobalintmask.o"
include "$(BUILD_DIR)/src/libultra/io/pfsdeletefile.o"
include "$(BUILD_DIR)/src/libultra/gu/ortho.o"
- include "$(BUILD_DIR)/asm/boot/interrupt.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/interrupt.o"
include "$(BUILD_DIR)/src/libultra/vimodes/vimodentsclan1.o"
include "$(BUILD_DIR)/src/libultra/vimodes/vimodempallan1.o"
include "$(BUILD_DIR)/src/libultra/io/vi.o"
@@ -188,14 +188,14 @@ beginseg
include "$(BUILD_DIR)/src/libultra/io/pfschecker.o"
include "$(BUILD_DIR)/src/libultra/io/aigetlen.o"
include "$(BUILD_DIR)/src/libultra/io/epiwrite.o"
- include "$(BUILD_DIR)/asm/boot/maptlbrdb.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/maptlbrdb.o"
include "$(BUILD_DIR)/src/libultra/os/yieldthread.o"
include "$(BUILD_DIR)/src/libultra/mgu/translate.o"
include "$(BUILD_DIR)/src/libultra/os/getcause.o"
include "$(BUILD_DIR)/src/libultra/io/contramwrite.o"
include "$(BUILD_DIR)/src/libultra/io/epirawwrite.o"
include "$(BUILD_DIR)/src/libultra/os/settimer.o"
- include "$(BUILD_DIR)/data/boot/libm_vals.rodata.o"
+ include "$(BUILD_DIR)/src/libultra/gu/libm_vals.o"
include "$(BUILD_DIR)/src/libultra/libc/xldtob.o"
include "$(BUILD_DIR)/src/libultra/libc/ldiv.o"
include "$(BUILD_DIR)/src/libultra/libc/xlitob.o"
@@ -204,7 +204,7 @@ beginseg
include "$(BUILD_DIR)/src/libultra/io/spsetstat.o"
include "$(BUILD_DIR)/src/libultra/io/vimgr.o"
include "$(BUILD_DIR)/src/libultra/io/vigetcurrcontext.o"
- include "$(BUILD_DIR)/asm/boot/writebackdcacheall.text.o"
+ include "$(BUILD_DIR)/src/libultra/os/writebackdcacheall.o"
include "$(BUILD_DIR)/src/libultra/os/getcurrfaultthread.o"
include "$(BUILD_DIR)/src/libultra/voice/voicemaskdictionary.o"
include "$(BUILD_DIR)/src/libultra/mgu/mtxf2l.o"
diff --git a/src/libultra/gu/libm_vals.s b/src/libultra/gu/libm_vals.s
new file mode 100644
index 000000000..fb430e1b6
--- /dev/null
+++ b/src/libultra/gu/libm_vals.s
@@ -0,0 +1,8 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+
+.rdata
+
+DATA(__libm_qnan_f)
+ .word 0x7F810000
+ENDDATA(__libm_qnan_f)
diff --git a/src/libultra/os/getintmask.s b/src/libultra/os/getintmask.s
index f5e7cf770..50c187f5c 100644
--- a/src/libultra/os/getintmask.s
+++ b/src/libultra/os/getintmask.s
@@ -22,13 +22,13 @@ LEAF(osGetIntMask)
.set noreorder
/* Extract interrupt enable bits from current SR */
mfc0 v0, C0_SR
- andi v0, v0, (SR_IMASK | SR_IE)
+ and v0, v0, (SR_IMASK | SR_IE)
/* Get value of __OSGlobalIntMask */
la t0, __OSGlobalIntMask
lw t1, (t0)
/* Bitwise-OR in the disabled CPU bits of __OSGlobalIntMask */
xor t0, t1, ~0
- andi t0, t0, SR_IMASK
+ and t0, t0, SR_IMASK
or v0, v0, t0
/* Fetch MI_INTR_MASK_REG */
lw t1, PHYS_TO_K1(MI_INTR_MASK_REG)
@@ -40,7 +40,7 @@ LEAF(osGetIntMask)
/* Bitwise-OR in the disabled RCP bits of __OSGlobalIntMask */
srl t0, t0, RCP_IMASKSHIFT
xor t0, t0, ~0
- andi t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
+ and t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
or t1, t1, t0
1:
/* Shift the RCP bits to not conflict with the CPU bits */
diff --git a/src/libultra/os/interrupt.s b/src/libultra/os/interrupt.s
new file mode 100644
index 000000000..3726c3a42
--- /dev/null
+++ b/src/libultra/os/interrupt.s
@@ -0,0 +1,45 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+#include "PR/os_thread.h"
+
+.text
+
+LEAF(__osDisableInt)
+ la t2, __OSGlobalIntMask
+ lw t3, (t2)
+ and t3, t3, SR_IMASK
+ MFC0( t0, C0_SR)
+ and t1, t0, ~SR_IE
+ MTC0( t1, C0_SR)
+ and v0, t0, SR_IE
+ lw t0, (t2)
+ and t0, t0, SR_IMASK
+.set noreorder
+ beq t0, t3, No_Change_Global_Int
+ /*! @bug this la should be lw, it may never come up in practice as to reach this code
+ *! the CPU bits of __OSGlobalIntMask must have changed while this function is running.
+ */
+ la t2, __osRunningThread
+ lw t1, THREAD_SR(t2)
+ and t2, t1, SR_IMASK
+ and t2, t2, t0
+.set reorder
+ and t1, t1, ~SR_IMASK
+ or t1, t1, t2
+ and t1, t1, ~SR_IE
+ MTC0( t1, C0_SR)
+ NOP
+ NOP
+No_Change_Global_Int:
+ jr ra
+END(__osDisableInt)
+
+LEAF(__osRestoreInt)
+ MFC0( t0, C0_SR)
+ or t0, t0, a0
+ MTC0( t0, C0_SR)
+ NOP
+ NOP
+ jr ra
+END(__osRestoreInt)
diff --git a/src/libultra/os/invaldcache.s b/src/libultra/os/invaldcache.s
new file mode 100644
index 000000000..2187ccf80
--- /dev/null
+++ b/src/libultra/os/invaldcache.s
@@ -0,0 +1,80 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+/**
+ * void osInvalDCache(void* vaddr, s32 nbytes);
+ *
+ * Invalidates the CPU Data Cache for `nbytes` at `vaddr`.
+ * The cache is not automatically synced with physical memory, so cache
+ * lines must be invalidated to ensure old data is not used in place of
+ * newly available data supplied by an external agent in a DMA operation.
+ *
+ * If `vaddr` is not aligned to a cache line boundary, or nbytes is not a
+ * multiple of the data cache line size (16 bytes) a larger region is
+ * invalidated.
+ *
+ * If the amount to invalidate is at least the data cache size (DCACHE_SIZE),
+ * the entire data cache is invalidated.
+ */
+LEAF(osInvalDCache)
+ /* If the amount to invalidate is less than or equal to 0, return immediately */
+ blez a1, 3f
+ /* If the amount to invalidate is as large as or larger than
+ * the data cache size, invalidate all */
+ li t3, DCACHE_SIZE
+ bgeu a1, t3, 4f
+ /* Ensure end address doesn't wrap around and end up smaller
+ * than the start address */
+ move t0, a0
+ addu t1, a0, a1
+ bgeu t0, t1, 3f
+ /* Mask start with cache line */
+ addu t1, t1, -DCACHE_LINESIZE
+ and t2, t0, DCACHE_LINEMASK
+ /* If mask is not zero, the start is not cache aligned */
+ beqz t2, 1f
+ /* Subtract mask result to align to cache line */
+ subu t0, t0, t2
+ /* Hit-Writeback-Invalidate unaligned part */
+ CACHE( (CACH_PD | C_HWBINV), (t0))
+ /* If that's all there is to do, return early */
+ bgeu t0, t1, 3f
+ addu t0, t0, DCACHE_LINESIZE
+1:
+ /* Mask end with cache line */
+ and t2, t1, DCACHE_LINEMASK
+ /* If mask is not zero, the end is not cache aligned */
+ beqz t2, 2f
+ /* Subtract mask result to align to cache line */
+ subu t1, t1, t2
+ /* Hit-Writeback-Invalidate unaligned part */
+ CACHE( (CACH_PD | C_HWBINV), DCACHE_LINESIZE(t1))
+ /* If that's all there is to do, return early */
+ bltu t1, t0, 3f
+ /* Invalidate the rest */
+2:
+ /* Hit-Invalidate */
+ CACHE( (CACH_PD | C_HINV), (t0))
+.set noreorder
+ bltu t0, t1, 2b
+ addu t0, t0, DCACHE_LINESIZE
+.set reorder
+3:
+ jr ra
+
+4:
+ li t0, K0BASE
+ addu t1, t0, t3
+ addu t1, t1, -DCACHE_LINESIZE
+5:
+ /* Index-Writeback-Invalidate */
+ CACHE( (CACH_PD | C_IWBINV), (t0))
+.set noreorder
+ bltu t0, t1, 5b
+ addu t0, DCACHE_LINESIZE
+.set reorder
+ jr ra
+END(osInvalDCache)
diff --git a/src/libultra/os/invalicache.s b/src/libultra/os/invalicache.s
new file mode 100644
index 000000000..2d0840880
--- /dev/null
+++ b/src/libultra/os/invalicache.s
@@ -0,0 +1,44 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+LEAF(osInvalICache)
+ /* If the amount to invalidate is less than or equal to 0, return immediately */
+ blez a1, 2f
+ /* If the amount to invalidate is as large as or larger than */
+ /* the instruction cache size, invalidate all */
+ li t3, ICACHE_SIZE
+ bgeu a1, t3, 3f
+ /* ensure end address doesn't wrap around and end up smaller */
+ /* than the start address */
+ move t0, a0
+ addu t1, a0, a1
+ bgeu t0, t1, 2f
+ /* Mask and subtract to align to cache line */
+ addu t1, t1, -ICACHE_LINESIZE
+ and t2, t0, ICACHE_LINEMASK
+ subu t0, t0, t2
+1:
+ CACHE( (CACH_PI | C_HINV), (t0))
+.set noreorder
+ bltu t0, t1, 1b
+ addu t0, t0, ICACHE_LINESIZE
+.set reorder
+2:
+ jr ra
+
+3:
+ li t0, K0BASE
+ addu t1, t0, t3
+ addu t1, t1, -ICACHE_LINESIZE
+4:
+ CACHE( (CACH_PI | C_IINV), (t0))
+.set noreorder
+ bltu t0, t1, 4b
+ addu t0, ICACHE_LINESIZE
+.set reorder
+ jr ra
+.set reorder
+END(osInvalICache)
diff --git a/src/libultra/os/maptlbrdb.s b/src/libultra/os/maptlbrdb.s
new file mode 100644
index 000000000..e186f060d
--- /dev/null
+++ b/src/libultra/os/maptlbrdb.s
@@ -0,0 +1,31 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+#include "PR/rdb.h"
+
+.text
+
+LEAF(osMapTLBRdb)
+ MFC0( t0, C0_ENTRYHI)
+ li t1, NTLBENTRIES
+ MTC0( t1, C0_INX)
+ MTC0( zero, C0_PAGEMASK)
+ li t2, (TLBLO_UNCACHED | TLBLO_D | TLBLO_V | TLBLO_G)
+ li t1, (RDB_BASE_REG & TLBHI_VPN2MASK)
+ MTC0( t1, C0_ENTRYHI)
+ /* Possible bug? Virtual address instead of physical address set as page frame number */
+ li t1, RDB_BASE_VIRTUAL_ADDR
+ srl t3, t1, TLBLO_PFNSHIFT
+ or t3, t3, t2
+ MTC0( t3, C0_ENTRYLO0)
+ li t1, TLBLO_G
+ MTC0( t1, C0_ENTRYLO1)
+ NOP
+ TLBWI
+ NOP
+ NOP
+ NOP
+ NOP
+ MTC0( t0, C0_ENTRYHI)
+ jr ra
+END(osMapTLBRdb)
diff --git a/src/libultra/os/probetlb.s b/src/libultra/os/probetlb.s
new file mode 100644
index 000000000..27b4418fa
--- /dev/null
+++ b/src/libultra/os/probetlb.s
@@ -0,0 +1,83 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+/**
+ * u32 __osProbeTLB(void* vaddr);
+ *
+ * Searches the TLB for the physical address associated with
+ * the virtual address `vaddr`.
+ *
+ * Returns the physical address if found, or -1 if not found.
+ */
+LEAF(__osProbeTLB)
+.set noreorder
+ /* Set C0_ENTRYHI based on supplied vaddr */
+ mfc0 t0, C0_ENTRYHI
+ and t1, t0, TLBHI_PIDMASK
+ and t2, a0, TLBHI_VPN2MASK
+ or t1, t1, t2
+ mtc0 t1, C0_ENTRYHI
+ nop
+ nop
+ nop
+ /* TLB probe, sets C0_INX to a value matching C0_ENTRYHI. */
+ /* If no match is found the TLBINX_PROBE bit is set to indicate this. */
+ tlbp
+ nop
+ nop
+ /* Read result */
+ mfc0 t3, C0_INX
+ and t3, t3, TLBINX_PROBE
+ /* Branch if no match was found */
+ bnez t3, 3f
+ nop
+
+ /* Read TLB, sets C0_ENTRYHI, C0_ENTRYLO0, C0_ENTRYLO1 and C0_PAGEMASK for the TLB */
+ /* entry indicated by C0_INX */
+ tlbr
+ nop
+ nop
+ nop
+ /* Calculate page size = (page mask + 0x2000) >> 1 */
+ mfc0 t3, C0_PAGEMASK
+ add t3, t3, 0x2000
+ srl t3, t3, 1
+ /* & with vaddr */
+ and t4, t3, a0
+ /* Select C0_ENTRYLO0 or C0_ENTRYLO1 */
+ bnez t4, 1f
+ add t3, t3, -1 /* make bitmask out of page size */
+ mfc0 v0, C0_ENTRYLO0
+ b 2f
+ nop
+1:
+ mfc0 v0, C0_ENTRYLO1
+2:
+ /* Check valid bit and branch if not valid */
+ and t5, v0, TLBLO_V
+ beqz t5, 3f
+ nop
+
+ /* Extract the Page Frame Number from the entry */
+ and v0, v0, TLBLO_PFNMASK
+ sll v0, v0, TLBLO_PFNSHIFT
+ /* Mask vaddr with page size mask */
+ and t5, a0, t3
+ /* Add masked vaddr to pfn to obtain the physical address */
+ add v0, v0, t5
+ b 4f
+ nop
+3:
+ /* No physical address for the supplied virtual address was found, */
+ /* return -1 */
+ li v0, -1
+4:
+ /* Restore original C0_ENTRYHI value before returning */
+ mtc0 t0, C0_ENTRYHI
+ jr ra
+ nop
+.set reorder
+END(__osProbeTLB)
diff --git a/src/libultra/os/unmaptlball.s b/src/libultra/os/unmaptlball.s
new file mode 100644
index 000000000..1933f373f
--- /dev/null
+++ b/src/libultra/os/unmaptlball.s
@@ -0,0 +1,25 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+LEAF(osUnmapTLBAll)
+ MFC0( t0, C0_ENTRYHI)
+ li t1, (NTLBENTRIES - 1)
+ li t2, (K0BASE & TLBHI_VPN2MASK)
+ MTC0( t2, C0_ENTRYHI)
+ MTC0( zero, C0_ENTRYLO0)
+ MTC0( zero, C0_ENTRYLO1)
+1:
+ MTC0( t1, C0_INX)
+ NOP
+ TLBWI
+ NOP
+ NOP
+ addi t1, t1, -1
+ bgez t1, 1b
+
+ MTC0( t0, C0_ENTRYHI)
+ jr ra
+END(osUnmapTLBAll)
diff --git a/src/libultra/os/writebackdcache.s b/src/libultra/os/writebackdcache.s
new file mode 100644
index 000000000..1d77fea50
--- /dev/null
+++ b/src/libultra/os/writebackdcache.s
@@ -0,0 +1,54 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+/**
+ * void osWritebackDCache(void* vaddr, s32 nbytes);
+ *
+ * Writes back the contents of the data cache to main memory for `nbytes` at `vaddr`.
+ * If `nbytes` is as large as or larger than the data cache size, the entire cache is
+ * written back.
+ */
+LEAF(osWritebackDCache)
+ /* If the amount to write back is less than or equal to 0, return immediately */
+ blez a1, 2f
+
+ /* If the amount to write back is as large as or larger than */
+ /* the data cache size, write back all */
+ li t3, DCACHE_SIZE
+ bgeu a1, t3, 3f
+
+ /* ensure end address doesn't wrap around and end up smaller */
+ /* than the start address */
+ move t0, a0
+ addu t1, a0, a1
+ bgeu t0, t1, 2f
+
+ /* Mask and subtract to align to cache line */
+ addu t1, t1, -DCACHE_LINESIZE
+ and t2, t0, DCACHE_LINEMASK
+ subu t0, t0, t2
+1:
+ CACHE( (CACH_PD | C_HWB), (t0))
+.set noreorder
+ bltu t0, t1, 1b
+ addu t0, t0, DCACHE_LINESIZE
+.set reorder
+2:
+ jr ra
+
+/* same as osWritebackDCacheAll in operation */
+3:
+ li t0, K0BASE
+ addu t1, t0, t3
+ addu t1, t1, -DCACHE_LINESIZE
+4:
+ CACHE( (CACH_PD | C_IWBINV), (t0))
+.set noreorder
+ bltu t0, t1, 4b
+ addu t0, DCACHE_LINESIZE
+.set reorder
+ jr ra
+END(osWritebackDCache)
diff --git a/src/libultra/os/writebackdcacheall.s b/src/libultra/os/writebackdcacheall.s
new file mode 100644
index 000000000..432b3b05e
--- /dev/null
+++ b/src/libultra/os/writebackdcacheall.s
@@ -0,0 +1,19 @@
+#include "PR/asm.h"
+#include "PR/regdef.h"
+#include "PR/R4300.h"
+
+.text
+
+LEAF(osWritebackDCacheAll)
+ li t0, K0BASE
+ li t2, DCACHE_SIZE
+ addu t1, t0, t2
+ addu t1, t1, -DCACHE_LINESIZE
+1:
+ CACHE( (CACH_PD | C_IWBINV), (t0))
+.set noreorder
+ bltu t0, t1, 1b
+ addu t0, DCACHE_LINESIZE
+.set reorder
+ jr ra
+END(osWritebackDCacheAll)
diff --git a/tools/warnings_count/warnings_build_current.txt b/tools/warnings_count/warnings_build_current.txt
index 96fff2b09..1d4e5da56 100644
--- a/tools/warnings_count/warnings_build_current.txt
+++ b/tools/warnings_count/warnings_build_current.txt
@@ -1,5 +1,6 @@
Warning: In Soundfont Soundfont_40: Invalid pointer indirect 0 for samplebank SampleBank_2
cc: Warning: -mips3 should not be used for ucode 32-bit compiles
as1: Warning: src/libultra/os/getintmask.s, line 38: Macro instruction used in branch delay slot
+as1: Warning: src/libultra/os/interrupt.s, line 23: Macro instruction used in branch delay slot
cc: Warning: -mips3 should not be used for ucode 32-bit compiles
cc: Warning: -mips3 should not be used for ucode 32-bit compiles