From 6b255ec09c1ceb1b655ef2d2516063e59bf544ab Mon Sep 17 00:00:00 2001
From: toy <toy>
Date: Wed, 13 Nov 2002 13:12:35 +0000
Subject: [PATCH] Was not properly handling undefined foreign symbols: o Need
 to restore all global (%g) Lisp registers because they may have   been
 trashed by the C code. o The unimp trap_Error was wrong.  Get the right
 number of arg bytes   and the right SC_OFFSET!

---
 lisp/sparc-assem.S | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/lisp/sparc-assem.S b/lisp/sparc-assem.S
index d5d1cd802..3f41a021e 100644
--- a/lisp/sparc-assem.S
+++ b/lisp/sparc-assem.S
@@ -405,15 +405,43 @@ _resolve_linkage_tramp:
 		
 	.global _undefined_foreign_symbol_trap
 	FUNCDEF(_undefined_foreign_symbol_trap)
-_undefined_foreign_symbol_trap:	
+#define	SC_OFFSET_HI(sc, reg)	((sc | (reg << 5)) >> 8)
+#define	SC_OFFSET_LO(sc, reg)	((sc | (reg << 5)) & 0xff)
+/*
+ * When we get called, %o0 contains the address of the data_vector object 
+ * which is a string naming the bad symbol.
+ */
+_undefined_foreign_symbol_trap:
+	/*
+	   Need to restore all the global registers with the Lisp values that 
+	   were saved away in call_into_c.  (This routine is only called from 
+	   os_link_one_symbol, which is called from resolve_linkage_tramp, which 
+	   is called from call_into_c.)
+
+	   The global registers are volatile across function calls, so who
+	   knows what values have been they contain now!
+		
+	*/
+
+	load(_current_dynamic_space_free_pointer, reg_ALLOC)
+        load(_current_binding_stack_pointer, reg_BSP)
+        load(_current_control_stack_pointer, reg_CSP)
+        load(_current_control_frame_pointer, reg_CFP)
+		
+	set	NIL, reg_NIL
+
+	mov	%o0, reg_A0			
 	unimp	trap_Error
-	.byte	2	/* Number of argument bytes */
+	.byte	4	/* Number of argument bytes */
 	.byte	UNDEFINED_FOREIGN_SYMBOL_ERROR
-        /* Escape to create 16bit BE number from following two values */
+        /* Escape to create 16bit BE number from following two values
+	   but bytes are given in little-endian order (!) */
         .byte	254
-        /* SC_OFFSET(sc_DescriptorReg,NL0) NL0 = %o0 */
-	.byte	sc_NonDescriptorReg
-	.byte	0
+        /* SC_OFFSET(sc_DescriptorReg,A0) = (offset << 5) | sc_DescriptorReg */
+	/* reg_A0 = 16.  See the defref for a0 in sparc/vm.lisp */
+		
+	.byte	SC_OFFSET_LO(sc_DescriptorReg, 16)
+	.byte	SC_OFFSET_HI(sc_DescriptorReg, 16)
 	.align	4
 					
 #endif
-- 
GitLab