Просмотр исходного кода

Implement basic setjmp using musl's awesome existing code

jD91mZM2 6 лет назад
Родитель
Сommit
4e99b55417
46 измененных файлов с 1297 добавлено и 3 удалено
  1. 9 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 67 0
      include/bits/setjmp.h
  4. 1 0
      src/lib.rs
  5. 11 0
      src/setjmp/Cargo.toml
  6. 72 0
      src/setjmp/build.rs
  7. 6 0
      src/setjmp/cbindgen.toml
  8. 6 0
      src/setjmp/impl/README.md
  9. 24 0
      src/setjmp/impl/aarch64/longjmp.s
  10. 24 0
      src/setjmp/impl/aarch64/setjmp.s
  11. 43 0
      src/setjmp/impl/arm/longjmp.s
  12. 45 0
      src/setjmp/impl/arm/setjmp.s
  13. 2 0
      src/setjmp/impl/bin/.gitignore
  14. 20 0
      src/setjmp/impl/i386/longjmp.s
  15. 23 0
      src/setjmp/impl/i386/setjmp.s
  16. 14 0
      src/setjmp/impl/m68k/longjmp.s
  17. 18 0
      src/setjmp/impl/m68k/setjmp.s
  18. 29 0
      src/setjmp/impl/microblaze/longjmp.s
  19. 32 0
      src/setjmp/impl/microblaze/setjmp.s
  20. 40 0
      src/setjmp/impl/mips/longjmp.S
  21. 39 0
      src/setjmp/impl/mips/setjmp.S
  22. 37 0
      src/setjmp/impl/mips64/longjmp.S
  23. 34 0
      src/setjmp/impl/mips64/setjmp.S
  24. 36 0
      src/setjmp/impl/mipsn32/longjmp.S
  25. 34 0
      src/setjmp/impl/mipsn32/setjmp.S
  26. 25 0
      src/setjmp/impl/or1k/longjmp.s
  27. 27 0
      src/setjmp/impl/or1k/setjmp.s
  28. 69 0
      src/setjmp/impl/powerpc/longjmp.S
  29. 63 0
      src/setjmp/impl/powerpc/setjmp.S
  30. 81 0
      src/setjmp/impl/powerpc64/longjmp.s
  31. 89 0
      src/setjmp/impl/powerpc64/setjmp.s
  32. 23 0
      src/setjmp/impl/s390x/longjmp.s
  33. 25 0
      src/setjmp/impl/s390x/setjmp.s
  34. 28 0
      src/setjmp/impl/sh/longjmp.S
  35. 32 0
      src/setjmp/impl/sh/setjmp.S
  36. 22 0
      src/setjmp/impl/x32/longjmp.s
  37. 22 0
      src/setjmp/impl/x32/setjmp.s
  38. 22 0
      src/setjmp/impl/x86_64/longjmp.s
  39. 22 0
      src/setjmp/impl/x86_64/setjmp.s
  40. 62 0
      src/setjmp/src/lib.rs
  41. 2 2
      src/stdlib/src/lib.rs
  42. 1 1
      tests/.gitignore
  43. 1 0
      tests/Makefile
  44. 0 0
      tests/expected/setjmp.stderr
  45. 2 0
      tests/expected/setjmp.stdout
  46. 12 0
      tests/setjmp.c

+ 9 - 0
Cargo.lock

@@ -283,6 +283,7 @@ dependencies = [
  "netinet 0.1.0",
  "platform 0.1.0",
  "semaphore 0.1.0",
+ "setjmp 0.1.0",
  "signal 0.1.0",
  "stdio 0.1.0",
  "stdlib 0.1.0",
@@ -357,6 +358,14 @@ dependencies = [
  "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "setjmp"
+version = "0.1.0"
+dependencies = [
+ "cbindgen 0.5.2",
+ "platform 0.1.0",
+]
+
 [[package]]
 name = "signal"
 version = "0.1.0"

+ 1 - 0
Cargo.toml

@@ -24,6 +24,7 @@ grp = { path = "src/grp" }
 locale = { path = "src/locale" }
 netinet = { path = "src/netinet" }
 platform = { path = "src/platform" }
+setjmp = { path = "src/setjmp" }
 semaphore = { path = "src/semaphore" }
 signal = { path = "src/signal" }
 stdio = { path = "src/stdio" }

+ 67 - 0
include/bits/setjmp.h

@@ -0,0 +1,67 @@
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H
+
+#ifdef __arch64__
+typedef unsigned long jmp_buf[22];
+#endif
+
+#ifdef __arm__
+typedef unsigned long long jmp_buf[32];
+#endif
+
+#ifdef __i386__
+typedef unsigned long jmp_buf[6];
+#endif
+
+#ifdef __m68k__
+typedef unsigned long jmp_buf[39];
+#endif
+
+#ifdef __microblaze__
+typedef unsigned long jmp_buf[18];
+#endif
+
+#ifdef __mips__
+typedef unsigned long long jmp_buf[13];
+#endif
+
+#ifdef __mips64__
+typedef unsigned long long jmp_buf[23];
+#endif
+
+#ifdef __mipsn32__
+typedef unsigned long long jmp_buf[23];
+#endif
+
+#ifdef __or1k__
+typedef unsigned long jmp_buf[13];
+#endif
+
+#ifdef __powerpc__
+typedef unsigned long long jmp_buf[56];
+#endif
+
+#ifdef __powerpc64__
+typedef uint128_t jmp_buf[32];
+#endif
+
+#ifdef __s390x__
+typedef unsigned long jmp_buf[18];
+#endif
+
+#ifdef __sh__
+typedef unsigned long jmp_buf[15];
+#endif
+
+#ifdef __x32__
+typedef unsigned long long jmp_buf[8];
+#endif
+
+#ifdef __x86_64__
+typedef unsigned long jmp_buf[8];
+#endif
+
+int setjmp(jmp_buf buf);
+void longjmp(jmp_buf buf, int value);
+
+#endif /* _SETJMP_H */

+ 1 - 0
src/lib.rs

@@ -13,6 +13,7 @@ pub extern crate grp;
 pub extern crate locale;
 pub extern crate netinet;
 pub extern crate semaphore;
+pub extern crate setjmp;
 pub extern crate stdio;
 pub extern crate stdlib;
 pub extern crate string;

+ 11 - 0
src/setjmp/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "setjmp"
+version = "0.1.0"
+authors = ["Jeremy Soller <[email protected]>"]
+build = "build.rs"
+
+[build-dependencies]
+cbindgen = { path = "../../cbindgen" }
+
+[dependencies]
+platform = { path = "../platform" }

+ 72 - 0
src/setjmp/build.rs

@@ -0,0 +1,72 @@
+extern crate cbindgen;
+
+use std::{env, fs, process::Command};
+
+fn compile(file: &str, object: &str, output: &str) {
+    let status = Command::new("gcc")
+        .args(&["-c", file, "-o", object])
+        .status()
+        .expect("failed to run gcc to compile assembly");
+
+    if !status.success() {
+        panic!("compilation error");
+    }
+
+    let status = Command::new("ar")
+        .args(&["rcs", output, object])
+        .status()
+        .expect("failed to run ar to convert object to a static library");
+
+    if !status.success() {
+        panic!("error converting object to static library");
+    }
+}
+
+fn main() {
+    println!("cargo:rustc-link-lib=static=setjmp");
+    println!("cargo:rustc-link-lib=static=longjmp");
+
+    macro_rules! detect_arch {
+        ($($($token:tt);+),+) => {
+            $(
+                detect_arch!(inner $($token);+);
+            )+
+        };
+        (inner $arch:expr) => {
+            detect_arch!(inner $arch; ".s");
+        };
+        (inner $arch:expr; $ext:expr) => {
+            #[cfg(target_arch = $arch)] {
+                compile(concat!("impl/", $arch, "/setjmp", $ext), "impl/bin/setjmp.o", "impl/bin/libsetjmp.a");
+                compile(concat!("impl/", $arch, "/longjmp", $ext), "impl/bin/longjmp.o", "impl/bin/liblongjmp.a");
+
+                let dir = env::current_dir().expect("failed to find current directory");
+                println!("cargo:rustc-link-search=native={}/impl/bin", dir.display());
+            }
+        };
+    }
+
+    detect_arch! {
+        "aarch64",
+        "arm",
+        "i386",
+        "m68k",
+        "microblaze",
+        "mips"; ".S",
+        "mips64"; ".S",
+        "mipsn32"; ".S",
+        "or1k",
+        "powerpc"; ".S",
+        "powerpc64",
+        "s390x",
+        "sh"; ".S",
+        "x32",
+        "x86_64"
+    }
+
+    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
+    fs::create_dir_all("../../target/include").expect("failed to create include directory");
+    cbindgen::generate(crate_dir)
+        .expect("failed to generate bindings")
+        .write_to_file("../../target/include/setjmp.h");
+}

+ 6 - 0
src/setjmp/cbindgen.toml

@@ -0,0 +1,6 @@
+include_guard = "_SETJMP_H"
+trailer = "#include <bits/setjmp.h>"
+language = "C"
+
+[enum]
+prefix_with_name = true

+ 6 - 0
src/setjmp/impl/README.md

@@ -0,0 +1,6 @@
+# setjmp implementation
+
+All this code belongs to [musl libc](https://www.musl-libc.org/).
+They own it. All rights go to them.
+Huge thanks to them for doing this tedious per-arch assembly work!
+We will reuse this awesome effort :)

+ 24 - 0
src/setjmp/impl/aarch64/longjmp.s

@@ -0,0 +1,24 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,%function
+.type longjmp,%function
+_longjmp:
+longjmp:
+	// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
+	ldp x19, x20, [x0,#0]
+	ldp x21, x22, [x0,#16]
+	ldp x23, x24, [x0,#32]
+	ldp x25, x26, [x0,#48]
+	ldp x27, x28, [x0,#64]
+	ldp x29, x30, [x0,#80]
+	ldr x2, [x0,#104]
+	mov sp, x2
+	ldp d8 , d9, [x0,#112]
+	ldp d10, d11, [x0,#128]
+	ldp d12, d13, [x0,#144]
+	ldp d14, d15, [x0,#160]
+
+	mov x0, x1
+	cbnz x1, 1f
+	mov x0, #1
+1:	br x30

+ 24 - 0
src/setjmp/impl/aarch64/setjmp.s

@@ -0,0 +1,24 @@
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
+	stp x19, x20, [x0,#0]
+	stp x21, x22, [x0,#16]
+	stp x23, x24, [x0,#32]
+	stp x25, x26, [x0,#48]
+	stp x27, x28, [x0,#64]
+	stp x29, x30, [x0,#80]
+	mov x2, sp
+	str x2, [x0,#104]
+	stp  d8,  d9, [x0,#112]
+	stp d10, d11, [x0,#128]
+	stp d12, d13, [x0,#144]
+	stp d14, d15, [x0,#160]
+	mov x0, #0
+	ret

+ 43 - 0
src/setjmp/impl/arm/longjmp.s

@@ -0,0 +1,43 @@
+.syntax unified
+.global _longjmp
+.global longjmp
+.type _longjmp,%function
+.type longjmp,%function
+_longjmp:
+longjmp:
+	mov ip,r0
+	movs r0,r1
+	moveq r0,#1
+	ldmia ip!, {v1,v2,v3,v4,v5,v6,sl,fp}
+	ldmia ip!, {r2,lr}
+	mov sp,r2
+
+	adr r1,1f
+	ldr r2,1f
+	ldr r1,[r1,r2]
+
+	tst r1,#0x260
+	beq 3f
+	tst r1,#0x20
+	beq 2f
+	ldc p2, cr4, [ip], #48
+2:	tst r1,#0x40
+	beq 2f
+	.fpu vfp
+	vldmia ip!, {d8-d15}
+	.fpu softvfp
+	.eabi_attribute 10, 0
+	.eabi_attribute 27, 0
+2:	tst r1,#0x200
+	beq 3f
+	ldcl p1, cr10, [ip], #8
+	ldcl p1, cr11, [ip], #8
+	ldcl p1, cr12, [ip], #8
+	ldcl p1, cr13, [ip], #8
+	ldcl p1, cr14, [ip], #8
+	ldcl p1, cr15, [ip], #8
+3:	bx lr
+
+.hidden __hwcap
+.align 2
+1:	.word __hwcap-1b

+ 45 - 0
src/setjmp/impl/arm/setjmp.s

@@ -0,0 +1,45 @@
+.syntax unified
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,%function
+.type _setjmp,%function
+.type setjmp,%function
+__setjmp:
+_setjmp:
+setjmp:
+	mov ip,r0
+	stmia ip!,{v1,v2,v3,v4,v5,v6,sl,fp}
+	mov r2,sp
+	stmia ip!,{r2,lr}
+	mov r0,#0
+
+	adr r1,1f
+	ldr r2,1f
+	ldr r1,[r1,r2]
+
+	tst r1,#0x260
+	beq 3f
+	tst r1,#0x20
+	beq 2f
+	stc p2, cr4, [ip], #48
+2:	tst r1,#0x40
+	beq 2f
+	.fpu vfp
+	vstmia ip!, {d8-d15}
+	.fpu softvfp
+	.eabi_attribute 10, 0
+	.eabi_attribute 27, 0
+2:	tst r1,#0x200
+	beq 3f
+	stcl p1, cr10, [ip], #8
+	stcl p1, cr11, [ip], #8
+	stcl p1, cr12, [ip], #8
+	stcl p1, cr13, [ip], #8
+	stcl p1, cr14, [ip], #8
+	stcl p1, cr15, [ip], #8
+3:	bx lr
+
+.hidden __hwcap
+.align 2
+1:	.word __hwcap-1b

+ 2 - 0
src/setjmp/impl/bin/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 20 - 0
src/setjmp/impl/i386/longjmp.s

@@ -0,0 +1,20 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+	mov  4(%esp),%edx
+	mov  8(%esp),%eax
+	test    %eax,%eax
+	jnz 1f
+	inc     %eax
+1:
+	mov   (%edx),%ebx
+	mov  4(%edx),%esi
+	mov  8(%edx),%edi
+	mov 12(%edx),%ebp
+	mov 16(%edx),%ecx
+	mov     %ecx,%esp
+	mov 20(%edx),%ecx
+	jmp *%ecx

+ 23 - 0
src/setjmp/impl/i386/setjmp.s

@@ -0,0 +1,23 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	mov 4(%esp), %eax
+	mov    %ebx, (%eax)
+	mov    %esi, 4(%eax)
+	mov    %edi, 8(%eax)
+	mov    %ebp, 12(%eax)
+	lea 4(%esp), %ecx
+	mov    %ecx, 16(%eax)
+	mov  (%esp), %ecx
+	mov    %ecx, 20(%eax)
+	xor    %eax, %eax
+	ret

+ 14 - 0
src/setjmp/impl/m68k/longjmp.s

@@ -0,0 +1,14 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+	movea.l 4(%sp),%a0
+	move.l 8(%sp),%d0
+	bne 1f
+	move.l #1,%d0
+1:	movem.l (%a0),%d2-%d7/%a2-%a7
+	fmovem.x 52(%a0),%fp2-%fp7
+	move.l 48(%a0),(%sp)
+	rts

+ 18 - 0
src/setjmp/impl/m68k/setjmp.s

@@ -0,0 +1,18 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	movea.l 4(%sp),%a0
+	movem.l %d2-%d7/%a2-%a7,(%a0)
+	move.l (%sp),48(%a0)
+	fmovem.x %fp2-%fp7,52(%a0)
+	clr.l %d0
+	rts

+ 29 - 0
src/setjmp/impl/microblaze/longjmp.s

@@ -0,0 +1,29 @@
+.global _longjmp
+.global longjmp
+.type   _longjmp,@function
+.type   longjmp,@function
+_longjmp:
+longjmp:
+	addi    r3, r6, 0
+	bnei    r3, 1f
+	addi    r3, r3, 1
+1:      lwi     r1,  r5, 0
+	lwi     r15, r5, 4
+	lwi     r2,  r5, 8
+	lwi     r13, r5, 12
+	lwi     r18, r5, 16
+	lwi     r19, r5, 20
+	lwi     r20, r5, 24
+	lwi     r21, r5, 28
+	lwi     r22, r5, 32
+	lwi     r23, r5, 36
+	lwi     r24, r5, 40
+	lwi     r25, r5, 44
+	lwi     r26, r5, 48
+	lwi     r27, r5, 52
+	lwi     r28, r5, 56
+	lwi     r29, r5, 60
+	lwi     r30, r5, 64
+	lwi     r31, r5, 68
+	rtsd    r15, 8
+	nop

+ 32 - 0
src/setjmp/impl/microblaze/setjmp.s

@@ -0,0 +1,32 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	swi     r1,  r5, 0
+	swi     r15, r5, 4
+	swi     r2,  r5, 8
+	swi     r13, r5, 12
+	swi     r18, r5, 16
+	swi     r19, r5, 20
+	swi     r20, r5, 24
+	swi     r21, r5, 28
+	swi     r22, r5, 32
+	swi     r23, r5, 36
+	swi     r24, r5, 40
+	swi     r25, r5, 44
+	swi     r26, r5, 48
+	swi     r27, r5, 52
+	swi     r28, r5, 56
+	swi     r29, r5, 60
+	swi     r30, r5, 64
+	swi     r31, r5, 68
+	rtsd    r15, 8
+	ori     r3, r0, 0

+ 40 - 0
src/setjmp/impl/mips/longjmp.S

@@ -0,0 +1,40 @@
+.set noreorder
+
+.global _longjmp
+.global longjmp
+.type   _longjmp,@function
+.type   longjmp,@function
+_longjmp:
+longjmp:
+	move    $2, $5
+	bne     $2, $0, 1f
+	nop
+	addu    $2, $2, 1
+1:
+#ifndef __mips_soft_float
+	lwc1    $20, 56($4)
+	lwc1    $21, 60($4)
+	lwc1    $22, 64($4)
+	lwc1    $23, 68($4)
+	lwc1    $24, 72($4)
+	lwc1    $25, 76($4)
+	lwc1    $26, 80($4)
+	lwc1    $27, 84($4)
+	lwc1    $28, 88($4)
+	lwc1    $29, 92($4)
+	lwc1    $30, 96($4)
+	lwc1    $31, 100($4)
+#endif
+	lw      $ra,  0($4)
+	lw      $sp,  4($4)
+	lw      $16,  8($4)
+	lw      $17, 12($4)
+	lw      $18, 16($4)
+	lw      $19, 20($4)
+	lw      $20, 24($4)
+	lw      $21, 28($4)
+	lw      $22, 32($4)
+	lw      $23, 36($4)
+	lw      $30, 40($4)
+	jr      $ra
+	lw      $28, 44($4)

+ 39 - 0
src/setjmp/impl/mips/setjmp.S

@@ -0,0 +1,39 @@
+.set noreorder
+
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type   __setjmp,@function
+.type   _setjmp,@function
+.type   setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	sw      $ra,  0($4)
+	sw      $sp,  4($4)
+	sw      $16,  8($4)
+	sw      $17, 12($4)
+	sw      $18, 16($4)
+	sw      $19, 20($4)
+	sw      $20, 24($4)
+	sw      $21, 28($4)
+	sw      $22, 32($4)
+	sw      $23, 36($4)
+	sw      $30, 40($4)
+	sw      $28, 44($4)
+#ifndef __mips_soft_float
+	swc1    $20, 56($4)
+	swc1    $21, 60($4)
+	swc1    $22, 64($4)
+	swc1    $23, 68($4)
+	swc1    $24, 72($4)
+	swc1    $25, 76($4)
+	swc1    $26, 80($4)
+	swc1    $27, 84($4)
+	swc1    $28, 88($4)
+	swc1    $29, 92($4)
+	swc1    $30, 96($4)
+	swc1    $31, 100($4)
+#endif
+	jr      $ra
+	li      $2, 0

+ 37 - 0
src/setjmp/impl/mips64/longjmp.S

@@ -0,0 +1,37 @@
+.set	noreorder
+.global	_longjmp
+.global	longjmp
+.type	_longjmp,@function
+.type	longjmp,@function
+_longjmp:
+longjmp:
+	move	$2, $5
+
+	bne	$2, $0, 1f
+	nop
+	daddu	$2, $2, 1
+1:
+#ifndef __mips_soft_float
+	ldc1	$24, 96($4)
+	ldc1	$25, 104($4)
+	ldc1	$26, 112($4)
+	ldc1	$27, 120($4)
+	ldc1	$28, 128($4)
+	ldc1	$29, 136($4)
+	ldc1	$30, 144($4)
+	ldc1	$31, 152($4)
+#endif
+	ld	$ra, 0($4)
+	ld	$sp, 8($4)
+	ld	$gp, 16($4)
+	ld	$16, 24($4)
+	ld	$17, 32($4)
+	ld	$18, 40($4)
+	ld	$19, 48($4)
+	ld	$20, 56($4)
+	ld	$21, 64($4)
+	ld	$22, 72($4)
+	ld	$23, 80($4)
+	ld	$30, 88($4)
+	jr	$ra
+	nop

+ 34 - 0
src/setjmp/impl/mips64/setjmp.S

@@ -0,0 +1,34 @@
+.set	noreorder
+.global	__setjmp
+.global	_setjmp
+.global	setjmp
+.type	__setjmp,@function
+.type	_setjmp,@function
+.type	setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	sd	$ra, 0($4)
+	sd	$sp, 8($4)
+	sd	$gp, 16($4)
+	sd	$16, 24($4)
+	sd	$17, 32($4)
+	sd	$18, 40($4)
+	sd	$19, 48($4)
+	sd	$20, 56($4)
+	sd	$21, 64($4)
+	sd	$22, 72($4)
+	sd	$23, 80($4)
+	sd	$30, 88($4)
+#ifndef __mips_soft_float
+	sdc1	$24, 96($4)
+	sdc1	$25, 104($4)
+	sdc1	$26, 112($4)
+	sdc1	$27, 120($4)
+	sdc1	$28, 128($4)
+	sdc1	$29, 136($4)
+	sdc1	$30, 144($4)
+	sdc1	$31, 152($4)
+#endif
+	jr	$ra
+	li	$2, 0

+ 36 - 0
src/setjmp/impl/mipsn32/longjmp.S

@@ -0,0 +1,36 @@
+.set	noreorder
+.global	_longjmp
+.global	longjmp
+.type	_longjmp,@function
+.type	longjmp,@function
+_longjmp:
+longjmp:
+	move	$2, $5
+	bne	$2, $0, 1f
+	nop
+	addu	$2, $2, 1
+1:
+#ifndef __mips_soft_float
+	ldc1	$24, 96($4)
+	ldc1	$25, 104($4)
+	ldc1	$26, 112($4)
+	ldc1	$27, 120($4)
+	ldc1	$28, 128($4)
+	ldc1	$29, 136($4)
+	ldc1	$30, 144($4)
+	ldc1	$31, 152($4)
+#endif
+	ld	$ra, 0($4)
+	ld	$sp, 8($4)
+	ld	$gp, 16($4)
+	ld	$16, 24($4)
+	ld	$17, 32($4)
+	ld	$18, 40($4)
+	ld	$19, 48($4)
+	ld	$20, 56($4)
+	ld	$21, 64($4)
+	ld	$22, 72($4)
+	ld	$23, 80($4)
+	ld	$30, 88($4)
+	jr	$ra
+	nop

+ 34 - 0
src/setjmp/impl/mipsn32/setjmp.S

@@ -0,0 +1,34 @@
+.set	noreorder
+.global	__setjmp
+.global	_setjmp
+.global	setjmp
+.type	__setjmp,@function
+.type	_setjmp,@function
+.type	setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	sd	$ra, 0($4)
+	sd	$sp, 8($4)
+	sd	$gp, 16($4)
+	sd	$16, 24($4)
+	sd	$17, 32($4)
+	sd	$18, 40($4)
+	sd	$19, 48($4)
+	sd	$20, 56($4)
+	sd	$21, 64($4)
+	sd	$22, 72($4)
+	sd	$23, 80($4)
+	sd	$30, 88($4)
+#ifndef __mips_soft_float
+	sdc1	$24, 96($4)
+	sdc1	$25, 104($4)
+	sdc1	$26, 112($4)
+	sdc1	$27, 120($4)
+	sdc1	$28, 128($4)
+	sdc1	$29, 136($4)
+	sdc1	$30, 144($4)
+	sdc1	$31, 152($4)
+#endif
+	jr	$ra
+	li	$2, 0

+ 25 - 0
src/setjmp/impl/or1k/longjmp.s

@@ -0,0 +1,25 @@
+.global _longjmp
+.global longjmp
+.type   _longjmp,@function
+.type   longjmp,@function
+_longjmp:
+longjmp:
+	l.sfeqi	r4, 0
+	l.bnf	1f
+	 l.addi	r11, r4,0
+	l.ori	r11, r0, 1
+1:	l.lwz	r1, 0(r3)
+	l.lwz	r2, 4(r3)
+	l.lwz	r9, 8(r3)
+	l.lwz	r10, 12(r3)
+	l.lwz	r14, 16(r3)
+	l.lwz	r16, 20(r3)
+	l.lwz	r18, 24(r3)
+	l.lwz	r20, 28(r3)
+	l.lwz	r22, 32(r3)
+	l.lwz	r24, 36(r3)
+	l.lwz	r26, 40(r3)
+	l.lwz	r28, 44(r3)
+	l.lwz	r30, 48(r3)
+	l.jr	r9
+	 l.nop

+ 27 - 0
src/setjmp/impl/or1k/setjmp.s

@@ -0,0 +1,27 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	l.sw	0(r3), r1
+	l.sw	4(r3), r2
+	l.sw	8(r3), r9
+	l.sw	12(r3), r10
+	l.sw	16(r3), r14
+	l.sw	20(r3), r16
+	l.sw	24(r3), r18
+	l.sw	28(r3), r20
+	l.sw	32(r3), r22
+	l.sw	36(r3), r24
+	l.sw	40(r3), r26
+	l.sw	44(r3), r28
+	l.sw	48(r3), r30
+	l.jr	r9
+	 l.ori	r11,r0,0

+ 69 - 0
src/setjmp/impl/powerpc/longjmp.S

@@ -0,0 +1,69 @@
+	.global _longjmp
+	.global longjmp
+	.type   _longjmp,@function
+	.type   longjmp,@function
+_longjmp:
+longjmp:
+	/*
+	 * void longjmp(jmp_buf env, int val);
+	 * put val into return register and restore the env saved in setjmp
+	 * if val(r4) is 0, put 1 there.
+	 */
+	/* 0) move old return address into r0 */
+	lwz 0, 0(3)
+	/* 1) put it into link reg */
+	mtlr 0
+	/* 2 ) restore stack ptr */
+	lwz 1, 4(3)
+	/* 3) restore control reg */
+	lwz 0, 8(3)
+	mtcr 0
+	/* 4) restore r14-r31 */
+	lwz 14, 12(3)
+	lwz 15, 16(3)
+	lwz 16, 20(3)
+	lwz 17, 24(3)
+	lwz 18, 28(3)
+	lwz 19, 32(3)
+	lwz 20, 36(3)
+	lwz 21, 40(3)
+	lwz 22, 44(3)
+	lwz 23, 48(3)
+	lwz 24, 52(3)
+	lwz 25, 56(3)
+	lwz 26, 60(3)
+	lwz 27, 64(3)
+	lwz 28, 68(3)
+	lwz 29, 72(3)
+	lwz 30, 76(3)
+	lwz 31, 80(3)
+#ifndef _SOFT_FLOAT
+	lfd 14,88(3)
+	lfd 15,96(3)
+	lfd 16,104(3)
+	lfd 17,112(3)
+	lfd 18,120(3)
+	lfd 19,128(3)
+	lfd 20,136(3)
+	lfd 21,144(3)
+	lfd 22,152(3)
+	lfd 23,160(3)
+	lfd 24,168(3)
+	lfd 25,176(3)
+	lfd 26,184(3)
+	lfd 27,192(3)
+	lfd 28,200(3)
+	lfd 29,208(3)
+	lfd 30,216(3)
+	lfd 31,224(3)
+#endif
+	/* 5) put val into return reg r3 */
+	mr 3, 4
+
+	/* 6) check if return value is 0, make it 1 in that case */
+	cmpwi cr7, 4, 0
+	bne cr7, 1f
+	li 3, 1
+1:
+	blr
+

+ 63 - 0
src/setjmp/impl/powerpc/setjmp.S

@@ -0,0 +1,63 @@
+	.global ___setjmp
+	.hidden ___setjmp
+	.global __setjmp
+	.global _setjmp
+	.global setjmp
+	.type   __setjmp,@function
+	.type   _setjmp,@function
+	.type   setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	/* 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg) */
+	mflr 0
+	stw 0, 0(3)
+	/* 1) store reg1 (SP) */
+	stw 1, 4(3)
+	/* 2) store cr */
+	mfcr 0
+	stw 0, 8(3)
+	/* 3) store r14-31 */
+	stw 14, 12(3)
+	stw 15, 16(3)
+	stw 16, 20(3)
+	stw 17, 24(3)
+	stw 18, 28(3)
+	stw 19, 32(3)
+	stw 20, 36(3)
+	stw 21, 40(3)
+	stw 22, 44(3)
+	stw 23, 48(3)
+	stw 24, 52(3)
+	stw 25, 56(3)
+	stw 26, 60(3)
+	stw 27, 64(3)
+	stw 28, 68(3)
+	stw 29, 72(3)
+	stw 30, 76(3)
+	stw 31, 80(3)
+#ifndef _SOFT_FLOAT
+	stfd 14,88(3)
+	stfd 15,96(3)
+	stfd 16,104(3)
+	stfd 17,112(3)
+	stfd 18,120(3)
+	stfd 19,128(3)
+	stfd 20,136(3)
+	stfd 21,144(3)
+	stfd 22,152(3)
+	stfd 23,160(3)
+	stfd 24,168(3)
+	stfd 25,176(3)
+	stfd 26,184(3)
+	stfd 27,192(3)
+	stfd 28,200(3)
+	stfd 29,208(3)
+	stfd 30,216(3)
+	stfd 31,224(3)
+#endif
+	/* 4) set return value to 0 */
+	li 3, 0
+	/* 5) return */
+	blr

+ 81 - 0
src/setjmp/impl/powerpc64/longjmp.s

@@ -0,0 +1,81 @@
+	.global _longjmp
+	.global longjmp
+	.type   _longjmp,@function
+	.type   longjmp,@function
+_longjmp:
+longjmp:
+	# 0) move old return address into the link register
+	ld   0,  0*8(3)
+	mtlr 0
+	# 1) restore cr
+	ld   0,  1*8(3)
+	mtcr 0
+	# 2) restore SP
+	ld   1,  2*8(3)
+	# 3) restore TOC into both r2 and the caller's stack.
+	#    Which location is required depends on whether setjmp was called
+	#    locally or non-locally, but it's always safe to restore to both.
+	ld   2,  3*8(3)
+	std  2,   24(1)
+	# 4) restore r14-r31
+	ld  14,  4*8(3)
+	ld  15,  5*8(3)
+	ld  16,  6*8(3)
+	ld  17,  7*8(3)
+	ld  18,  8*8(3)
+	ld  19,  9*8(3)
+	ld  20, 10*8(3)
+	ld  21, 11*8(3)
+	ld  22, 12*8(3)
+	ld  23, 13*8(3)
+	ld  24, 14*8(3)
+	ld  25, 15*8(3)
+	ld  26, 16*8(3)
+	ld  27, 17*8(3)
+	ld  28, 18*8(3)
+	ld  29, 19*8(3)
+	ld  30, 20*8(3)
+	ld  31, 21*8(3)
+	# 5) restore floating point registers f14-f31
+	lfd 14, 22*8(3)
+	lfd 15, 23*8(3)
+	lfd 16, 24*8(3)
+	lfd 17, 25*8(3)
+	lfd 18, 26*8(3)
+	lfd 19, 27*8(3)
+	lfd 20, 28*8(3)
+	lfd 21, 29*8(3)
+	lfd 22, 30*8(3)
+	lfd 23, 31*8(3)
+	lfd 24, 32*8(3)
+	lfd 25, 33*8(3)
+	lfd 26, 34*8(3)
+	lfd 27, 35*8(3)
+	lfd 28, 36*8(3)
+	lfd 29, 37*8(3)
+	lfd 30, 38*8(3)
+	lfd 31, 39*8(3)
+
+	# 6) restore vector registers v20-v31
+	addi 3, 3, 40*8
+	lvx 20, 0, 3 ; addi 3, 3, 16
+	lvx 21, 0, 3 ; addi 3, 3, 16
+	lvx 22, 0, 3 ; addi 3, 3, 16
+	lvx 23, 0, 3 ; addi 3, 3, 16
+	lvx 24, 0, 3 ; addi 3, 3, 16
+	lvx 25, 0, 3 ; addi 3, 3, 16
+	lvx 26, 0, 3 ; addi 3, 3, 16
+	lvx 27, 0, 3 ; addi 3, 3, 16
+	lvx 28, 0, 3 ; addi 3, 3, 16
+	lvx 29, 0, 3 ; addi 3, 3, 16
+	lvx 30, 0, 3 ; addi 3, 3, 16
+	lvx 31, 0, 3
+
+	# 7) return r4 ? r4 : 1
+	mr    3,   4
+	cmpwi cr7, 4, 0
+	bne   cr7, 1f
+	li    3,   1
+1:
+	blr
+

+ 89 - 0
src/setjmp/impl/powerpc64/setjmp.s

@@ -0,0 +1,89 @@
+	.global __setjmp
+	.global _setjmp
+	.global setjmp
+	.type   __setjmp,@function
+	.type   _setjmp,@function
+	.type   setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	ld 5, 24(1)   # load from the TOC slot in the caller's stack frame
+	b __setjmp_toc
+
+	.localentry __setjmp,.-__setjmp
+	.localentry _setjmp,.-_setjmp
+	.localentry setjmp,.-setjmp
+	mr 5, 2
+
+	.global __setjmp_toc
+	.hidden __setjmp_toc
+	# same as normal setjmp, except TOC pointer to save is provided in r5.
+	# r4 would normally be the 2nd parameter, but we're using r5 to simplify calling from sigsetjmp.
+	# solves the problem of knowing whether to save the TOC pointer from r2 or the caller's stack frame.
+__setjmp_toc:
+	# 0) store IP into 0, then into the jmpbuf pointed to by r3 (first arg)
+	mflr  0
+	std   0,  0*8(3)
+	# 1) store cr
+	mfcr  0
+	std   0,  1*8(3)
+	# 2) store SP and TOC
+	std   1,  2*8(3)
+	std   5,  3*8(3)
+	# 3) store r14-31
+	std  14,  4*8(3)
+	std  15,  5*8(3)
+	std  16,  6*8(3)
+	std  17,  7*8(3)
+	std  18,  8*8(3)
+	std  19,  9*8(3)
+	std  20, 10*8(3)
+	std  21, 11*8(3)
+	std  22, 12*8(3)
+	std  23, 13*8(3)
+	std  24, 14*8(3)
+	std  25, 15*8(3)
+	std  26, 16*8(3)
+	std  27, 17*8(3)
+	std  28, 18*8(3)
+	std  29, 19*8(3)
+	std  30, 20*8(3)
+	std  31, 21*8(3)
+	# 4) store floating point registers f14-f31
+	stfd 14, 22*8(3)
+	stfd 15, 23*8(3)
+	stfd 16, 24*8(3)
+	stfd 17, 25*8(3)
+	stfd 18, 26*8(3)
+	stfd 19, 27*8(3)
+	stfd 20, 28*8(3)
+	stfd 21, 29*8(3)
+	stfd 22, 30*8(3)
+	stfd 23, 31*8(3)
+	stfd 24, 32*8(3)
+	stfd 25, 33*8(3)
+	stfd 26, 34*8(3)
+	stfd 27, 35*8(3)
+	stfd 28, 36*8(3)
+	stfd 29, 37*8(3)
+	stfd 30, 38*8(3)
+	stfd 31, 39*8(3)
+
+	# 5) store vector registers v20-v31
+	addi  3, 3, 40*8
+	stvx 20, 0, 3 ; addi 3, 3, 16
+	stvx 21, 0, 3 ; addi 3, 3, 16
+	stvx 22, 0, 3 ; addi 3, 3, 16
+	stvx 23, 0, 3 ; addi 3, 3, 16
+	stvx 24, 0, 3 ; addi 3, 3, 16
+	stvx 25, 0, 3 ; addi 3, 3, 16
+	stvx 26, 0, 3 ; addi 3, 3, 16
+	stvx 27, 0, 3 ; addi 3, 3, 16
+	stvx 28, 0, 3 ; addi 3, 3, 16
+	stvx 29, 0, 3 ; addi 3, 3, 16
+	stvx 30, 0, 3 ; addi 3, 3, 16
+	stvx 31, 0, 3
+
+	# 6) return 0
+	li 3, 0
+	blr

+ 23 - 0
src/setjmp/impl/s390x/longjmp.s

@@ -0,0 +1,23 @@
+	.global _longjmp
+	.global longjmp
+	.type   _longjmp,@function
+	.type   longjmp,@function
+_longjmp:
+longjmp:
+
+1:
+	lmg %r6, %r15, 0(%r2)
+
+	ld  %f8, 10*8(%r2)
+	ld  %f9, 11*8(%r2)
+	ld %f10, 12*8(%r2)
+	ld %f11, 13*8(%r2)
+	ld %f12, 14*8(%r2)
+	ld %f13, 15*8(%r2)
+	ld %f14, 16*8(%r2)
+	ld %f15, 17*8(%r2)
+
+	ltgr %r2, %r3
+	bnzr %r14
+	lhi  %r2, 1
+	br   %r14

+ 25 - 0
src/setjmp/impl/s390x/setjmp.s

@@ -0,0 +1,25 @@
+	.global ___setjmp
+	.hidden ___setjmp
+	.global __setjmp
+	.global _setjmp
+	.global setjmp
+	.type   __setjmp,@function
+	.type   _setjmp,@function
+	.type   setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	stmg %r6, %r15, 0(%r2)
+
+	std  %f8,  10*8(%r2)
+	std  %f9,  11*8(%r2)
+	std  %f10, 12*8(%r2)
+	std  %f11, 13*8(%r2)
+	std  %f12, 14*8(%r2)
+	std  %f13, 15*8(%r2)
+	std  %f14, 16*8(%r2)
+	std  %f15, 17*8(%r2)
+
+	lghi %r2, 0
+	br   %r14

+ 28 - 0
src/setjmp/impl/sh/longjmp.S

@@ -0,0 +1,28 @@
+.global _longjmp
+.global longjmp
+.type   _longjmp, @function
+.type   longjmp,  @function
+_longjmp:
+longjmp:
+	mov.l  @r4+, r8
+	mov.l  @r4+, r9
+	mov.l  @r4+, r10
+	mov.l  @r4+, r11
+	mov.l  @r4+, r12
+	mov.l  @r4+, r13
+	mov.l  @r4+, r14
+	mov.l  @r4+, r15
+	lds.l  @r4+, pr
+#if __SH_FPU_ANY__ || __SH4__
+	fmov.s @r4+, fr12
+	fmov.s @r4+, fr13
+	fmov.s @r4+, fr14
+	fmov.s @r4+, fr15
+#endif
+
+	tst  r5, r5
+	movt r0
+	add  r5, r0
+
+	rts
+	 nop

+ 32 - 0
src/setjmp/impl/sh/setjmp.S

@@ -0,0 +1,32 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type   __setjmp, @function
+.type   _setjmp,  @function
+.type   setjmp,   @function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+#if __SH_FPU_ANY__ || __SH4__
+	add   #52, r4
+	fmov.s fr15, @-r4
+	fmov.s fr14, @-r4
+	fmov.s fr13, @-r4
+	fmov.s fr12, @-r4
+#else
+	add   #36, r4
+#endif
+	sts.l  pr,   @-r4
+	mov.l  r15,  @-r4
+	mov.l  r14,  @-r4
+	mov.l  r13,  @-r4
+	mov.l  r12,  @-r4
+	mov.l  r11,  @-r4
+	mov.l  r10,  @-r4
+	mov.l  r9,   @-r4
+	mov.l  r8,   @-r4
+	rts
+	 mov  #0, r0

+ 22 - 0
src/setjmp/impl/x32/longjmp.s

@@ -0,0 +1,22 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+	mov %rsi,%rax           /* val will be longjmp return */
+	test %rax,%rax
+	jnz 1f
+	inc %rax                /* if val==0, val=1 per longjmp semantics */
+1:
+	mov (%rdi),%rbx         /* rdi is the jmp_buf, restore regs from it */
+	mov 8(%rdi),%rbp
+	mov 16(%rdi),%r12
+	mov 24(%rdi),%r13
+	mov 32(%rdi),%r14
+	mov 40(%rdi),%r15
+	mov 48(%rdi),%rdx       /* this ends up being the stack pointer */
+	mov %rdx,%rsp
+	mov 56(%rdi),%rdx       /* this is the instruction pointer */
+	jmp *%rdx               /* goto saved address without altering rsp */

+ 22 - 0
src/setjmp/impl/x32/setjmp.s

@@ -0,0 +1,22 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	mov %rbx,(%rdi)         /* rdi is jmp_buf, move registers onto it */
+	mov %rbp,8(%rdi)
+	mov %r12,16(%rdi)
+	mov %r13,24(%rdi)
+	mov %r14,32(%rdi)
+	mov %r15,40(%rdi)
+	lea 8(%rsp),%rdx        /* this is our rsp WITHOUT current ret addr */
+	mov %rdx,48(%rdi)
+	mov (%rsp),%rdx         /* save return addr ptr for new rip */
+	mov %rdx,56(%rdi)
+	xor %rax,%rax           /* always return 0 */
+	ret

+ 22 - 0
src/setjmp/impl/x86_64/longjmp.s

@@ -0,0 +1,22 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+	mov %rsi,%rax           /* val will be longjmp return */
+	test %rax,%rax
+	jnz 1f
+	inc %rax                /* if val==0, val=1 per longjmp semantics */
+1:
+	mov (%rdi),%rbx         /* rdi is the jmp_buf, restore regs from it */
+	mov 8(%rdi),%rbp
+	mov 16(%rdi),%r12
+	mov 24(%rdi),%r13
+	mov 32(%rdi),%r14
+	mov 40(%rdi),%r15
+	mov 48(%rdi),%rdx       /* this ends up being the stack pointer */
+	mov %rdx,%rsp
+	mov 56(%rdi),%rdx       /* this is the instruction pointer */
+	jmp *%rdx               /* goto saved address without altering rsp */

+ 22 - 0
src/setjmp/impl/x86_64/setjmp.s

@@ -0,0 +1,22 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	mov %rbx,(%rdi)         /* rdi is jmp_buf, move registers onto it */
+	mov %rbp,8(%rdi)
+	mov %r12,16(%rdi)
+	mov %r13,24(%rdi)
+	mov %r14,32(%rdi)
+	mov %r15,40(%rdi)
+	lea 8(%rsp),%rdx        /* this is our rsp WITHOUT current ret addr */
+	mov %rdx,48(%rdi)
+	mov (%rsp),%rdx         /* save return addr ptr for new rip */
+	mov %rdx,56(%rdi)
+	xor %rax,%rax           /* always return 0 */
+	ret

+ 62 - 0
src/setjmp/src/lib.rs

@@ -0,0 +1,62 @@
+//! setjmp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/setjmp.h.html
+
+#![no_std]
+
+extern crate platform;
+
+use platform::types::*;
+
+#[cfg(target_arch = "aarch64")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 22];
+#[cfg(target_arch = "arm")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 32];
+#[cfg(target_arch = "i386")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 6];
+#[cfg(target_arch = "m68k")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 39];
+#[cfg(target_arch = "microblaze")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 18];
+#[cfg(target_arch = "mips")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 13];
+#[cfg(target_arch = "mips64")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 23];
+#[cfg(target_arch = "mipsn32")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 23];
+#[cfg(target_arch = "or1k")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 13];
+#[cfg(target_arch = "powerpc")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 56];
+#[cfg(target_arch = "powerpc64")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [u128; 32];
+#[cfg(target_arch = "s390x")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 18];
+#[cfg(target_arch = "sh")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 15];
+#[cfg(target_arch = "x32")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulonglong; 8];
+#[cfg(target_arch = "x86_64")]
+#[allow(non_camel_case_types)]
+type jmp_buf = [c_ulong; 8];
+
+#[link(name = "setjmp", kind = "static")]
+extern "C" {
+    fn setjmp(buf: jmp_buf) -> c_int;
+}
+#[link(name = "longjmp", kind = "static")]
+extern "C" {
+    fn longjmp(buf: jmp_buf, val: c_int);
+}

+ 2 - 2
src/stdlib/src/lib.rs

@@ -412,10 +412,10 @@ pub extern "C" fn qsort(
 #[no_mangle]
 pub unsafe extern "C" fn rand() -> c_int {
     match RNG {
-        Some(ref mut rng) => rng.gen_range::<c_int>(0, RAND_MAX),
+        Some(ref mut rng) => rng.gen_range(0, RAND_MAX),
         None => {
             let mut rng = XorShiftRng::from_seed([1; 16]);
-            let ret = rng.gen_range::<c_int>(0, RAND_MAX);
+            let ret = rng.gen_range(0, RAND_MAX);
             RNG = Some(rng);
             ret
         }

+ 1 - 1
tests/.gitignore

@@ -26,7 +26,7 @@
 /rename
 /scanf
 /setid
-/setid
+/setjmp
 /sleep
 /sprintf
 /stdlib/a64l

+ 1 - 0
tests/Makefile

@@ -23,6 +23,7 @@ EXPECT_BINS=\
 	rename \
 	rmdir \
 	scanf \
+	setjmp \
 	sleep \
 	sprintf \
 	stdio/fwrite \

+ 0 - 0
tests/expected/setjmp.stderr


+ 2 - 0
tests/expected/setjmp.stdout

@@ -0,0 +1,2 @@
+jumping...
+hi from jump

+ 12 - 0
tests/setjmp.c

@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <setjmp.h>
+
+int main() {
+    jmp_buf buf;
+    if (setjmp(buf)) {
+        puts("hi from jump");
+    } else {
+        puts("jumping...");
+        longjmp(buf, 0);
+    }
+}