diff --git a/src/code/amd64.c b/src/code/amd64.c
index e883c8273c42600be766c4f3b626179a26be48d0..71368ed8fc8e9a6578ae492cd9110ee480092da7 100644
--- a/src/code/amd64.c
+++ b/src/code/amd64.c
@@ -45,6 +45,15 @@
 #define REG_R14 MISSING_P_
 #define REG_R15 MISSING_P_
 
+struct soff { int off; int type; int value; };
+
+static struct soff SVAL(int i)
+{
+  struct soff res;
+  res.off = res.type = i*sizeof(struct svalue);
+  res.value = res.type + 8;
+  return res;
+}
 
 /* Register encodings */
 enum amd64_reg {P_REG_RAX = 0, P_REG_RBX = 3, P_REG_RCX = 1, P_REG_RDX = 2,
@@ -214,6 +223,13 @@ static void mov_reg_reg(enum amd64_reg from_reg, enum amd64_reg to_reg )
   modrm( 3, from_reg, to_reg );
 }
 
+static void mov_reg32_reg(enum amd64_reg from_reg, enum amd64_reg to_reg )
+{
+  rex( 0, from_reg, 0, to_reg );
+  opcode( 0x89 );
+  modrm( 3, from_reg, to_reg );
+}
+
 #define PUSH_INT(X) ins_int((INT32)(X), (void (*)(char))add_to_program)
 static void low_mov_mem_reg(enum amd64_reg from_reg, ptrdiff_t offset,
                             enum amd64_reg to_reg)
@@ -1078,7 +1094,7 @@ static void amd64_load_mark_sp_reg(void)
 
 static void mov_sval_type(enum amd64_reg src, enum amd64_reg dst )
 {
-  mov_mem8_reg( src, OFFSETOF(svalue, tu.t.type), dst);
+  mov_mem8_reg( src, SVAL(0).type, dst);
 /*  and_reg32_imm( dst, 0x1f );*/
 }
 
@@ -1118,7 +1134,7 @@ static void update_arg2(INT32 value)
 static void amd64_add_sp( int num )
 {
   amd64_load_sp_reg();
-  add_reg_imm( sp_reg, sizeof(struct svalue)*num);
+  add_reg_imm( sp_reg, num * sizeof(struct svalue));
   dirty_regs |= 1 << PIKE_SP_REG;
   flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this  */
 }
@@ -1126,7 +1142,7 @@ static void amd64_add_sp( int num )
 static void amd64_add_mark_sp( int num )
 {
   amd64_load_mark_sp_reg();
-  add_reg_imm( mark_sp_reg, sizeof(struct svalue*)*num);
+  add_reg_imm( mark_sp_reg, num * sizeof(struct svalue*));
   dirty_regs |= 1 << PIKE_MARK_SP_REG;
   flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */
 }
@@ -1140,10 +1156,8 @@ static void amd64_push_svaluep_to(int reg, int spoff)
   amd64_load_sp_reg();
   mov_mem_reg(reg, OFFSETOF(svalue, tu.t.type), P_REG_RAX);
   mov_mem_reg(reg, OFFSETOF(svalue, u.refs), P_REG_RCX);
-  mov_reg_mem(P_REG_RAX, sp_reg,
-	      spoff*sizeof(struct svalue)+OFFSETOF(svalue, tu.t.type));
-  mov_reg_mem(P_REG_RCX, sp_reg,
-	      spoff*sizeof(struct svalue)+OFFSETOF(svalue, u.refs));
+  mov_reg_mem(P_REG_RAX, sp_reg, SVAL(spoff).type);
+  mov_reg_mem(P_REG_RCX, sp_reg, SVAL(spoff).value);
   and_reg32_imm(P_REG_RAX, MIN_REF_TYPE);
   jz(&label_A);
   add_imm_mem( 1, P_REG_RCX, OFFSETOF(pike_string, refs));
@@ -1159,8 +1173,8 @@ static void amd64_push_svaluep(int reg)
 static void amd64_push_int(INT64 value, int subtype)
 {
   amd64_load_sp_reg();
-  mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, OFFSETOF(svalue, tu.t.type));
-  mov_imm_mem(value, sp_reg, OFFSETOF(svalue, u.integer));
+  mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, SVAL(0).type);
+  mov_imm_mem(value, sp_reg, SVAL(0).value);
   amd64_add_sp( 1 );
 }
 
@@ -1211,19 +1225,18 @@ static void amd64_call_c_function(void *addr)
   call_imm(addr);
 }
 
-static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )
+static void amd64_free_svalue_off(enum amd64_reg src, int off, int guaranteed_ref )
 {
   LABELS();
   if( src == P_REG_RAX )
     Pike_fatal("Clobbering RAX for free-svalue\n");
     /* load type -> RAX */
-  mov_sval_type( src, P_REG_RAX );
-
+  mov_mem8_reg( src, off, P_REG_RAX );
   and_reg_imm(P_REG_RAX, MIN_REF_TYPE);
   jz( &label_A );
 
   /* Load pointer to refs -> RAX */
-  mov_mem_reg( src, OFFSETOF(svalue, u.refs), P_REG_RAX);
+  mov_mem_reg( src,off+OFFSETOF(svalue, u.refs), P_REG_RAX);
    /* if( !--*RAX ) */
   add_mem32_imm( P_REG_RAX, OFFSETOF(pike_string,refs),  -1);
   if( !guaranteed_ref )
@@ -1231,13 +1244,17 @@ static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )
     /* We need to see if refs got to 0. */
     jnz( &label_A );
     /* if so, call really_free_svalue */
-    if( src != ARG1_REG )
-      mov_reg_reg( src, ARG1_REG );
+    add_reg_imm_reg( src, off, ARG1_REG );
     amd64_call_c_function(really_free_svalue);
   }
   LABEL_A;
 }
 
+static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )
+{
+  amd64_free_svalue_off(src,0,guaranteed_ref);
+}
+
 /* Type already in register. Note: Clobbers the type register. */
 static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type,
                                    int guaranteed_ref )
@@ -1536,6 +1553,16 @@ static void amd64_ins_branch_check_threads_etc(int code_only)
 
 void amd64_init_interpreter_state(void)
 {
+#ifdef PIKE_DEBUG
+  if( PIKE_T_INT != 0 )
+    Pike_fatal("assumption failed: pike_t_int == 0\n");
+  if( sizeof(struct svalue) != 16 )
+    Pike_fatal("assumption failed: sizeof svalue != 16\n");
+  if( OFFSETOF(svalue,tu.t.type) != 0 )
+    Pike_fatal("assumption failed: offsetof(svalue.tu.t.type) != 0\n");
+  if( OFFSETOF(svalue,u.integer) != 8 )
+    Pike_fatal("assumption failed: offsetof(svalue.u.integer) != 8\n");
+#endif
   instrs[F_CATCH - F_OFFSET].address = inter_return_opcode_F_CATCH;
 }
 
@@ -1925,6 +1952,27 @@ void ins_f_byte(unsigned int b)
       rel_addr = PIKE_PC;
     }
     break;
+
+    /* sp-1 = undefinedp(sp-1) */
+  case F_UNDEFINEDP:
+    {
+    LABELS();
+    ins_debug_instr_prologue(b, 0, 0);
+    amd64_load_sp_reg();
+
+    mov_mem32_reg( sp_reg, SVAL(-1).type, P_REG_RAX );
+    cmp_reg32_imm( P_REG_RAX, 1<<16 | PIKE_T_INT );
+    jne( &label_A );
+    mov_imm_mem( 1, sp_reg,SVAL(-1).value);
+    jmp( &label_B );
+  LABEL_A;
+    amd64_free_svalue_off( sp_reg, SVAL(-1).off,0 );
+    mov_imm_mem( 0, sp_reg,SVAL(-1).value);
+  LABEL_B;
+    mov_imm_mem( PIKE_T_INT, sp_reg,SVAL(-1).type);
+    }
+    return;
+
   case F_ZERO_TYPE:
     {
       LABELS();
@@ -1932,8 +1980,8 @@ void ins_f_byte(unsigned int b)
       amd64_load_sp_reg();
       mov_mem32_reg( sp_reg, -sizeof(struct svalue), P_REG_RAX );
       /* Rax now has type + subtype. */
-      mov_reg_reg( P_REG_RAX, P_REG_RBX );
-      and_reg_imm( P_REG_RAX, 0x1f );
+      mov_reg32_reg( P_REG_RAX, P_REG_RBX );
+      and_reg32_imm( P_REG_RAX, 0x1f );
       cmp_reg32_imm( P_REG_RAX, PIKE_T_INT );
       jne( &label_A );
       /* It is an integer. */
@@ -2101,7 +2149,7 @@ void ins_f_byte(unsigned int b)
     amd64_load_fp_reg();
     /* Note: really mem16, but we & with PIKE_FRAME_RETURN_INTERNAL anyway */
     mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX );
-    and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL);
+    and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL);
     jnz( &label_A );
     /* So, it is just a normal return. */
     LABEL_B;
@@ -2112,7 +2160,7 @@ void ins_f_byte(unsigned int b)
     LABEL_A;
     /* We should jump to the given address. */
     mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX );
-    and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP );
+    and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP );
     jnz( &label_C );
     amd64_call_c_function( low_return );
     jmp( &label_D );
@@ -2136,7 +2184,7 @@ void ins_f_byte(unsigned int b)
     /* NB: We only care about subtype 1! */
     cmp_reg32_imm(P_REG_RAX, (1<<16)|PIKE_T_STRING);
     jne(&label_A);
-    and_reg_imm(P_REG_RAX, 0x1f);
+    and_reg32_imm(P_REG_RAX, 0x1f);
     mov_reg_mem32(P_REG_RAX,
 		  sp_reg, OFFSETOF(svalue, tu.t.type) - sizeof(struct svalue));
     LABEL_A;