From 34a384a128d9630679f9c90bb27eaa0822e5b798 Mon Sep 17 00:00:00 2001
From: Pawel Olzacki <p.olzacki2@samsung.com>
Date: Tue, 17 Jun 2014 09:16:03 +0200
Subject: [PATCH] Added Mipsel architecture support

---
 mk/platform.mk                     | 32 ++++++++++-
 src/libcore/mem.rs                 |  2 +
 src/libgreen/context.rs            |  3 +
 src/liblibc/lib.rs                 |  8 +++
 src/libnative/io/c_unix.rs         | 15 ++++-
 src/librustc/back/mipsel.rs        | 72 ++++++++++++++++++++++++
 src/librustc/driver/config.rs      | 12 ++--
 src/librustc/lib.rs                |  1 +
 src/librustc/middle/trans/adt.rs   |  3 +-
 src/librustc/middle/trans/asm.rs   |  1 +
 src/librustc/middle/trans/base.rs  |  6 +-
 src/librustc/middle/trans/cabi.rs  |  3 +-
 src/librustc/middle/trans/type_.rs |  4 +-
 src/librustrt/libunwind.rs         |  1 +
 src/librustrt/mutex.rs             |  4 ++
 src/librustrt/stack.rs             |  2 +
 src/libstd/os.rs                   |  4 ++
 src/libsyntax/abi.rs               |  3 +-
 src/rt/arch/mipsel/_context.S      | 88 ++++++++++++++++++++++++++++++
 src/rt/arch/mipsel/morestack.S     | 43 +++++++++++++++
 src/rt/arch/mipsel/record_sp.S     | 40 ++++++++++++++
 21 files changed, 331 insertions(+), 16 deletions(-)
 create mode 100644 src/librustc/back/mipsel.rs
 create mode 100644 src/rt/arch/mipsel/_context.S
 create mode 100644 src/rt/arch/mipsel/morestack.S
 create mode 100644 src/rt/arch/mipsel/record_sp.S

diff --git a/mk/platform.mk b/mk/platform.mk
index 1efa1cc5b6d85..3c6296d610aac 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -374,6 +374,36 @@ CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,
 RUSTC_FLAGS_arm-unknown-linux-gnueabi :=
 RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
 
+# mipsel-linux configuration
+CC_mipsel-linux=mipsel-linux-gcc
+CXX_mipsel-linux=mipsel-linux-g++
+CPP_mipsel-linux=mipsel-linux-gcc 
+AR_mipsel-linux=mipsel-linux-ar
+CFG_LIB_NAME_mipsel-linux=lib$(1).so
+CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
+CFG_LIB_GLOB_mipsel-linux=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_mipsel-linux=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_mipsel-linux := -mips32 -mabi=32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_mipsel-linux := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_mipsel-linux := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_mipsel-linux := -shared -fPIC -g -mips32
+CFG_GCCISH_DEF_FLAG_mipsel-linux := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_mipsel-linux := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_mipsel-linux := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_mipsel-linux := .linux.def
+CFG_LLC_FLAGS_mipsel-linux :=
+CFG_INSTALL_NAME_mipsel-linux =
+CFG_LIBUV_LINK_FLAGS_mipsel-linux =
+CFG_EXE_SUFFIX_mipsel-linux :=
+CFG_WINDOWSY_mipsel-linux :=
+CFG_UNIXY_mipsel-linux := 1
+CFG_PATH_MUNGE_mipsel-linux := true
+CFG_LDPATH_mipsel-linux :=
+CFG_RUN_mipsel-linux=
+CFG_RUN_TARG_mipsel-linux=
+RUSTC_FLAGS_mipsel-linux := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
+
+
 # mips-unknown-linux-gnu configuration
 CC_mips-unknown-linux-gnu=mips-linux-gnu-gcc
 CXX_mips-unknown-linux-gnu=mips-linux-gnu-g++
@@ -612,7 +642,7 @@ define CFG_MAKE_TOOLCHAIN
         $$(CFG_GCCISH_DEF_FLAG_$(1))$$(3) $$(2)        \
         $$(call CFG_INSTALL_NAME_$(1),$$(4))
 
-  ifeq ($$(findstring $(HOST_$(1)),arm mips),)
+  ifeq ($$(findstring $(HOST_$(1)),arm mips mipsel),)
 
   # We're using llvm-mc as our assembler because it supports
   # .cfi pseudo-ops on mac
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 237efcd0096d0..a04afd59ecee1 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -470,6 +470,7 @@ mod tests {
     #[cfg(target_arch = "x86")]
     #[cfg(target_arch = "arm")]
     #[cfg(target_arch = "mips")]
+    #[cfg(target_arch = "mipsel")]
     fn size_of_32() {
         assert_eq!(size_of::<uint>(), 4u);
         assert_eq!(size_of::<*uint>(), 4u);
@@ -501,6 +502,7 @@ mod tests {
     #[cfg(target_arch = "x86")]
     #[cfg(target_arch = "arm")]
     #[cfg(target_arch = "mips")]
+    #[cfg(target_arch = "mipsel")]
     fn align_of_32() {
         assert_eq!(align_of::<uint>(), 4u);
         assert_eq!(align_of::<*uint>(), 4u);
diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs
index e6915385a42d5..f11a1d2c66737 100644
--- a/src/libgreen/context.rs
+++ b/src/libgreen/context.rs
@@ -268,12 +268,15 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
 }
 
 #[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
 type Registers = [uint, ..32];
 
 #[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
 fn new_regs() -> Box<Registers> { box {[0, .. 32]} }
 
 #[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
 fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
                          procedure: raw::Procedure, sp: *mut uint) {
     let sp = align_down(sp);
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index 9ed0d50a03e8a..2aa84a337f298 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -463,6 +463,7 @@ pub mod types {
         #[cfg(target_arch = "x86")]
         #[cfg(target_arch = "arm")]
         #[cfg(target_arch = "mips")]
+        #[cfg(target_arch = "mipsel")]
         pub mod arch {
             pub mod c95 {
                 pub type c_char = i8;
@@ -491,6 +492,7 @@ pub mod types {
             }
             #[cfg(target_arch = "x86")]
             #[cfg(target_arch = "mips")]
+            #[cfg(target_arch = "mipsel")]
             pub mod posix88 {
                 pub type off_t = i32;
                 pub type dev_t = u64;
@@ -599,6 +601,7 @@ pub mod types {
                 }
             }
             #[cfg(target_arch = "mips")]
+            #[cfg(target_arch = "mipsel")]
             pub mod posix01 {
                 use types::os::arch::c95::{c_long, c_ulong, time_t};
                 use types::os::arch::posix88::{gid_t, ino_t};
@@ -2209,6 +2212,7 @@ pub mod consts {
         }
 
         #[cfg(target_arch = "mips")]
+        #[cfg(target_arch = "mipsel")]
         pub mod posix88 {
             use types::os::arch::c95::c_int;
             use types::common::c95::c_void;
@@ -2483,6 +2487,7 @@ pub mod consts {
             pub static PTHREAD_STACK_MIN: size_t = 16384;
 
             #[cfg(target_arch = "mips", target_os = "linux")]
+            #[cfg(target_arch = "mipsel", target_os = "linux")]
             pub static PTHREAD_STACK_MIN: size_t = 131072;
 
             pub static CLOCK_REALTIME: c_int = 0;
@@ -2536,6 +2541,7 @@ pub mod consts {
             pub static SHUT_RDWR: c_int = 2;
         }
         #[cfg(target_arch = "mips")]
+        #[cfg(target_arch = "mipsel")]
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
@@ -2604,6 +2610,7 @@ pub mod consts {
             pub static MAP_STACK : c_int = 0x020000;
         }
         #[cfg(target_arch = "mips")]
+        #[cfg(target_arch = "mipsel")]
         pub mod extra {
             use types::os::arch::c95::c_int;
 
@@ -2976,6 +2983,7 @@ pub mod consts {
             pub static PTHREAD_STACK_MIN: size_t = 4096;
 
             #[cfg(target_arch = "mips")]
+            #[cfg(target_arch = "mipsel")]
             #[cfg(target_arch = "x86")]
             #[cfg(target_arch = "x86_64")]
             pub static PTHREAD_STACK_MIN: size_t = 2048;
diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs
index 70fd6310070da..7a52c04849853 100644
--- a/src/libnative/io/c_unix.rs
+++ b/src/libnative/io/c_unix.rs
@@ -23,20 +23,26 @@ use libc;
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub static FIONBIO: libc::c_ulong = 0x8004667e;
-#[cfg(target_os = "linux", not(target_arch = "mips"))]
+#[cfg(target_os = "linux", target_arch = "x86")]
+#[cfg(target_os = "linux", target_arch = "x86_64")]
+#[cfg(target_os = "linux", target_arch = "arm")]
 #[cfg(target_os = "android")]
 pub static FIONBIO: libc::c_ulong = 0x5421;
 #[cfg(target_os = "linux", target_arch = "mips")]
+#[cfg(target_os = "linux", target_arch = "mipsel")]
 pub static FIONBIO: libc::c_ulong = 0x667e;
 
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub static FIOCLEX: libc::c_ulong = 0x20006601;
-#[cfg(target_os = "linux", not(target_arch = "mips"))]
+#[cfg(target_os = "linux", target_arch = "x86")]
+#[cfg(target_os = "linux", target_arch = "x86_64")]
+#[cfg(target_os = "linux", target_arch = "arm")]
 #[cfg(target_os = "android")]
 pub static FIOCLEX: libc::c_ulong = 0x5451;
 #[cfg(target_os = "linux", target_arch = "mips")]
+#[cfg(target_os = "linux", target_arch = "mipsel")]
 pub static FIOCLEX: libc::c_ulong = 0x6601;
 
 #[cfg(target_os = "macos")]
@@ -109,7 +115,9 @@ mod select {
     }
 }
 
-#[cfg(target_os = "linux", not(target_arch = "mips"))]
+#[cfg(target_os = "linux", target_arch = "x86")]
+#[cfg(target_os = "linux", target_arch = "x86_64")]
+#[cfg(target_os = "linux", target_arch = "arm")]
 #[cfg(target_os = "android")]
 mod signal {
     use libc;
@@ -153,6 +161,7 @@ mod signal {
 }
 
 #[cfg(target_os = "linux", target_arch = "mips")]
+#[cfg(target_os = "linux", target_arch = "mipsel")]
 mod signal {
     use libc;
 
diff --git a/src/librustc/back/mipsel.rs b/src/librustc/back/mipsel.rs
new file mode 100644
index 0000000000000..c2c48a41e8fe0
--- /dev/null
+++ b/src/librustc/back/mipsel.rs
@@ -0,0 +1,72 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use back::target_strs;
+use syntax::abi;
+
+pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t {
+    return target_strs::t {
+        module_asm: "".to_string(),
+
+        data_layout: match target_os {
+          abi::OsMacos => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
+          abi::OsiOS => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
+          abi::OsWin32 => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
+          abi::OsLinux => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
+          abi::OsAndroid => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
+          abi::OsFreebsd => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+        },
+
+        target_triple: target_triple,
+
+        cc_args: Vec::new(),
+    };
+}
diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs
index db96330d656fe..95e0af028fa40 100644
--- a/src/librustc/driver/config.rs
+++ b/src/librustc/driver/config.rs
@@ -18,7 +18,7 @@ use driver::session::Session;
 use back;
 use back::link;
 use back::target_strs;
-use back::{arm, x86, x86_64, mips};
+use back::{arm, x86, x86_64, mips, mipsel};
 use middle::lint;
 
 use syntax::abi;
@@ -373,7 +373,8 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         abi::X86 =>    ("little", "x86",    "32"),
         abi::X86_64 => ("little", "x86_64", "64"),
         abi::Arm =>    ("little", "arm",    "32"),
-        abi::Mips =>   ("big",    "mips",   "32")
+        abi::Mips =>   ("big",    "mips",   "32"),
+        abi::Mipsel => ("little", "mipsel", "32")
     };
 
     let fam = match sess.targ_cfg.os {
@@ -452,6 +453,7 @@ static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'stat
     ("xscale", abi::Arm),
     ("thumb",  abi::Arm),
 
+    ("mipsel", abi::Mipsel),
     ("mips",   abi::Mips)];
 
 pub fn build_target_config(sopts: &Options) -> Config {
@@ -470,14 +472,16 @@ pub fn build_target_config(sopts: &Options) -> Config {
       abi::X86 => (ast::TyI32, ast::TyU32),
       abi::X86_64 => (ast::TyI64, ast::TyU64),
       abi::Arm => (ast::TyI32, ast::TyU32),
-      abi::Mips => (ast::TyI32, ast::TyU32)
+      abi::Mips => (ast::TyI32, ast::TyU32),
+      abi::Mipsel => (ast::TyI32, ast::TyU32)
     };
     let target_triple = sopts.target_triple.clone();
     let target_strs = match arch {
       abi::X86 => x86::get_target_strs(target_triple, os),
       abi::X86_64 => x86_64::get_target_strs(target_triple, os),
       abi::Arm => arm::get_target_strs(target_triple, os),
-      abi::Mips => mips::get_target_strs(target_triple, os)
+      abi::Mips => mips::get_target_strs(target_triple, os),
+      abi::Mipsel => mipsel::get_target_strs(target_triple, os)
     };
     Config {
         os: os,
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 680bd667c3f0d..e6f9ae0212497 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -97,6 +97,7 @@ pub mod back {
     pub mod link;
     pub mod lto;
     pub mod mips;
+    pub mod mipsel;
     pub mod rpath;
     pub mod svh;
     pub mod target_strs;
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 1b530ea342491..cbec0125cc579 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -60,7 +60,7 @@ use middle::trans::type_::Type;
 use middle::trans::type_of;
 use middle::ty;
 use middle::ty::Disr;
-use syntax::abi::{X86, X86_64, Arm, Mips};
+use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
 use syntax::ast;
 use syntax::attr;
 use syntax::attr::IntType;
@@ -367,6 +367,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
                 // corresponding to `choose_shortest`.  However, we don't run on those yet...?
                 Arm => at_least_32,
                 Mips => at_least_32,
+                Mipsel => at_least_32,
             }
         }
         attr::ReprAny => {
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 871b75760f1d0..81bb50a83afdf 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -135,6 +135,7 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
 
 #[cfg(target_arch = "arm")]
 #[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
 fn get_clobbers() -> String {
     "".to_string()
 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 4657c8cd13654..6f7a90ad040b9 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -83,7 +83,7 @@ use std::cell::{Cell, RefCell};
 use std::rc::Rc;
 use std::{i8, i16, i32, i64};
 use std::gc::Gc;
-use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
+use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustIntrinsic};
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
@@ -1021,7 +1021,7 @@ pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef,
     let _icx = push_ctxt("call_memcpy");
     let ccx = cx.ccx();
     let key = match ccx.sess().targ_cfg.arch {
-        X86 | Arm | Mips => "llvm.memcpy.p0i8.p0i8.i32",
+        X86 | Arm | Mips | Mipsel => "llvm.memcpy.p0i8.p0i8.i32",
         X86_64 => "llvm.memcpy.p0i8.p0i8.i64"
     };
     let memcpy = ccx.get_intrinsic(&key);
@@ -1065,7 +1065,7 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
     let ccx = b.ccx;
 
     let intrinsic_key = match ccx.sess().targ_cfg.arch {
-        X86 | Arm | Mips => "llvm.memset.p0i8.i32",
+        X86 | Arm | Mips | Mipsel => "llvm.memset.p0i8.i32",
         X86_64 => "llvm.memset.p0i8.i64"
     };
 
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index 02671b1186631..df1347f6d8f10 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -16,7 +16,7 @@ use middle::trans::cabi_x86_64;
 use middle::trans::cabi_arm;
 use middle::trans::cabi_mips;
 use middle::trans::type_::Type;
-use syntax::abi::{X86, X86_64, Arm, Mips};
+use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
 
 #[deriving(Clone, PartialEq)]
 pub enum ArgKind {
@@ -110,5 +110,6 @@ pub fn compute_abi_info(ccx: &CrateContext,
         X86_64 => cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def),
         Arm => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
         Mips => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
+        Mipsel => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
     }
 }
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 5d58500f761a4..0d20b704ed86d 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -16,7 +16,7 @@ use lib::llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 use middle::trans::context::CrateContext;
 
 use syntax::ast;
-use syntax::abi::{X86, X86_64, Arm, Mips};
+use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
 
 use std::c_str::ToCStr;
 use std::mem;
@@ -106,7 +106,7 @@ impl Type {
 
     pub fn int(ccx: &CrateContext) -> Type {
         match ccx.tcx.sess.targ_cfg.arch {
-            X86 | Arm | Mips => Type::i32(ccx),
+            X86 | Arm | Mips | Mipsel => Type::i32(ccx),
             X86_64 => Type::i64(ccx)
         }
     }
diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs
index 2d58c1bee15bd..fe9b2b569c060 100644
--- a/src/librustrt/libunwind.rs
+++ b/src/librustrt/libunwind.rs
@@ -69,6 +69,7 @@ pub static unwinder_private_data_size: int = 20;
 pub static unwinder_private_data_size: int = 5;
 
 #[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
 pub static unwinder_private_data_size: int = 2;
 
 pub struct _Unwind_Exception {
diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs
index ee696f2cf7c08..2bbfcf73917c9 100644
--- a/src/librustrt/mutex.rs
+++ b/src/librustrt/mutex.rs
@@ -415,6 +415,8 @@ mod imp {
         static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
         #[cfg(target_arch = "mips")]
         static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
+        #[cfg(target_arch = "mipsel")]
+        static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
         #[cfg(target_arch = "x86_64")]
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
         #[cfg(target_arch = "x86")]
@@ -423,6 +425,8 @@ mod imp {
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
         #[cfg(target_arch = "mips")]
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+        #[cfg(target_arch = "mipsel")]
+        static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
 
         #[repr(C)]
         pub struct pthread_mutex_t {
diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs
index e6fa845bedc89..b90f1a0f493f4 100644
--- a/src/librustrt/stack.rs
+++ b/src/librustrt/stack.rs
@@ -217,6 +217,7 @@ pub unsafe fn record_sp_limit(limit: uint) {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
+    #[cfg(target_arch = "mipsel")]
     #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         use libc::c_void;
@@ -298,6 +299,7 @@ pub unsafe fn get_sp_limit() -> uint {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
+    #[cfg(target_arch = "mipsel")]
     #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         use libc::c_void;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index f6b1c04dd34c6..25b7befd74e97 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -1726,6 +1726,10 @@ mod arch_consts {
     pub static ARCH: &'static str = "mips";
 }
 
+#[cfg(target_arch = "mipsel")]
+mod arch_consts {
+    pub static ARCH: &'static str = "mipsel";
+}
 
 #[cfg(test)]
 mod tests {
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index 7ff020d6818e1..3d6266fd4c09d 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -41,7 +41,8 @@ pub enum Architecture {
     X86,
     X86_64,
     Arm,
-    Mips
+    Mips,
+    Mipsel
 }
 
 static IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
diff --git a/src/rt/arch/mipsel/_context.S b/src/rt/arch/mipsel/_context.S
new file mode 100644
index 0000000000000..cfe77cc30456b
--- /dev/null
+++ b/src/rt/arch/mipsel/_context.S
@@ -0,0 +1,88 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section	.note.GNU-stack, "", @progbits
+#endif
+
+.text
+.globl rust_swap_registers
+.align 2
+.set nomips16
+.ent rust_swap_registers
+rust_swap_registers:
+        .set noreorder
+        .set nomacro
+        .set noat
+        sw $1, 1 * 4($4)
+        sw $2, 2 * 4($4)
+        sw $3, 3 * 4($4)
+        sw $4, 4 * 4($4)
+        sw $5, 5 * 4($4)
+        sw $6, 6 * 4($4)
+        sw $7, 7 * 4($4)
+
+        sw $8, 8 * 4($4)
+        sw $9, 9 * 4($4)
+        sw $10, 10 * 4($4)
+        sw $11, 11 * 4($4)
+        sw $12, 12 * 4($4)
+        sw $13, 13 * 4($4)
+        sw $14, 14 * 4($4)
+        sw $15, 15 * 4($4)
+
+        sw $16, 16 * 4($4)
+        sw $17, 17 * 4($4)
+        sw $18, 18 * 4($4)
+        sw $19, 19 * 4($4)
+        sw $20, 20 * 4($4)
+        sw $21, 21 * 4($4)
+        sw $22, 22 * 4($4)
+        sw $23, 23 * 4($4)
+
+        sw $24, 24 * 4($4)
+        sw $25, 25 * 4($4)
+        sw $26, 26 * 4($4)
+        sw $27, 27 * 4($4)
+        sw $28, 28 * 4($4)
+        sw $29, 29 * 4($4)
+        sw $30, 30 * 4($4)
+        sw $31, 31 * 4($4)
+
+        lw $1, 1 * 4($5)
+        lw $2, 2 * 4($5)
+        lw $3, 3 * 4($5)
+        lw $4, 4 * 4($5)
+        lw $6, 6 * 4($5)
+        lw $7, 7 * 4($5)
+
+        lw $8, 8 * 4($5)
+        lw $9, 9 * 4($5)
+        lw $10, 10 * 4($5)
+        lw $11, 11 * 4($5)
+        lw $12, 12 * 4($5)
+        lw $13, 13 * 4($5)
+        lw $14, 14 * 4($5)
+        lw $15, 15 * 4($5)
+
+        lw $16, 16 * 4($5)
+        lw $17, 17 * 4($5)
+        lw $18, 18 * 4($5)
+        lw $19, 19 * 4($5)
+        lw $20, 20 * 4($5)
+        lw $21, 21 * 4($5)
+        lw $22, 22 * 4($5)
+        lw $23, 23 * 4($5)
+
+        lw $24, 24 * 4($5)
+        lw $25, 25 * 4($5)
+        lw $26, 26 * 4($5)
+        lw $27, 27 * 4($5)
+        lw $28, 28 * 4($5)
+        lw $29, 29 * 4($5)
+        lw $30, 30 * 4($5)
+        lw $31, 31 * 4($5)
+
+        lw $5, 5 * 4($5)
+
+        jr $31
+        nop
+.end rust_swap_registers
diff --git a/src/rt/arch/mipsel/morestack.S b/src/rt/arch/mipsel/morestack.S
new file mode 100644
index 0000000000000..266933df8c51c
--- /dev/null
+++ b/src/rt/arch/mipsel/morestack.S
@@ -0,0 +1,43 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section        .note.GNU-stack, "", @progbits
+#endif
+
+/* See i386/morestack.S for the lengthy, general explanation. */
+
+.text
+
+.globl rust_stack_exhausted
+.globl __morestack
+
+.hidden __morestack
+
+.cfi_startproc
+.set nomips16
+.ent __morestack
+__morestack:
+        .set noreorder
+        .set nomacro
+
+        addiu $29, $29, -4
+        sw $30, 0($29)
+
+        // 16 = 4 (current) + 12 (previous)
+        .cfi_def_cfa_offset 16
+        .cfi_offset 31, -4
+        .cfi_offset 30, -16
+
+        move $30, $29
+        .cfi_def_cfa_register 30
+
+        // O32 ABI always reserves 16 bytes for arguments
+        addiu $29, $29, -16
+
+        lw $25, %call16(rust_stack_exhausted)($28)
+        jalr $25
+        nop
+
+        // the above function make sure that we never get here
+
+.end __morestack
+.cfi_endproc
diff --git a/src/rt/arch/mipsel/record_sp.S b/src/rt/arch/mipsel/record_sp.S
new file mode 100644
index 0000000000000..a6dfa04edbbd7
--- /dev/null
+++ b/src/rt/arch/mipsel/record_sp.S
@@ -0,0 +1,40 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section	.note.GNU-stack, "", @progbits
+#endif
+
+.text
+
+.globl record_sp_limit
+.align 2
+.set nomips16
+.ent record_sp_limit
+record_sp_limit:
+        .set noreorder
+        .set nomacro
+        .set push
+        .set mips32r2
+        rdhwr $3, $29
+        .set pop
+        addiu $3, $3, -0x7004
+        sw $4, 0($3)
+        jr $31
+        nop
+.end record_sp_limit
+
+.globl get_sp_limit
+.align 2
+.set nomips16
+.ent get_sp_limit
+get_sp_limit:
+        .set noreorder
+        .set nomacro
+        .set push
+        .set mips32r2
+        rdhwr $3, $29
+        .set pop
+        addiu $3, $3, -0x7004
+        lw $2, 0($3)
+        jr $31
+        nop
+.end get_sp_limit