From 25727a362ff54dcb05472fbafcdf8ac04702c83b Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Tue, 14 Mar 2023 16:40:30 -0400
Subject: [PATCH] Improve demonstration of using self-modifying code.

---
 examples/self_modify_code/self_modify_code.c | 27 +++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/examples/self_modify_code/self_modify_code.c b/examples/self_modify_code/self_modify_code.c
index 5e40b5f..bf33dc5 100644
--- a/examples/self_modify_code/self_modify_code.c
+++ b/examples/self_modify_code/self_modify_code.c
@@ -8,6 +8,8 @@
 uint32_t count;
 
 
+// This is a complicated way to do it from C land, as a demonstration
+
 // Tell the compiler to put this code in the .data section.  That
 // will cause the startup code to copy it from flash into RAM where
 // it can be easily modified at runtime.
@@ -38,10 +40,14 @@ uint32_t ReadCSRSelfModify( uint16_t whichcsr )
 	// can know what opcode we want to use, then we can let C tell us
 	// what register it would like the value in.
 	//
+	// The fence is needed to make sure the CPU knows to not use
+	// cached instructions.
+	//
 	// The constraints are "ret" is a "write" register, and register a3
 	// is going to be clobbered by the assembly code.
 	asm volatile( 
 		".global readCSRLabel   \n"
+		"	fence               \n"
 		"readCSRLabel:          \n"
 		"	csrrs a3, 0x000, x0 \n"
 		"	addi %[ret], a3, 0  \n"
@@ -51,6 +57,25 @@ uint32_t ReadCSRSelfModify( uint16_t whichcsr )
 }
 
 
+uint32_t ReadCSRSelfModifySimple( uint16_t whichcsr ) __attribute__(( section(".data"))) __attribute__((noinline));
+uint32_t ReadCSRSelfModifySimple( uint16_t whichcsr )
+{
+	uint32_t ret;
+	uint32_t csrcmd = 0x000026f3 | ( whichcsr << 20);
+	asm volatile( 
+		".global readCSRLabel   \n"
+		"   la a3, readCSRLabel \n"
+		"   sw %[csrcmd], 0(a3) \n"
+		"   fence               \n"
+		"readCSRLabel:          \n"
+		"	csrrs a3, 0x000, x0 \n"
+		"	addi %[ret], a3, 0  \n"
+		 : [ret]"=r"(ret) : [csrcmd]"r"(csrcmd) : "a3" );
+
+	return ret;
+}
+
+
 int main()
 {
 	SystemInit48HSI();
@@ -64,7 +89,7 @@ int main()
 	int i;
 	for( i = 0x000; i < 0x1000; i++ )
 	{
-		uint32_t rv =  ReadCSRSelfModify( i );
+		uint32_t rv =  ReadCSRSelfModifySimple( i );
 		if( rv )
 			printf( "%03x = %08x\n", i, rv );
 	}
-- 
GitLab