diff --git a/src/lisp/Config.sparc_sunc b/src/lisp/Config.sparc_sunc
index 2e0b4e069693737c4607667a5b8cdf0e48011fad..9c159320d37a0d17d0a223808ef4877f905c5ae5 100644
--- a/src/lisp/Config.sparc_sunc
+++ b/src/lisp/Config.sparc_sunc
@@ -24,7 +24,7 @@ CC_V8PLUS = -m32 -xarch=sparc
 AS_V8PLUS = -m32 -xarch=sparc
 endif
 
-CFLAGS += -xlibmieee -O
+CFLAGS += -xlibmieee -O -DRELOCATABLE_STACK_START
 DEPEND_FLAGS = -xM
 ASFLAGS = $(AS_V8PLUS)
 OS_LINK_FLAGS = -M /usr/lib/ld/map.noexstk
diff --git a/src/lisp/Config.x86_common b/src/lisp/Config.x86_common
index abd098cfa3ea940403c49f854a2a9e58b768a503..31aebfc1ebfe73e6daf128d669fca5104016f638 100644
--- a/src/lisp/Config.x86_common
+++ b/src/lisp/Config.x86_common
@@ -43,7 +43,8 @@ CPP_INCLUDE_OPTIONS := -I. -I$(PATH1) -I-
 endif
 
 CPPFLAGS := $(CPP_DEFINE_OPTIONS) $(CPP_INCLUDE_OPTIONS) 
-CFLAGS += -Wstrict-prototypes -Wall -O2 -g -fno-omit-frame-pointer
+CFLAGS += -Wstrict-prototypes -Wall -g -fno-omit-frame-pointer
+CFLAGS += -O2
 ASFLAGS = -g 
 
 ASSEM_SRC = x86-assem.S
diff --git a/src/lisp/Config.x86_darwin b/src/lisp/Config.x86_darwin
index 03324aac97099f2dfec1a1035daf1de1b2d9fb3a..c21e746c770dd2b024cb4e3a6563a96d4c42de01 100644
--- a/src/lisp/Config.x86_darwin
+++ b/src/lisp/Config.x86_darwin
@@ -6,7 +6,7 @@ include Config.x86_common
 # you have the 10.5 SDK available.
 MIN_VER = -mmacosx-version-min=10.5
 
-CPPFLAGS += -DDARWIN $(MIN_VER) -m32
+CPPFLAGS += -DDARWIN $(MIN_VER) -m32 -DRELOCATABLE_STACK_START
 CFLAGS += -g3 -mtune=generic
 ASFLAGS += -g3 $(MIN_VER)
 
diff --git a/src/lisp/Config.x86_linux b/src/lisp/Config.x86_linux
index 457a24a3454237c267e3765093eb84d474815fcb..92c5b8946eaf4e6dd95a34d686caf36c7e42b77b 100644
--- a/src/lisp/Config.x86_linux
+++ b/src/lisp/Config.x86_linux
@@ -1,7 +1,7 @@
 # -*- Mode: makefile -*-
 include Config.x86_common
 
-CPPFLAGS += -m32 -D__NO_CTYPE -D_GNU_SOURCE
+CPPFLAGS += -m32 -D__NO_CTYPE -D_GNU_SOURCE -DRELOCATABLE_STACK_START
 CFLAGS += -rdynamic  -march=pentium4 -mfpmath=sse -mtune=generic
 
 UNDEFSYMPATTERN = -Xlinker -u -Xlinker &
diff --git a/src/lisp/Darwin-os.c b/src/lisp/Darwin-os.c
index 53d2db591103528e30912205bb4a89aae1ef7a7f..fd7425af77fcc60c2afc7134cf00c45d07fe8080 100644
--- a/src/lisp/Darwin-os.c
+++ b/src/lisp/Darwin-os.c
@@ -464,8 +464,8 @@ valid_addr(os_vm_address_t addr)
 #ifndef GENCGC
 	|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
 #endif
-	|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
-	|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
+	|| in_range_p(addr, (lispobj)control_stack, control_stack_size)
+	|| in_range_p(addr, (lispobj)binding_stack, binding_stack_size))
 	return TRUE;
     return FALSE;
 }
diff --git a/src/lisp/FreeBSD-os.c b/src/lisp/FreeBSD-os.c
index 51c295b3f023fe3c9f6fe879f9e595b58c97b3a1..d7cdf9b8f8625bb829c99c10b97ee5d46053dd13 100644
--- a/src/lisp/FreeBSD-os.c
+++ b/src/lisp/FreeBSD-os.c
@@ -224,8 +224,8 @@ valid_addr(os_vm_address_t addr)
 #ifndef GENCGC
 	|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
 #endif
-	|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
-	|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
+	|| in_range_p(addr, control_stack, control_stack_size)
+	|| in_range_p(addr, binding_stack, binding_stack_size))
 	return TRUE;
     return FALSE;
 }
diff --git a/src/lisp/Linux-os.c b/src/lisp/Linux-os.c
index 7f7a4d7acd350c1ef5b443ef5a28cf848c2e368f..4cf54fbbb906ec8528f4d9019beefdf300b3de6b 100644
--- a/src/lisp/Linux-os.c
+++ b/src/lisp/Linux-os.c
@@ -385,8 +385,8 @@ valid_addr(os_vm_address_t addr)
 	|| in_range_p(addr, STATIC_SPACE_START, static_space_size)
 	|| in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
 	|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
-	|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
-	|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
+	|| in_range_p(addr, control_stack, control_stack_size)
+	|| in_range_p(addr, binding_stack, binding_stack_size))
 	return TRUE;
     return FALSE;
 }
@@ -454,17 +454,17 @@ sigsegv_handler(HANDLER_ARGS)
 #ifdef i386
     interrupt_handle_now(signal, contextstruct);
 #else
-#define CONTROL_STACK_TOP (((char*) CONTROL_STACK_START) + control_stack_size)
+#define CONTROL_STACK_TOP (((char*) control_stack) + control_stack_size)
 
     addr = arch_get_bad_addr(signal, code, context);
 
     if (addr != NULL && context->sc_regs[reg_ALLOC] & (1 << 63)) {
 	context->sc_regs[reg_ALLOC] -= (1 << 63);
 	interrupt_handle_pending(context);
-    } else if (addr > CONTROL_STACK_TOP && addr < BINDING_STACK_START) {
+    } else if (addr > CONTROL_STACK_TOP && addr < (os_vm_address_t)binding_stack) {
 	fprintf(stderr, "Possible stack overflow at 0x%08lX!\n", addr);
 	/* try to fix control frame pointer */
-	while (!(CONTROL_STACK_START <= *current_control_frame_pointer &&
+	while (!((lispobj)control_stack <= *current_control_frame_pointer &&
 		 *current_control_frame_pointer <= CONTROL_STACK_TOP))
 	    ((char *) current_control_frame_pointer) -= sizeof(lispobj);
 	ldb_monitor();
diff --git a/src/lisp/NetBSD-os.c b/src/lisp/NetBSD-os.c
index 6957ab1a670ecc4391f53e190d1c298bb7617e57..5c5a8bf5101567ef75e9490b1432cf53750c366c 100644
--- a/src/lisp/NetBSD-os.c
+++ b/src/lisp/NetBSD-os.c
@@ -277,8 +277,8 @@ valid_addr(os_vm_address_t addr)
 #ifndef GENCGC
 	|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
 #endif
-	|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
-	|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
+	|| in_range_p(addr, control_stack, control_stack_size)
+	|| in_range_p(addr, binding_stack, binding_stack_size))
 	return TRUE;
     return FALSE;
 }
diff --git a/src/lisp/backtrace.c b/src/lisp/backtrace.c
index 871b692f5f72b98c7bfd846ef307c9d38f250e77..5e6ff9a6351523d3e55e5cf160713e9fd65f6317 100644
--- a/src/lisp/backtrace.c
+++ b/src/lisp/backtrace.c
@@ -252,7 +252,7 @@ backtrace(int nframes)
 static int
 stack_pointer_p(unsigned long p)
 {
-    return (p < CONTROL_STACK_START + control_stack_size
+    return ((void *)p < (void *)control_stack + control_stack_size
 	    && p > (unsigned long) &p && (p & 3) == 0);
 }
 
diff --git a/src/lisp/gencgc.c b/src/lisp/gencgc.c
index cc071dda8bafb3d37846bb656ed3a7edea9b3703..7f45d71181b263bcdff59e10638d4cec07430eac 100644
--- a/src/lisp/gencgc.c
+++ b/src/lisp/gencgc.c
@@ -166,7 +166,7 @@ check_escaped_stack_object(lispobj * where, lispobj obj)
 
     if (Pointerp(obj)
 	&& (p = (void *) PTR(obj),
-	    (p >= (void *) CONTROL_STACK_START
+	    (p >= (void *) control_stack
 	     && p < (void *) control_stack_end))) {
 	char *space;
 
@@ -195,7 +195,7 @@ check_escaped_stack_object(lispobj * where, lispobj obj)
 	    lose("Escaped stack-allocated object 0x%08lx at %p in %s\n",
 		 (unsigned long) obj, where, space);
 #ifndef i386
-	else if ((where >= (lispobj *) CONTROL_STACK_START
+	else if ((where >= (lispobj *) control_stack
 		  && where < (lispobj *) (control_stack_end))
 		 || (space == NULL)) {
 	    /* Do nothing if it the reference is from the control stack,
@@ -2136,17 +2136,19 @@ read_only_space_p(lispobj obj)
 static inline boolean
 control_stack_space_p(lispobj obj)
 {
-    lispobj end = CONTROL_STACK_START + control_stack_size;
+    char *object = (char *) obj;
+    char *end = (char *)control_stack + control_stack_size;
 
-    return (obj >= CONTROL_STACK_START) && (obj < end);
+    return (object >= (char *) control_stack) && (object < end);
 }
 
 static inline boolean
 binding_stack_space_p(lispobj obj)
 {
-    lispobj end = BINDING_STACK_START + binding_stack_size;
+    char *object = (char *) obj;
+    char *end = (char *)binding_stack + binding_stack_size;
 
-    return (obj >= BINDING_STACK_START) && (obj < end);
+    return (object >= (char *) binding_stack) && (object < end);
 }
     
 static inline boolean
@@ -2157,7 +2159,12 @@ signal_space_p(lispobj obj)
 
     return (obj >= SIGNAL_STACK_START) && (obj < end);
 #else
-    return FALSE;
+    extern char altstack[];
+    
+    char* object = (char*) obj;
+    char* end = altstack + SIGNAL_STACK_SIZE;
+    
+    return (object >= altstack && object < end);
 #endif    
 }
 
@@ -7322,11 +7329,11 @@ verify_gc(void)
     int static_space_size = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER)
 	- (lispobj *) static_space;
     int binding_stack_size = (lispobj *) get_binding_stack_pointer()
-	- (lispobj *) BINDING_STACK_START;
+	- (lispobj *) binding_stack;
 
     verify_space((lispobj *) READ_ONLY_SPACE_START, read_only_space_size);
     verify_space((lispobj *) static_space, static_space_size);
-    verify_space((lispobj *) BINDING_STACK_START, binding_stack_size);
+    verify_space((lispobj *) binding_stack, binding_stack_size);
     verify_space((lispobj *) (void *) &scavenger_hooks, 1);
 }
 
@@ -7494,16 +7501,16 @@ scavenge_interrupt_handlers(void)
 static void
 scavenge_control_stack(void)
 {
-    unsigned long control_stack_size;
+    unsigned long current_stack_size;
 
-    control_stack_size = current_control_stack_pointer - control_stack;
+    current_stack_size = current_control_stack_pointer - control_stack;
 
 #ifdef PRINTNOISE
     printf("Scavenging the control stack (%d bytes) ...\n",
-	   control_stack_size * sizeof(lispobj));
+	   current_stack_size * sizeof(lispobj));
 #endif
 
-    scavenge(control_stack, control_stack_size);
+    scavenge(control_stack, current_stack_size);
 
 #ifdef PRINTNOISE
     printf("Done scavenging the control stack.\n");
@@ -7523,7 +7530,7 @@ garbage_collect_generation(int generation, int raise)
 
 #ifdef GC_ASSERTIONS
 #if defined(i386) || defined(__x86_64)
-    invalid_stack_start = (void *) CONTROL_STACK_START;
+    invalid_stack_start = (void *) control_stack;
     invalid_stack_end = (void *) &raise;
 #else /* not i386 */
     invalid_stack_start = (void *) &raise;
diff --git a/src/lisp/globals.c b/src/lisp/globals.c
index 18b4556c83491b2d799647c4a73f40ad4781d41e..7347070a12805b942e809649fd7717425188ea68 100644
--- a/src/lisp/globals.c
+++ b/src/lisp/globals.c
@@ -28,7 +28,6 @@ lispobj *dynamic_1_space;
 unsigned dynamic_space_size;
 lispobj *control_stack;
 
-
 #if (defined(i386) || defined(__x86_64))
 lispobj *control_stack_end;
 #endif
diff --git a/src/lisp/interrupt.c b/src/lisp/interrupt.c
index 406ae48303964b567ca5d9efb7836a85ed10639c..937ffa714e1466ec84d1f139536c851e80cad7a2 100644
--- a/src/lisp/interrupt.c
+++ b/src/lisp/interrupt.c
@@ -405,10 +405,7 @@ interrupt_maybe_gc(HANDLER_ARGS)
 * Noise to install handlers.                                     *
 \****************************************************************/
 
-#if !(defined(i386) || defined(__x86_64))
-#define SIGNAL_STACK_SIZE SIGSTKSZ
-static char altstack[SIGNAL_STACK_SIZE];
-#endif
+char altstack[SIGNAL_STACK_SIZE];
 
 void
 interrupt_install_low_level_handler(int signal, void handler(HANDLER_ARGS))
@@ -431,7 +428,7 @@ interrupt_install_low_level_handler(int signal, void handler(HANDLER_ARGS))
     if (signal == PROTECTION_VIOLATION_SIGNAL) {
 	stack_t sigstack;
 
-#if (defined( i386 ) || defined(__x86_64))
+#if defined(SIGNAL_STACK_START)
 	sigstack.ss_sp = (void *) SIGNAL_STACK_START;
 #else
 	sigstack.ss_sp = (void *) altstack;
diff --git a/src/lisp/lisp.c b/src/lisp/lisp.c
index c07a1d6ead55a44408773ad6b684d3ffd37a33de..bd81fdafa9b2c6e12f0684e00fa306007d828535 100644
--- a/src/lisp/lisp.c
+++ b/src/lisp/lisp.c
@@ -687,8 +687,16 @@ main(int argc, const char *argv[], const char *envp[])
     if (builtin_image_flag != 0)
 	map_core_sections(argv[0]);
 #endif
+
+    /*
+     * Validate the basic lisp spaces first like the heap and static
+     * and read-only spaces.  Do this so that the stacks (if thy're
+     * relocatable) don't get randomly allocated on top of our desired
+     * lisp spaces.
+     */
     validate();
     gc_init();
+    validate_stacks();
 
     /* This is the first use of malloc() and must come after the
      * static memory layout is mmapped to avoid conflicts with possible
diff --git a/src/lisp/os-common.c b/src/lisp/os-common.c
index ab82d3688167068d5bd40254eeed8af66d6d4eb9..5c8462a6311887f716a04d5c0baa0bf8370982d1 100755
--- a/src/lisp/os-common.c
+++ b/src/lisp/os-common.c
@@ -413,7 +413,7 @@ guard_zones(char **yellow_start, char **red_start)
     /*
      * All x86's have a control stack (aka C stack) that grows down.
      */
-    char *end = (char *) CONTROL_STACK_START;
+    char *end = (char *) control_stack;
 
     *red_start = end;
     *yellow_start = *red_start + RED_ZONE_SIZE;
@@ -424,7 +424,7 @@ guard_zones(char **yellow_start, char **red_start)
      * control stack area.
      */
 
-    char *end = (char *) CONTROL_STACK_START + control_stack_size;
+    char *end = (char *) control_stack + control_stack_size;
 
     *red_start = end - RED_ZONE_SIZE;
     *yellow_start = *red_start - YELLOW_ZONE_SIZE;
diff --git a/src/lisp/ppc-validate.h b/src/lisp/ppc-validate.h
index 40530f79e68817e3e247941f012a987444d5539e..2eb6029f49cb7af278f5ebf5969ada250f651684 100644
--- a/src/lisp/ppc-validate.h
+++ b/src/lisp/ppc-validate.h
@@ -45,6 +45,8 @@
 #define CONTROL_STACK_SIZE  	(0x07ff8000)	/* 128 MB, almost */
 #define CONTROL_STACK_END       (CONTROL_STACK_START + control_stack_size)
 
+#define SIGNAL_STACK_SIZE	SIGSTKSZ
+
 #define BINDING_STACK_START 	(0x38000000)
 #define BINDING_STACK_SIZE  	(0x07ff8000)	/* 128 MB, almost */
 
diff --git a/src/lisp/save.c b/src/lisp/save.c
index 640dccd79294072796c254f14a9768674abc96cc..3fcbfd4b298f0a26bc2e5588afc0f2295fc2404a 100644
--- a/src/lisp/save.c
+++ b/src/lisp/save.c
@@ -136,7 +136,9 @@ save(char *filename, lispobj init_function, int sse2_mode)
     }
     printf("[Undoing binding stack... ");
     fflush(stdout);
-    unbind_to_here((lispobj *) BINDING_STACK_START);
+
+    unbind_to_here((lispobj *) binding_stack);
+
     SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
     SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
     SetSymbolValue(EVAL_STACK_TOP, 0);
@@ -278,7 +280,9 @@ save_executable(char *filename, lispobj init_function)
 
     printf("[Undoing binding stack... ");
     fflush(stdout);
-    unbind_to_here((lispobj *)BINDING_STACK_START);
+
+    unbind_to_here((lispobj *)binding_stack);
+
     SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
     SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
     SetSymbolValue(EVAL_STACK_TOP, 0);
diff --git a/src/lisp/solaris-os.c b/src/lisp/solaris-os.c
index e3647f7e05bb8b87c89a9ce895e6d37f02d34e1f..6e993387e2889e4818d911cd2aaaa8a12831d21e 100644
--- a/src/lisp/solaris-os.c
+++ b/src/lisp/solaris-os.c
@@ -169,8 +169,14 @@ os_flush_icache(os_vm_address_t address, os_vm_size_t length)
 void
 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
 {
-    if (mprotect((void *) address, length, prot) == -1)
-	perror("mprotect");
+    if (mprotect((void *) address, length, prot) == -1) {
+        char msg[1000];
+
+        snprintf(msg, sizeof(msg), "mprotect: os_protect(0x%p, %u, 0x%x): ",
+                 address, length, prot);
+        
+	perror(msg);
+    }
 }
 
 static boolean
@@ -193,8 +199,8 @@ boolean valid_addr(os_vm_address_t addr)
 #ifndef GENCGC
 	    || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
 #endif
-	    || in_range_p(addr, CONTROL_STACK_START, control_stack_size)
-	    || in_range_p(addr, BINDING_STACK_START, binding_stack_size));
+	    || in_range_p(addr, (lispobj)control_stack, control_stack_size)
+	    || in_range_p(addr, (lispobj)binding_stack, binding_stack_size));
 }
 
 /* ---------------------------------------------------------------- */
@@ -403,11 +409,16 @@ os_vm_address_t round_up_sparse_size(os_vm_address_t addr)
 /*
  * An array of the start of the spaces which should have holes placed
  * after them.  Must not include the dynamic spaces because the size
- * of the dynamic space can be controlled from the command line.
+ * of the dynamic space can be controlled from the command line.  Also
+ * must not include the binding and control stacks.  They're handled
+ * below.
  */
 static os_vm_address_t spaces[] = {
     READ_ONLY_SPACE_START, STATIC_SPACE_START,
-    BINDING_STACK_START, CONTROL_STACK_START
+#ifndef RELOCATABLE_STACK_START
+    BINDING_STACK_START,
+    CONTROL_STACK_START
+#endif    
 };
 
 /*
@@ -430,27 +441,41 @@ static unsigned long *space_size[] = {
 #define HOLE_SIZE 0x2000
 
 void
-make_holes(void)
+make_hole(os_vm_address_t space_start, size_t space_size)
 {
-    int k;
     os_vm_address_t hole;
 
     /* Make holes of the appropriate size for desired spaces */
 
-    for (k = 0; k < sizeof(spaces) / sizeof(spaces[0]); ++k) {
-
-	hole = spaces[k] + *space_size[k];
+    hole = space_start + space_size;
 
-	if (os_validate(hole, HOLE_SIZE) == NULL) {
-	    fprintf(stderr,
-		    "ensure_space: Failed to validate hole of %d bytes at 0x%08lX\n",
-		    HOLE_SIZE, (unsigned long) hole);
-	    exit(1);
-	}
-	/* Make it inaccessible */
-	os_protect(hole, HOLE_SIZE, 0);
+    if (os_validate(hole, HOLE_SIZE) == NULL) {
+        fprintf(stderr,
+                "ensure_space: Failed to validate hole of %d bytes at 0x%08lX\n",
+                HOLE_SIZE, (unsigned long) hole);
+        exit(1);
     }
+    /* Make it inaccessible */
+    os_protect(hole, HOLE_SIZE, 0);
+}
+
+void
+make_holes(void)
+{
+    int k;
+    os_vm_address_t hole;
+
+    /*
+     * Make holes of the appropriate size for desired spaces.  The
+     * stacks are handled in make_stack_holes, if they are
+     * relocatable.
+     */
 
+    for (k = 0; k < sizeof(spaces) / sizeof(spaces[0]); ++k) {
+        make_hole(spaces[k], *space_size[k]);
+    }
+    
+    
     /* Round up the dynamic_space_size to the nearest SPARSE_BLOCK_SIZE */
     dynamic_space_size = round_up_sparse_size(dynamic_space_size);
 
@@ -477,6 +502,15 @@ make_holes(void)
 #endif
 }
 
+void
+make_stack_holes(void)
+{
+#ifdef RELOCATABLE_STACK_START
+    make_hole((os_vm_address_t)control_stack, control_stack_size);
+    make_hole((os_vm_address_t)binding_stack, binding_stack_size);
+#endif
+}
+    
 void *
 os_dlsym(const char *sym_name, lispobj lib_list)
 {
diff --git a/src/lisp/sparc-validate.h b/src/lisp/sparc-validate.h
index 0a6a6cea1aa6536b6f44bace0484d7b33452beef..2d34285c4a0ce91787f3b6b0375ddc60b98182c5 100644
--- a/src/lisp/sparc-validate.h
+++ b/src/lisp/sparc-validate.h
@@ -92,15 +92,24 @@
 #define READ_ONLY_SPACE_START	(SpaceStart_TargetReadOnly)
 #define READ_ONLY_SPACE_SIZE	((2*MB_128) - SPARSE_BLOCK_SIZE)	/* 256 MB - 32 KB, 256 MB max */
 
+#ifndef RELOCATABLE_STACK_START
 #define BINDING_STACK_START 	(0x20000000)
+#endif
+
 #define BINDING_STACK_SIZE  	(MB_128 - SPARSE_BLOCK_SIZE)	/* 128 MB - 32 KB, 128 MB max */
 
 #define STATIC_SPACE_START  	(SpaceStart_TargetStatic)
 #define STATIC_SPACE_SIZE   	((2*MB_128) - SPARSE_BLOCK_SIZE)	/* 256 MB - 32 KB, 256 MB max */
 
+#ifndef RELOCATABLE_STACK_START
 #define CONTROL_STACK_START 	(0x38000000)
+#endif
 #define CONTROL_STACK_SIZE  	(MB_128 - SPARSE_BLOCK_SIZE)	/* 128 MB - 32 KB, 128 MB max */
+#if 0
 #define CONTROL_STACK_END       (CONTROL_STACK_START + control_stack_size)
+#endif
+
+#define SIGNAL_STACK_SIZE	SIGSTKSZ
 
 #define DYNAMIC_0_SPACE_START	(SpaceStart_TargetDynamic)
 
diff --git a/src/lisp/validate.c b/src/lisp/validate.c
index 7872a12ceb2d1cfc860c9c447a4901409e6d292a..d0474b50b49a8953975912d0d6e43d42237440bd 100644
--- a/src/lisp/validate.c
+++ b/src/lisp/validate.c
@@ -18,6 +18,7 @@
 
 #ifdef sparc
 extern void make_holes(void);
+extern void make_stack_holes(void);
 #endif
 
 static void
@@ -92,20 +93,10 @@ validate(void)
     */
 #endif
 
-    /* Control Stack */
-    control_stack = (lispobj *) CONTROL_STACK_START;
-#if (defined(i386) || defined(__x86_64))
-    control_stack_end = (lispobj *) (CONTROL_STACK_START + control_stack_size);
-#endif
-    ensure_space(control_stack, control_stack_size);
-
 #ifdef SIGNAL_STACK_START
     ensure_space((lispobj *) SIGNAL_STACK_START, SIGNAL_STACK_SIZE);
 #endif
 
-    /* Binding Stack */
-    binding_stack = (lispobj *) BINDING_STACK_START;
-    ensure_space(binding_stack, binding_stack_size);
 #ifdef LINKAGE_TABLE
     ensure_space((lispobj *) FOREIGN_LINKAGE_SPACE_START,
 		 FOREIGN_LINKAGE_SPACE_SIZE);
@@ -118,6 +109,40 @@ validate(void)
     printf(" done.\n");
 #endif
 
+}
+
+void
+validate_stacks()
+{
+    /* Control Stack */
+#ifdef CONTROL_STACK_START
+    /* Map the control stack at a fixed location */
+    control_stack = (lispobj *) CONTROL_STACK_START;
+#if (defined(i386) || defined(__x86_64))
+    control_stack_end = (lispobj *) (CONTROL_STACK_START + control_stack_size);
+#endif
+    ensure_space(control_stack, control_stack_size);
+#else
+    /* Map the conrol stack wherever we have space */
+    control_stack = (lispobj*) os_validate(NULL, control_stack_size);
+
+#if (defined(i386) || defined(__x86_64))
+    control_stack_end = (void*)control_stack + control_stack_size;
+#endif
+#endif
+
+    /* Binding Stack */
+#ifdef BINDING_STACK_START
+    binding_stack = (lispobj *) BINDING_STACK_START;
+    ensure_space(binding_stack, binding_stack_size);
+#else
+    /* Map the binding stack wherever we have space */
+    binding_stack = (lispobj*) os_validate(NULL, binding_stack_size);
+#endif
+#ifdef sparc
+    make_stack_holes();
+#endif
+
 #ifdef RED_ZONE_HIT
     os_guard_control_stack(0, 1);
 #endif
diff --git a/src/lisp/validate.h b/src/lisp/validate.h
index 784258e3efb705222155fee8c4dd208298744624..7f1c0e0c70a129825b17c62ce8dba895f8e4e59e 100644
--- a/src/lisp/validate.h
+++ b/src/lisp/validate.h
@@ -37,5 +37,6 @@
 #endif
 
 extern void validate(void);
+extern void validate_stacks(void);
 
 #endif /* _VALIDATE_H_ */
diff --git a/src/lisp/x86-assem.S b/src/lisp/x86-assem.S
index 3ab41d69f158adc7603e0928f7c5b8bbff720881..b7aa7f183ecb804d5b00563ef53cbd6172952cba 100644
--- a/src/lisp/x86-assem.S
+++ b/src/lisp/x86-assem.S
@@ -143,7 +143,8 @@ FUNCDEF(call_into_lisp)
 	movl	%eax, GNAME(foreign_function_call_active)
 
 	movl	%esp,%ebx	# remember current stack
-	cmpl	$CONTROL_STACK_START,%esp
+	cmpl	GNAME(control_stack), %esp
+
 	jbe	ChangeToLispStack
 	cmpl	GNAME(control_stack_end), %esp
 	jbe	OnLispStack
diff --git a/src/lisp/x86-validate-darwin.h b/src/lisp/x86-validate-darwin.h
index 53166e84490afaa1da524cdca64bf7b154b0e362..1ac37f3d0b1a16dd4a4c699352485e3e1e47bda4 100644
--- a/src/lisp/x86-validate-darwin.h
+++ b/src/lisp/x86-validate-darwin.h
@@ -18,10 +18,14 @@
 #define STATIC_SPACE_START	(SpaceStart_TargetStatic)
 #define STATIC_SPACE_SIZE	(0x0ffff000)	/* 256MB - 1 page */
 
+#ifndef RELOCATABLE_STACK_START
 #define BINDING_STACK_START	(0x38000000)
+#endif
 #define BINDING_STACK_SIZE	(0x07fff000)	/* 128MB - 1 page */
 
+#ifdef RELOCATABLE_STACK_START
 #define CONTROL_STACK_START	(0x40000000)
+#endif
 
 /*
  * According to /usr/include/sys/signal.h, MINSIGSTKSZ is 32K and
@@ -29,7 +33,9 @@
  */
 #define CONTROL_STACK_SIZE	(0x07fdf000)	/* 128MB - SIGSTKSZ - 1 page */
 
+#ifndef RELOCATABLE_STACK_START
 #define SIGNAL_STACK_START	(0x47fe0000)    /* One page past the end of the control stack */
+#endif
 #define SIGNAL_STACK_SIZE	SIGSTKSZ
 
 #define DYNAMIC_0_SPACE_START	(SpaceStart_TargetDynamic)
diff --git a/src/lisp/x86-validate-linux.h b/src/lisp/x86-validate-linux.h
index 032d7aab14750771d55eb4b4e9bc35e026070393..7b22a1aaaa7cd2743f694a78bcdea3ed1ba3b9ec 100644
--- a/src/lisp/x86-validate-linux.h
+++ b/src/lisp/x86-validate-linux.h
@@ -45,13 +45,19 @@
 #define STATIC_SPACE_START	(SpaceStart_TargetStatic)
 #define STATIC_SPACE_SIZE	(0x0ffff000)	/* 256MB - 1 page */
 
+#ifndef RELOCATABLE_STACK_START
 #define BINDING_STACK_START	(0x20000000)
+#endif
 #define BINDING_STACK_SIZE	(0x07fff000)	/* 128MB - 1 page */
 
+#ifndef RELOCATABLE_STACK_START
 #define CONTROL_STACK_START	0x38000000
+#endif
 #define CONTROL_STACK_SIZE	(0x07fff000 - 8192)
 
+#ifndef RELOCATABLE_STACK_START
 #define SIGNAL_STACK_START	CONTROL_STACK_END
+#endif
 #define SIGNAL_STACK_SIZE	SIGSTKSZ
 
 #define DYNAMIC_0_SPACE_START	(SpaceStart_TargetDynamic)