diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs
index 789723af1b1..db6308c10dc 100644
--- a/src/librustrt/libunwind.rs
+++ b/src/librustrt/libunwind.rs
@@ -60,7 +60,7 @@ pub type _Unwind_Word = libc::uintptr_t;
 pub static unwinder_private_data_size: uint = 5;
 
 #[cfg(target_arch = "x86_64")]
-pub static unwinder_private_data_size: uint = 2;
+pub static unwinder_private_data_size: uint = 6;
 
 #[cfg(target_arch = "arm", not(target_os = "ios"))]
 pub static unwinder_private_data_size: uint = 20;
diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs
index 52b02479f7f..9c62936ef9a 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -227,7 +227,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 //   This is achieved by overriding the return value in search phase to always
 //   say "catch!".
 
-#[cfg(not(target_arch = "arm"), not(test))]
+#[cfg(not(target_arch = "arm"), not(windows, target_arch = "x86_64"), not(test))]
 #[doc(hidden)]
 #[allow(visible_private_types)]
 pub mod eabi {
@@ -244,7 +244,8 @@ pub mod eabi {
     }
 
     #[lang="eh_personality"]
-    extern fn eh_personality(
+    #[no_mangle] // referenced from rust_try.ll
+    extern fn rust_eh_personality(
         version: c_int,
         actions: uw::_Unwind_Action,
         exception_class: uw::_Unwind_Exception_Class,
@@ -260,21 +261,19 @@ pub mod eabi {
 
     #[no_mangle] // referenced from rust_try.ll
     pub extern "C" fn rust_eh_personality_catch(
-        version: c_int,
+        _version: c_int,
         actions: uw::_Unwind_Action,
-        exception_class: uw::_Unwind_Exception_Class,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
     ) -> uw::_Unwind_Reason_Code
     {
+
         if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
             uw::_URC_HANDLER_FOUND // catch!
         }
         else { // cleanup phase
-            unsafe {
-                __gcc_personality_v0(version, actions, exception_class, ue_header,
-                                     context)
-            }
+            uw::_URC_INSTALL_CONTEXT
         }
     }
 }
@@ -299,7 +298,7 @@ pub mod eabi {
     }
 
     #[lang="eh_personality"]
-    #[no_mangle] // so we can reference it by name from middle/trans/base.rs
+    #[no_mangle] // referenced from rust_try.ll
     pub extern "C" fn rust_eh_personality(
         version: c_int,
         actions: uw::_Unwind_Action,
@@ -316,21 +315,18 @@ pub mod eabi {
 
     #[no_mangle] // referenced from rust_try.ll
     pub extern "C" fn rust_eh_personality_catch(
-        version: c_int,
+        _version: c_int,
         actions: uw::_Unwind_Action,
-        exception_class: uw::_Unwind_Exception_Class,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
     ) -> uw::_Unwind_Reason_Code
     {
         if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
             uw::_URC_HANDLER_FOUND // catch!
         }
         else { // cleanup phase
-            unsafe {
-                __gcc_personality_sj0(version, actions, exception_class, ue_header,
-                                      context)
-            }
+            uw::_URC_INSTALL_CONTEXT
         }
     }
 }
@@ -338,7 +334,7 @@ pub mod eabi {
 
 // ARM EHABI uses a slightly different personality routine signature,
 // but otherwise works the same.
-#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))]
+#[cfg(target_arch = "arm", not(target_os = "ios", not(test)))]
 #[allow(visible_private_types)]
 pub mod eabi {
     use uw = libunwind;
@@ -352,7 +348,8 @@ pub mod eabi {
     }
 
     #[lang="eh_personality"]
-    extern "C" fn eh_personality(
+    #[no_mangle] // referenced from rust_try.ll
+    extern "C" fn rust_eh_personality(
         state: uw::_Unwind_State,
         ue_header: *mut uw::_Unwind_Exception,
         context: *mut uw::_Unwind_Context
@@ -366,8 +363,8 @@ pub mod eabi {
     #[no_mangle] // referenced from rust_try.ll
     pub extern "C" fn rust_eh_personality_catch(
         state: uw::_Unwind_State,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
     ) -> uw::_Unwind_Reason_Code
     {
         if (state as c_int & uw::_US_ACTION_MASK as c_int)
@@ -375,9 +372,107 @@ pub mod eabi {
             uw::_URC_HANDLER_FOUND // catch!
         }
         else { // cleanup phase
-            unsafe {
-                __gcc_personality_v0(state, ue_header, context)
+            uw::_URC_INSTALL_CONTEXT
+        }
+    }
+}
+
+// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx)
+//
+// This looks a bit convoluted because rather than implementing a native SEH handler,
+// GCC reuses the same personality routine as for the other architectures by wrapping it
+// with an "API translator" layer (_GCC_specific_handler).
+
+#[cfg(windows, target_arch = "x86_64", not(test))]
+#[allow(visible_private_types)]
+#[allow(non_camel_case_types)]
+#[allow(unused_variable)]
+#[allow(uppercase_variables)]
+pub mod eabi {
+    use uw = libunwind;
+    use libc::{c_void, c_int};
+
+    struct EXCEPTION_RECORD;
+    struct CONTEXT;
+    struct DISPATCHER_CONTEXT;
+
+    #[repr(C)]
+    enum EXCEPTION_DISPOSITION {
+        ExceptionContinueExecution,
+        ExceptionContinueSearch,
+        ExceptionNestedException,
+        ExceptionCollidedUnwind
+    }
+
+    type _Unwind_Personality_Fn =
+        extern "C" fn(
+            version: c_int,
+            actions: uw::_Unwind_Action,
+            exception_class: uw::_Unwind_Exception_Class,
+            ue_header: *mut uw::_Unwind_Exception,
+            context: *mut uw::_Unwind_Context
+        ) -> uw::_Unwind_Reason_Code;
+
+    extern "C" {
+        fn __gcc_personality_seh0(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT
+        ) -> EXCEPTION_DISPOSITION;
+
+        fn _GCC_specific_handler(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT,
+            personality: _Unwind_Personality_Fn
+        ) -> EXCEPTION_DISPOSITION;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    extern "C" fn rust_eh_personality(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        unsafe {
+            __gcc_personality_seh0(exceptionRecord, establisherFrame,
+                                   contextRecord, dispatcherContext)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        extern "C" fn inner(
+                _version: c_int,
+                actions: uw::_Unwind_Action,
+                _exception_class: uw::_Unwind_Exception_Class,
+                _ue_header: *mut uw::_Unwind_Exception,
+                _context: *mut uw::_Unwind_Context
+            ) -> uw::_Unwind_Reason_Code
+        {
+            if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+                uw::_URC_HANDLER_FOUND // catch!
             }
+            else { // cleanup phase
+                uw::_URC_INSTALL_CONTEXT
+            }
+        }
+
+        unsafe {
+            _GCC_specific_handler(exceptionRecord, establisherFrame,
+                                  contextRecord, dispatcherContext,
+                                  inner)
         }
     }
 }
diff --git a/src/rt/rust_try.ll b/src/rt/rust_try.ll
index c912aa789bf..08bf5e3dfac 100644
--- a/src/rt/rust_try.ll
+++ b/src/rt/rust_try.ll
@@ -11,24 +11,40 @@
 ; Rust's try-catch
 ; When f(...) returns normally, the return value is null.
 ; When f(...) throws, the return value is a pointer to the caught exception object.
-; See also: libstd/rt/unwind.rs
+; See also: librustrt/unwind.rs
 
 define i8* @rust_try(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
 
-	invoke void %f(i8* %fptr, i8* %env)
-		to label %normal
-		unwind label %catch
+    %1 = invoke i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env)
+        to label %normal
+        unwind label %catch
 
 normal:
-	ret i8* null
+    ret i8* %1
 
 catch:
-	%1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
-			catch i8* null ; catch everything
-
-	; extract and return pointer to the exception object
-    %2 = extractvalue { i8*, i32 } %1, 0
-	ret i8* %2
+    landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
+        catch i8* null
+    ; execution will never reach here because rust_try_inner's landing pad does not resume unwinds
+    ret i8* null
 }
 
+define internal i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
+
+    invoke void %f(i8* %fptr, i8* %env)
+        to label %normal
+        unwind label %catch
+
+normal:
+    ret i8* null
+
+catch:
+    %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality to i8*)
+        catch i8* null
+    ; extract and return pointer to the exception object
+    %2 = extractvalue { i8*, i32 } %1, 0
+    ret i8* %2
+}
+
+declare i32 @rust_eh_personality(...)
 declare i32 @rust_eh_personality_catch(...)