diff --git a/lib/Target/Mips/Mips16InstrFormats.td b/lib/Target/Mips/Mips16InstrFormats.td
index 3672ea8..d93ba03 100644
--- a/lib/Target/Mips/Mips16InstrFormats.td
+++ b/lib/Target/Mips/Mips16InstrFormats.td
@@ -61,19 +61,16 @@ def FrmEXT_I816       : Format16<20>;
 def FrmEXT_I8_SVRS16  : Format16<21>;
 def FrmOther16        : Format16<22>; // Instruction w/ a custom format
 
-// Generic Mips 16 Format
-class MipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern,
+// Base class for Mips 16 Format
+// This class does not depend on the instruction size
+//
+class MipsInst16_Base<dag outs, dag ins, string asmstr, list<dag> pattern,
                  InstrItinClass itin, Format16 f>: Instruction
 {
-  field bits<16> Inst;
   Format16 Form = f;
 
   let Namespace = "Mips";
 
-  bits<5> Opcode = 0;
-
-  // Top 6 bits are the 'opcode' field
-  let Inst{15-11} = Opcode;
 
   let OutOperandList = outs;
   let InOperandList  = ins;
@@ -89,42 +86,42 @@ class MipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern,
 
   // TSFlags layout should be kept in sync with MipsInstrInfo.h.
   let TSFlags{4-0}   = FormBits;
+
+  let Predicates = [InMips16Mode];
 }
 
 //
-// TBD. Maybe MipsInst16 and Mips16_EXTEND should be derived from a single
-// base class
+// Generic Mips 16 Format
 //
-
-class MipsInst16_EXTEND<dag outs, dag ins, string asmstr, list<dag> pattern,
-                        InstrItinClass itin, Format16 f>: Instruction
+class MipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern,
+                 InstrItinClass itin, Format16 f>:
+        MipsInst16_Base<outs, ins, asmstr, pattern, itin, f>
 {
-  field bits<32> Inst;
-  Format16 Form = f;
-
-  let Namespace = "Mips";
-
+  field bits<16> Inst;
   bits<5> Opcode = 0;
-  bits<5> extend;
 
   // Top 6 bits are the 'opcode' field
-  let Inst{31-27} = extend;
   let Inst{15-11} = Opcode;
+}
 
-  let OutOperandList = outs;
-  let InOperandList  = ins;
+//
+// For 32 bit extended instruction forms.
+//
+class MipsInst16_32<dag outs, dag ins, string asmstr, list<dag> pattern,
+                    InstrItinClass itin, Format16 f>:
+        MipsInst16_Base<outs, ins, asmstr, pattern, itin, f>
+{
+  field bits<32> Inst;
 
-  let AsmString   = asmstr;
-  let Pattern     = pattern;
-  let Itinerary   = itin;
+}
 
-  //
-  // Attributes specific to Mips instructions...
-  //
-  bits<5> FormBits = Form.Value;
+class MipsInst16_EXTEND<dag outs, dag ins, string asmstr, list<dag> pattern,
+                        InstrItinClass itin, Format16 f>:
+        MipsInst16_32<outs, ins, asmstr, pattern, itin, f>
+{
+
+  let Inst{31-27} = 0b11110;
 
-  // TSFlags layout should be kept in sync with MipsInstrInfo.h.
-  let TSFlags{4-0}   = FormBits;
 }
 
 
@@ -189,6 +186,28 @@ class FRR16<bits<5> _funct, dag outs, dag ins, string asmstr,
   let Inst{4-0}   = funct;
 }
 
+
+//
+// J(AL)R(C) subformat
+//
+class FRR16_JALRC<dag outs, dag ins, string asmstr,
+            list<dag> pattern, InstrItinClass itin>:
+            MipsInst16<outs, ins, asmstr, pattern, itin, FrmRR16>
+{
+  bits<3>  rx;
+  bits<1>  nd;
+  bits<1>  l;
+  bits<1>  ra;
+
+  let Opcode = 0b11101;
+
+  let Inst{10-8} = rx;
+  let Inst{7} = nd;
+  let Inst{6} = l;
+  let Inst{5} = ra;
+  let Inst{4-0} = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // Format RRI instruction class in Mips : <|opcode|rx|ry|immed|>
 //===----------------------------------------------------------------------===//
@@ -376,15 +395,15 @@ class FI8_SVRS16<bits<5> op, bits<3> _SVRS, dag outs, dag ins, string asmstr,
 
 class FJAL16<bits<5> op, bits<1> _X, dag outs, dag ins, string asmstr,
              list<dag> pattern, InstrItinClass itin>:
-             MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmJAL16>
+             MipsInst16_32<outs, ins, asmstr, pattern, itin, FrmJAL16>
 {
   bits<1> X;
   bits<26> immed26;
 
   
-  let Opcode = op;
   let X = _X;
 
+  let Inst{31-27} = 0b00011;
   let Inst{26} = X;
   let Inst{25-21} = immed26{20-16};
   let Inst{20-16} = immed26{25-21};
@@ -398,14 +417,13 @@ class FJAL16<bits<5> op, bits<1> _X, dag outs, dag ins, string asmstr,
 //     <|opcode|immed10:5|immed15:1|op|0|0|0|0|0|0|immed4:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_I16<bits<5> op, bits<5> _eop, dag outs, dag ins, string asmstr,
+class FEXT_I16<bits<5> _eop, dag outs, dag ins, string asmstr,
                list<dag> pattern, InstrItinClass itin>:
                MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_I16>
 {
   bits<16> immed16;
   bits<5> eop;
   
-  let Opcode = op;
   let eop = _eop;
 
   let Inst{26-21} = immed16{10-5};
@@ -439,7 +457,6 @@ class FASMACRO16<bits<5> op, dag outs, dag ins, string asmstr,
   bits<3> p1;
   bits<5> p0;
   
-  let Opcode = op;
 
   let Inst{26-24} = select;
   let Inst{23-21} = p4;
@@ -457,21 +474,20 @@ class FASMACRO16<bits<5> op, dag outs, dag ins, string asmstr,
 //    <|opcode|immed10:5|immed15:11|op|rx|0|0|0|immed4:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_RI16<bits<5> op, bits<5> _eop, dag outs, dag ins, string asmstr,
+class FEXT_RI16<bits<5> _op, dag outs, dag ins, string asmstr,
                 list<dag> pattern, InstrItinClass itin>:
                 MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, 
                                   FrmEXT_RI16>
 {
   bits<16> immed16;
-  bits<5> eop;
+  bits<5> op;
   bits<3> rx;
   
-  let Opcode = op;
-  let eop = _eop;
+  let op = _op;
 
   let Inst{26-21} = immed16{10-5};
   let Inst{20-16} = immed16{15-11};
-  let Inst{15-11} = eop;
+  let Inst{15-11} = op;
   let Inst{10-8} = rx;
   let Inst{7-5} = 0;
   let Inst{4-0} = immed16{4-0}; 
@@ -483,22 +499,19 @@ class FEXT_RI16<bits<5> op, bits<5> _eop, dag outs, dag ins, string asmstr,
 //     <|opcode|immed10:5|immed15:11|op|rx|ry|immed4:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_RRI16<bits<5> op, bits<5> _eop, dag outs, dag ins, string asmstr,
+class FEXT_RRI16<bits<5> _op, dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin>:
                  MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, 
                                    FrmEXT_RRI16>
 {
   bits<16> immed16;
-  bits<5> eop;
   bits<3> rx;
   bits<3> ry;
-  
-  let Opcode = op;
-  let eop = _eop;
+
 
   let Inst{26-21} = immed16{10-5};
   let Inst{20-16} = immed16{15-11};
-  let Inst{15-11} = eop;
+  let Inst{15-11} = _op;
   let Inst{10-8} = rx;
   let Inst{7-5} = ry;
   let Inst{4-0} = immed16{4-0}; 
@@ -510,23 +523,21 @@ class FEXT_RRI16<bits<5> op, bits<5> _eop, dag outs, dag ins, string asmstr,
 //    <|opcode|immed10:4|immed14:11|RRI-A|rx|ry|f|immed3:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_RRI_A16<bits<5> op, bits<1> _f, dag outs, dag ins, string asmstr,
+class FEXT_RRI_A16<bits<1> _f, dag outs, dag ins, string asmstr,
                    list<dag> pattern, InstrItinClass itin>:
                    MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, 
                                      FrmEXT_RRI_A16>
 {
   bits<15> immed15;
-  bits<5> RRI_A;
   bits<3> rx;
   bits<3> ry;
   bits<1> f;
   
-  let Opcode = op;
   let f = _f;
 
   let Inst{26-20} = immed15{10-4};
   let Inst{19-16} = immed15{14-11};
-  let Inst{15-11} = RRI_A;
+  let Inst{15-11} = 0b01000;
   let Inst{10-8} = rx;
   let Inst{7-5} = ry;
   let Inst{4} = f;
@@ -545,18 +556,16 @@ class FEXT_SHIFT16<bits<5> op, bits<2> _f, dag outs, dag ins, string asmstr,
                                      FrmEXT_SHIFT16>
 {
   bits<6> sa6;
-  bits<5> shift;
   bits<3> rx;
   bits<3> ry;
   bits<2> f;
   
-  let Opcode = op;
   let f = _f;
 
   let Inst{26-22} = sa6{4-0};
   let Inst{21} = sa6{5};
   let Inst{20-16} = 0;
-  let Inst{15-11} = shift;
+  let Inst{15-11} = 0b00110;
   let Inst{10-8} = rx;
   let Inst{7-5} = ry;
   let Inst{4-2} = 0;
@@ -569,7 +578,7 @@ class FEXT_SHIFT16<bits<5> op, bits<2> _f, dag outs, dag ins, string asmstr,
 //    <|opcode|immed10:5|immed15:11|I8|funct|0|immed4:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_I816<bits<5> op, bits<3> _funct, dag outs, dag ins, string asmstr,
+class FEXT_I816<bits<3> _funct, dag outs, dag ins, string asmstr,
                 list<dag> pattern, InstrItinClass itin>:
                 MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, 
                                   FrmEXT_I816>
@@ -578,7 +587,6 @@ class FEXT_I816<bits<5> op, bits<3> _funct, dag outs, dag ins, string asmstr,
   bits<5> I8;
   bits<3> funct;
   
-  let Opcode = op;
   let funct = _funct;
 
   let Inst{26-21} = immed16{10-5};
@@ -595,7 +603,7 @@ class FEXT_I816<bits<5> op, bits<3> _funct, dag outs, dag ins, string asmstr,
 //    <|opcode|xsregs|framesize7:4|aregs|I8|SVRS|s|ra|s0|s1|framesize3:0>
 //===----------------------------------------------------------------------===//
 
-class FEXT_I8_SVRS16<bits<5> op, dag outs, dag ins, string asmstr,
+class FEXT_I8_SVRS16<dag outs, dag ins, string asmstr,
                      list<dag> pattern, InstrItinClass itin>:
                      MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, 
                                        FrmI8_SVRS16>
@@ -610,7 +618,6 @@ class FEXT_I8_SVRS16<bits<5> op, dag outs, dag ins, string asmstr,
   bits<1> s0;
   bits<1> s1;
   
-  let Opcode = op;
 
   let Inst{26-24} = xsregs;
   let Inst{23-20} = framesize{7-4};
diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td
index 7cbf2d4..fc53093 100644
--- a/lib/Target/Mips/Mips16InstrInfo.td
+++ b/lib/Target/Mips/Mips16InstrInfo.td
@@ -12,7 +12,23 @@
 //===----------------------------------------------------------------------===//
 
 let isReturn=1, isTerminator=1, hasDelaySlot=1, isCodeGenOnly=1,
-    isBarrier=1, hasCtrlDep=1, rx=0b000, ry=0b001 in
-def RET16 : FRR16 <0, (outs), (ins CPURAReg:$target),
-                   "jr\t$target", [(MipsRet CPURAReg:$target)], IIBranch>,
-            Requires<[InMips16Mode]>;
+    isBarrier=1, hasCtrlDep=1, rx=0, nd=0, l=0, ra=0  in
+def RET16 : FRR16_JALRC < (outs), (ins CPURAReg:$target),
+                   "jr\t$target", [(MipsRet CPURAReg:$target)], IIBranch>;
+
+// As stack alignment is always done with addiu, we need a 16-bit immediate
+let Defs = [SP], Uses = [SP] in {
+def ADJCALLSTACKDOWN16 : MipsPseudo16<(outs), (ins uimm16:$amt),
+                                  "!ADJCALLSTACKDOWN $amt",
+                                  [(callseq_start timm:$amt)]>;
+def ADJCALLSTACKUP16   : MipsPseudo16<(outs), (ins uimm16:$amt1, uimm16:$amt2),
+                                  "!ADJCALLSTACKUP $amt1",
+                                  [(callseq_end timm:$amt1, timm:$amt2)]>;
+}
+
+
+// Jump and Link (Call)
+let isCall=1, hasDelaySlot=1, nd=0, l=0, ra=0 in
+def JumpLinkReg16:
+    FRR16_JALRC<(outs), (ins CPU16Regs:$rs, variable_ops),
+       "jalr \t$rs", [(MipsJmpLink CPU16Regs:$rs)], IIBranch>;
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 7335858..6ea2692 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -103,6 +103,11 @@ MipsTargetLowering(MipsTargetMachine &TM)
   if (HasMips64)
     addRegisterClass(MVT::i64, &Mips::CPU64RegsRegClass);
 
+  if (Subtarget->inMips16Mode()) {
+    addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);
+    addRegisterClass(MVT::i32, &Mips::CPURARegRegClass);
+  }
+
   if (!TM.Options.UseSoftFloat) {
     addRegisterClass(MVT::f32, &Mips::FGR32RegClass);
 
