Adding the MicroBlaze backend.

The MicroBlaze is a highly configurable 32-bit soft-microprocessor for
use on Xilinx FPGAs. For more information see:
http://www.xilinx.com/tools/microblaze.htm
http://en.wikipedia.org/wiki/MicroBlaze

The current LLVM MicroBlaze backend generates assembly which can be
compiled using the an appropriate binutils assembler.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96969 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGen/MBlaze/brind.ll b/test/CodeGen/MBlaze/brind.ll
new file mode 100644
index 0000000..7798e0f
--- /dev/null
+++ b/test/CodeGen/MBlaze/brind.ll
@@ -0,0 +1,73 @@
+; Ensure that the select instruction is supported and is lowered to 
+; some sort of branch instruction.
+;
+; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
+
+declare i32 @printf(i8*, ...)
+@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
+
+@BLKS = private constant [5 x i8*]
+    [ i8* blockaddress(@brind, %L1),
+      i8* blockaddress(@brind, %L2),
+      i8* blockaddress(@brind, %L3),
+      i8* blockaddress(@brind, %L4),
+      i8* blockaddress(@brind, %L5) ]
+
+define i32 @brind(i32 %a, i32 %b)
+{
+    ; CHECK:        brind:
+entry:
+    br label %loop
+
+loop:
+    %tmp.0 = phi i32 [ 0, %entry ], [ %tmp.8, %finish ]
+    %dst.0 = getelementptr [5 x i8*]* @BLKS, i32 0, i32 %tmp.0
+    %dst.1 = load i8** %dst.0
+    indirectbr i8* %dst.1, [ label %L1,
+                             label %L2,
+                             label %L3,
+                             label %L4,
+                             label %L5 ]
+    ; CHECK:        br {{r[0-9]*}}
+
+L1:
+    %tmp.1 = add i32 %a, %b
+    br label %finish
+    ; CHECK:        br
+
+L2:
+    %tmp.2 = sub i32 %a, %b
+    br label %finish
+    ; CHECK:        br
+
+L3:
+    %tmp.3 = mul i32 %a, %b
+    br label %finish
+    ; CHECK:        br
+
+L4:
+    %tmp.4 = sdiv i32 %a, %b
+    br label %finish
+    ; CHECK:        br
+
+L5:
+    %tmp.5 = srem i32 %a, %b
+    br label %finish
+    ; CHECK:        br
+
+finish:
+    %tmp.6 = phi i32 [ %tmp.1, %L1 ],
+                     [ %tmp.2, %L2 ],
+                     [ %tmp.3, %L3 ],
+                     [ %tmp.4, %L4 ],
+                     [ %tmp.5, %L5 ]
+
+    call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0),
+                                 i32 %tmp.6)
+
+    %tmp.7 = add i32 %tmp.0, 1
+    %tmp.8 = urem i32 %tmp.7, 5
+
+    br label %loop
+    ; CHECK:        br
+}
diff --git a/test/CodeGen/MBlaze/callind.ll b/test/CodeGen/MBlaze/callind.ll
new file mode 100644
index 0000000..bfc8d00
--- /dev/null
+++ b/test/CodeGen/MBlaze/callind.ll
@@ -0,0 +1,80 @@
+; Ensure that indirect calls work and that they are lowered to some
+; sort of branch and link instruction.
+;
+; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
+
+declare i32 @printf(i8*, ...)
+@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
+
+@FUNS = private constant [5 x i32 (i32,i32)*]
+    [ i32 (i32,i32)* @doadd,
+      i32 (i32,i32)* @dosub,
+      i32 (i32,i32)* @domul,
+      i32 (i32,i32)* @dodiv,
+      i32 (i32,i32)* @dorem ]
+
+define i32 @doadd(i32 %a, i32 %b)
+{
+    ; CHECK:        doadd:
+    %tmp.0 = add i32 %a, %b
+    ret i32 %tmp.0
+    ; CHECK:        rtsd
+}
+
+define i32 @dosub(i32 %a, i32 %b)
+{
+    ; CHECK:        dosub:
+    %tmp.0 = sub i32 %a, %b
+    ret i32 %tmp.0
+    ; CHECK:        rtsd
+}
+
+define i32 @domul(i32 %a, i32 %b)
+{
+    ; CHECK:        domul:
+    %tmp.0 = mul i32 %a, %b
+    ret i32 %tmp.0
+    ; CHECK:        rtsd
+}
+
+define i32 @dodiv(i32 %a, i32 %b)
+{
+    ; CHECK:        dodiv:
+    %tmp.0 = sdiv i32 %a, %b
+    ret i32 %tmp.0
+    ; CHECK:        rtsd
+}
+
+define i32 @dorem(i32 %a, i32 %b)
+{
+    ; CHECK:        dorem:
+    %tmp.0 = srem i32 %a, %b
+    ret i32 %tmp.0
+    ; CHECK:        rtsd
+}
+
+define i32 @callind(i32 %a, i32 %b)
+{
+    ; CHECK:        callind:
+entry:
+    br label %loop
+
+loop:
+    %tmp.0 = phi i32 [ 0, %entry ], [ %tmp.3, %loop ]
+    %dst.0 = getelementptr [5 x i32 (i32,i32)*]* @FUNS, i32 0, i32 %tmp.0
+    %dst.1 = load i32 (i32,i32)** %dst.0
+    %tmp.1 = call i32 %dst.1(i32 %a, i32 %b)
+    ; CHECK-NOT:    brli
+    ; CHECK-NOT:    brlai
+    ; CHECK:        brl
+
+    call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0),
+                                 i32 %tmp.1)
+    ; CHECK:        brl
+
+    %tmp.2 = add i32 %tmp.0, 1
+    %tmp.3 = urem i32 %tmp.2, 5
+
+    br label %loop
+    ; CHECK:        br
+}
diff --git a/test/CodeGen/MBlaze/cc.ll b/test/CodeGen/MBlaze/cc.ll
new file mode 100644
index 0000000..de55728
--- /dev/null
+++ b/test/CodeGen/MBlaze/cc.ll
@@ -0,0 +1,315 @@
+; Test some of the calling convention lowering done by the MBlaze backend.
+; We test that integer values are passed in the correct registers and
+; returned in the correct registers. Additionally, we test that the stack
+; is used as appropriate for passing arguments that cannot be placed into
+; registers.
+;
+; RUN: llc < %s -march=mblaze | FileCheck %s
+
+declare i32 @printf(i8*, ...)
+@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
+
+define void @params0_noret() {
+    ; CHECK:        params0_noret:
+    ret void
+    ; CHECK-NOT:    {{.* r3, r0, 1}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i8 @params0_8bitret() {
+    ; CHECK:        params0_8bitret:
+    ret i8 1
+    ; CHECK:        {{.* r3, r0, 1}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i16 @params0_16bitret() {
+    ; CHECK:        params0_16bitret:
+    ret i16 1
+    ; CHECK:        {{.* r3, r0, 1}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params0_32bitret() {
+    ; CHECK:        params0_32bitret:
+    ret i32 1
+    ; CHECK:        {{.* r3, r0, 1}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i64 @params0_64bitret() {
+    ; CHECK:        params0_64bitret:
+    ret i64 1
+    ; CHECK:        {{.* r3, r0, .*}}
+    ; CHECK:        {{.* r4, r0, 1}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params1_32bitret(i32 %a) {
+    ; CHECK:        params1_32bitret:
+    ret i32 %a
+    ; CHECK:        {{.* r3, r5, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params2_32bitret(i32 %a, i32 %b) {
+    ; CHECK:        params2_32bitret:
+    ret i32 %b
+    ; CHECK:        {{.* r3, r6, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params3_32bitret(i32 %a, i32 %b, i32 %c) {
+    ; CHECK:        params3_32bitret:
+    ret i32 %c
+    ; CHECK:        {{.* r3, r7, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params4_32bitret(i32 %a, i32 %b, i32 %c, i32 %d) {
+    ; CHECK:        params4_32bitret:
+    ret i32 %d
+    ; CHECK:        {{.* r3, r8, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params5_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
+    ; CHECK:        params5_32bitret:
+    ret i32 %e
+    ; CHECK:        {{.* r3, r9, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params6_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
+    ; CHECK:        params6_32bitret:
+    ret i32 %f
+    ; CHECK:        {{.* r3, r10, r0}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params7_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+                             i32 %g) {
+    ; CHECK:        params7_32bitret:
+    ret i32 %g
+    ; CHECK:        {{lwi? r3, r1, 8}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params8_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+                             i32 %g, i32 %h) {
+    ; CHECK:        params8_32bitret:
+    ret i32 %h
+    ; CHECK:        {{lwi? r3, r1, 12}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params9_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+                             i32 %g, i32 %h, i32 %i) {
+    ; CHECK:        params9_32bitret:
+    ret i32 %i
+    ; CHECK:        {{lwi? r3, r1, 16}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define i32 @params10_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+                              i32 %g, i32 %h, i32 %i, i32 %j) {
+    ; CHECK:        params10_32bitret:
+    ret i32 %j
+    ; CHECK:        {{lwi? r3, r1, 20}}
+    ; CHECK-NOT:    {{.* r4, .*, .*}}
+    ; CHECK:        rtsd
+}
+
+define void @testing() {
+    %MSG.1 = getelementptr [13 x i8]* @MSG, i32 0, i32 0
+
+    call void @params0_noret()
+    ; CHECK:        brlid
+
+    %tmp.1 = call i8 @params0_8bitret()
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i8 %tmp.1)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.2 = call i16 @params0_16bitret()
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i16 %tmp.2)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.3 = call i32 @params0_32bitret()
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.3)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.4 = call i64 @params0_64bitret()
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i64 %tmp.4)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK:        {{.* r7, r4, r0}}
+    ; CHECK:        brlid
+
+    %tmp.5 = call i32 @params1_32bitret(i32 1)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.5)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.6 = call i32 @params2_32bitret(i32 1, i32 2)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.6)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.7 = call i32 @params3_32bitret(i32 1, i32 2, i32 3)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.7)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.8 = call i32 @params4_32bitret(i32 1, i32 2, i32 3, i32 4)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.8)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.9 = call i32 @params5_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.9)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.10 = call i32 @params6_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
+                                         i32 6)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        {{.* r10, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.10)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.11 = call i32 @params7_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
+                                         i32 6, i32 7)
+    ; CHECK:        {{swi? .*, r1, 4}}
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        {{.* r10, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.11)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.12 = call i32 @params8_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
+                                         i32 6, i32 7, i32 8)
+    ; CHECK:        {{swi? .*, r1, 4}}
+    ; CHECK:        {{swi? .*, r1, 8}}
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        {{.* r10, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.12)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.13 = call i32 @params9_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
+                                         i32 6, i32 7, i32 8, i32 9)
+    ; CHECK:        {{swi? .*, r1, 4}}
+    ; CHECK:        {{swi? .*, r1, 8}}
+    ; CHECK:        {{swi? .*, r1, 12}}
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        {{.* r10, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.13)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    %tmp.14 = call i32 @params10_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
+                                          i32 6, i32 7, i32 8, i32 9, i32 10)
+    ; CHECK:        {{swi? .*, r1, 4}}
+    ; CHECK:        {{swi? .*, r1, 8}}
+    ; CHECK:        {{swi? .*, r1, 12}}
+    ; CHECK:        {{swi? .*, r1, 16}}
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, .*, .*}}
+    ; CHECK:        {{.* r7, .*, .*}}
+    ; CHECK:        {{.* r8, .*, .*}}
+    ; CHECK:        {{.* r9, .*, .*}}
+    ; CHECK:        {{.* r10, .*, .*}}
+    ; CHECK:        brlid
+    call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.14)
+    ; CHECK:        {{.* r5, .*, .*}}
+    ; CHECK:        {{.* r6, r3, r0}}
+    ; CHECK-NOT:    {{.* r7, .*, .*}}
+    ; CHECK:        brlid
+
+    ret void
+}
diff --git a/test/CodeGen/MBlaze/dg.exp b/test/CodeGen/MBlaze/dg.exp
new file mode 100644
index 0000000..bfd5e47
--- /dev/null
+++ b/test/CodeGen/MBlaze/dg.exp
@@ -0,0 +1,5 @@
+load_lib llvm.exp
+
+if { [llvm_supports_target MBlaze] } {
+  RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
+}
diff --git a/test/CodeGen/MBlaze/div.ll b/test/CodeGen/MBlaze/div.ll
new file mode 100644
index 0000000..fae9830
--- /dev/null
+++ b/test/CodeGen/MBlaze/div.ll
@@ -0,0 +1,75 @@
+; Ensure that multiplication is lowered to function calls when the multiplier
+; unit is not available in the hardware and that function calls are not used
+; when the multiplier unit is available in the hardware.
+;
+; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
+; RUN: llc < %s -march=mblaze -mattr=+div | FileCheck -check-prefix=DIV %s
+
+define i8 @test_i8(i8 %a, i8 %b) {
+    ; FUN:        test_i8:
+    ; DIV:        test_i8:
+
+    %tmp.1 = udiv i8 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV:        idivu
+
+    %tmp.2 = sdiv i8 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV-NOT:    idivu
+    ; DIV:        idiv
+
+    %tmp.3 = add i8 %tmp.1, %tmp.2
+    ret i8 %tmp.3
+    ; FUN:        rtsd
+    ; DIV:        rtsd
+}
+
+define i16 @test_i16(i16 %a, i16 %b) {
+    ; FUN:        test_i16:
+    ; DIV:        test_i16:
+
+    %tmp.1 = udiv i16 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV:        idivu
+
+    %tmp.2 = sdiv i16 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV-NOT:    idivu
+    ; DIV:        idiv
+
+    %tmp.3 = add i16 %tmp.1, %tmp.2
+    ret i16 %tmp.3
+    ; FUN:        rtsd
+    ; DIV:        rtsd
+}
+
+define i32 @test_i32(i32 %a, i32 %b) {
+    ; FUN:        test_i32:
+    ; DIV:        test_i32:
+
+    %tmp.1 = udiv i32 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV:        idivu
+
+    %tmp.2 = sdiv i32 %a, %b
+    ; FUN-NOT:    idiv
+    ; FUN:        brlid
+    ; DIV-NOT:    brlid
+    ; DIV-NOT:    idivu
+    ; DIV:        idiv
+
+    %tmp.3 = add i32 %tmp.1, %tmp.2
+    ret i32 %tmp.3
+    ; FUN:        rtsd
+    ; DIV:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/fpu.ll b/test/CodeGen/MBlaze/fpu.ll
new file mode 100644
index 0000000..83f4d83
--- /dev/null
+++ b/test/CodeGen/MBlaze/fpu.ll
@@ -0,0 +1,66 @@
+; Ensure that floating point operations are lowered to function calls when the
+; FPU is not available in the hardware and that function calls are not used
+; when the FPU is available in the hardware.
+;
+; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
+; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s
+
+define float @test_add(float %a, float %b) {
+    ; FUN:        test_add:
+    ; FPU:        test_add:
+
+    %tmp.1 = fadd float %a, %b
+    ; FUN-NOT:    fadd
+    ; FUN:        brlid
+    ; FPU-NOT:    brlid
+    ; FPU:        fadd
+
+    ret float %tmp.1
+    ; FUN:        rtsd
+    ; FPU:        rtsd
+}
+
+define float @test_sub(float %a, float %b) {
+    ; FUN:        test_sub:
+    ; FPU:        test_sub:
+
+    %tmp.1 = fsub float %a, %b
+    ; FUN-NOT:    frsub
+    ; FUN:        brlid
+    ; FPU-NOT:    brlid
+    ; FPU:        frsub
+
+    ret float %tmp.1
+    ; FUN:        rtsd
+    ; FPU:        rtsd
+}
+
+define float @test_mul(float %a, float %b) {
+    ; FUN:        test_mul:
+    ; FPU:        test_mul:
+
+    %tmp.1 = fmul float %a, %b
+    ; FUN-NOT:    fmul
+    ; FUN:        brlid
+    ; FPU-NOT:    brlid
+    ; FPU:        fmul
+
+    ret float %tmp.1
+    ; FUN:        rtsd
+    ; FPU:        rtsd
+}
+
+define float @test_div(float %a, float %b) {
+    ; FUN:        test_div:
+    ; FPU:        test_div:
+
+    %tmp.1 = fdiv float %a, %b
+    ; FUN-NOT:    fdiv
+    ; FUN:        brlid
+    ; FPU-NOT:    brlid
+    ; FPU:        fdiv
+
+    ret float %tmp.1
+    ; FUN:        rtsd
+    ; FPU:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/fsl.ll b/test/CodeGen/MBlaze/fsl.ll
new file mode 100644
index 0000000..f9c6205
--- /dev/null
+++ b/test/CodeGen/MBlaze/fsl.ll
@@ -0,0 +1,323 @@
+; Ensure that the FSL instrinsic instruction generate single FSL instructions
+; at the machine level. Additionally, ensure that dynamic values use the
+; dynamic version of the instructions and that constant values use the
+; constant version of the instructions.
+;
+; RUN: llc < %s -march=mblaze | FileCheck %s
+
+declare i32 @llvm.mblaze.fsl.get(i32 %port)
+declare i32 @llvm.mblaze.fsl.aget(i32 %port)
+declare i32 @llvm.mblaze.fsl.cget(i32 %port)
+declare i32 @llvm.mblaze.fsl.caget(i32 %port)
+declare i32 @llvm.mblaze.fsl.eget(i32 %port)
+declare i32 @llvm.mblaze.fsl.eaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.ecget(i32 %port)
+declare i32 @llvm.mblaze.fsl.ecaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.nget(i32 %port)
+declare i32 @llvm.mblaze.fsl.naget(i32 %port)
+declare i32 @llvm.mblaze.fsl.ncget(i32 %port)
+declare i32 @llvm.mblaze.fsl.ncaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.neget(i32 %port)
+declare i32 @llvm.mblaze.fsl.neaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.necget(i32 %port)
+declare i32 @llvm.mblaze.fsl.necaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tget(i32 %port)
+declare i32 @llvm.mblaze.fsl.taget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tcget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tcaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.teget(i32 %port)
+declare i32 @llvm.mblaze.fsl.teaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tecget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tecaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tnget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tnaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tncget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tncaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tneget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tneaget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tnecget(i32 %port)
+declare i32 @llvm.mblaze.fsl.tnecaget(i32 %port)
+
+declare void @llvm.mblaze.fsl.put(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.aput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.cput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.caput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.nput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.naput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port)
+declare void @llvm.mblaze.fsl.tput(i32 %port)
+declare void @llvm.mblaze.fsl.taput(i32 %port)
+declare void @llvm.mblaze.fsl.tcput(i32 %port)
+declare void @llvm.mblaze.fsl.tcaput(i32 %port)
+declare void @llvm.mblaze.fsl.tnput(i32 %port)
+declare void @llvm.mblaze.fsl.tnaput(i32 %port)
+declare void @llvm.mblaze.fsl.tncput(i32 %port)
+declare void @llvm.mblaze.fsl.tncaput(i32 %port)
+
+define i32 @fsl_get(i32 %port)
+{
+    ; CHECK:        fsl_get:
+    %v0  = call i32 @llvm.mblaze.fsl.get(i32 %port)
+    ; CHECK:        getd
+    %v1  = call i32 @llvm.mblaze.fsl.aget(i32 %port)
+    ; CHECK-NEXT:   agetd
+    %v2  = call i32 @llvm.mblaze.fsl.cget(i32 %port)
+    ; CHECK-NEXT:   cgetd
+    %v3  = call i32 @llvm.mblaze.fsl.caget(i32 %port)
+    ; CHECK-NEXT:   cagetd
+    %v4  = call i32 @llvm.mblaze.fsl.eget(i32 %port)
+    ; CHECK-NEXT:   egetd
+    %v5  = call i32 @llvm.mblaze.fsl.eaget(i32 %port)
+    ; CHECK-NEXT:   eagetd
+    %v6  = call i32 @llvm.mblaze.fsl.ecget(i32 %port)
+    ; CHECK-NEXT:   ecgetd
+    %v7  = call i32 @llvm.mblaze.fsl.ecaget(i32 %port)
+    ; CHECK-NEXT:   ecagetd
+    %v8  = call i32 @llvm.mblaze.fsl.nget(i32 %port)
+    ; CHECK-NEXT:   ngetd
+    %v9  = call i32 @llvm.mblaze.fsl.naget(i32 %port)
+    ; CHECK-NEXT:   nagetd
+    %v10 = call i32 @llvm.mblaze.fsl.ncget(i32 %port)
+    ; CHECK-NEXT:   ncgetd
+    %v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 %port)
+    ; CHECK-NEXT:   ncagetd
+    %v12 = call i32 @llvm.mblaze.fsl.neget(i32 %port)
+    ; CHECK-NEXT:   negetd
+    %v13 = call i32 @llvm.mblaze.fsl.neaget(i32 %port)
+    ; CHECK-NEXT:   neagetd
+    %v14 = call i32 @llvm.mblaze.fsl.necget(i32 %port)
+    ; CHECK-NEXT:   necgetd
+    %v15 = call i32 @llvm.mblaze.fsl.necaget(i32 %port)
+    ; CHECK-NEXT:   necagetd
+    %v16 = call i32 @llvm.mblaze.fsl.tget(i32 %port)
+    ; CHECK-NEXT:   tgetd
+    %v17 = call i32 @llvm.mblaze.fsl.taget(i32 %port)
+    ; CHECK-NEXT:   tagetd
+    %v18 = call i32 @llvm.mblaze.fsl.tcget(i32 %port)
+    ; CHECK-NEXT:   tcgetd
+    %v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 %port)
+    ; CHECK-NEXT:   tcagetd
+    %v20 = call i32 @llvm.mblaze.fsl.teget(i32 %port)
+    ; CHECK-NEXT:   tegetd
+    %v21 = call i32 @llvm.mblaze.fsl.teaget(i32 %port)
+    ; CHECK-NEXT:   teagetd
+    %v22 = call i32 @llvm.mblaze.fsl.tecget(i32 %port)
+    ; CHECK-NEXT:   tecgetd
+    %v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 %port)
+    ; CHECK-NEXT:   tecagetd
+    %v24 = call i32 @llvm.mblaze.fsl.tnget(i32 %port)
+    ; CHECK-NEXT:   tngetd
+    %v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 %port)
+    ; CHECK-NEXT:   tnagetd
+    %v26 = call i32 @llvm.mblaze.fsl.tncget(i32 %port)
+    ; CHECK-NEXT:   tncgetd
+    %v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 %port)
+    ; CHECK-NEXT:   tncagetd
+    %v28 = call i32 @llvm.mblaze.fsl.tneget(i32 %port)
+    ; CHECK-NEXT:   tnegetd
+    %v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 %port)
+    ; CHECK-NEXT:   tneagetd
+    %v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 %port)
+    ; CHECK-NEXT:   tnecgetd
+    %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 %port)
+    ; CHECK-NEXT:   tnecagetd
+    ret i32 1
+    ; CHECK:        rtsd
+}
+
+define i32 @fslc_get()
+{
+    ; CHECK:        fslc_get:
+    %v0  = call i32 @llvm.mblaze.fsl.get(i32 1)
+    ; CHECK:        get
+    %v1  = call i32 @llvm.mblaze.fsl.aget(i32 1)
+    ; CHECK-NOT:    agetd
+    ; CHECK:        aget
+    %v2  = call i32 @llvm.mblaze.fsl.cget(i32 1)
+    ; CHECK-NOT:    cgetd
+    ; CHECK:        cget
+    %v3  = call i32 @llvm.mblaze.fsl.caget(i32 1)
+    ; CHECK-NOT:    cagetd
+    ; CHECK:        caget
+    %v4  = call i32 @llvm.mblaze.fsl.eget(i32 1)
+    ; CHECK-NOT:    egetd
+    ; CHECK:        eget
+    %v5  = call i32 @llvm.mblaze.fsl.eaget(i32 1)
+    ; CHECK-NOT:    eagetd
+    ; CHECK:        eaget
+    %v6  = call i32 @llvm.mblaze.fsl.ecget(i32 1)
+    ; CHECK-NOT:    ecgetd
+    ; CHECK:        ecget
+    %v7  = call i32 @llvm.mblaze.fsl.ecaget(i32 1)
+    ; CHECK-NOT:    ecagetd
+    ; CHECK:        ecaget
+    %v8  = call i32 @llvm.mblaze.fsl.nget(i32 1)
+    ; CHECK-NOT:    ngetd
+    ; CHECK:        nget
+    %v9  = call i32 @llvm.mblaze.fsl.naget(i32 1)
+    ; CHECK-NOT:    nagetd
+    ; CHECK:        naget
+    %v10 = call i32 @llvm.mblaze.fsl.ncget(i32 1)
+    ; CHECK-NOT:    ncgetd
+    ; CHECK:        ncget
+    %v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 1)
+    ; CHECK-NOT:    ncagetd
+    ; CHECK:        ncaget
+    %v12 = call i32 @llvm.mblaze.fsl.neget(i32 1)
+    ; CHECK-NOT:    negetd
+    ; CHECK:        neget
+    %v13 = call i32 @llvm.mblaze.fsl.neaget(i32 1)
+    ; CHECK-NOT:    neagetd
+    ; CHECK:        neaget
+    %v14 = call i32 @llvm.mblaze.fsl.necget(i32 1)
+    ; CHECK-NOT:    necgetd
+    ; CHECK:        necget
+    %v15 = call i32 @llvm.mblaze.fsl.necaget(i32 1)
+    ; CHECK-NOT:    necagetd
+    ; CHECK:        necaget
+    %v16 = call i32 @llvm.mblaze.fsl.tget(i32 1)
+    ; CHECK-NOT:    tgetd
+    ; CHECK:        tget
+    %v17 = call i32 @llvm.mblaze.fsl.taget(i32 1)
+    ; CHECK-NOT:    tagetd
+    ; CHECK:        taget
+    %v18 = call i32 @llvm.mblaze.fsl.tcget(i32 1)
+    ; CHECK-NOT:    tcgetd
+    ; CHECK:        tcget
+    %v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 1)
+    ; CHECK-NOT:    tcagetd
+    ; CHECK:        tcaget
+    %v20 = call i32 @llvm.mblaze.fsl.teget(i32 1)
+    ; CHECK-NOT:    tegetd
+    ; CHECK:        teget
+    %v21 = call i32 @llvm.mblaze.fsl.teaget(i32 1)
+    ; CHECK-NOT:    teagetd
+    ; CHECK:        teaget
+    %v22 = call i32 @llvm.mblaze.fsl.tecget(i32 1)
+    ; CHECK-NOT:    tecgetd
+    ; CHECK:        tecget
+    %v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 1)
+    ; CHECK-NOT:    tecagetd
+    ; CHECK:        tecaget
+    %v24 = call i32 @llvm.mblaze.fsl.tnget(i32 1)
+    ; CHECK-NOT:    tngetd
+    ; CHECK:        tnget
+    %v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 1)
+    ; CHECK-NOT:    tnagetd
+    ; CHECK:        tnaget
+    %v26 = call i32 @llvm.mblaze.fsl.tncget(i32 1)
+    ; CHECK-NOT:    tncgetd
+    ; CHECK:        tncget
+    %v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 1)
+    ; CHECK-NOT:    tncagetd
+    ; CHECK:        tncaget
+    %v28 = call i32 @llvm.mblaze.fsl.tneget(i32 1)
+    ; CHECK-NOT:    tnegetd
+    ; CHECK:        tneget
+    %v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 1)
+    ; CHECK-NOT:    tneagetd
+    ; CHECK:        tneaget
+    %v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 1)
+    ; CHECK-NOT:    tnecgetd
+    ; CHECK:        tnecget
+    %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 1)
+    ; CHECK-NOT:    tnecagetd
+    ; CHECK:        tnecaget
+    ret i32 1
+    ; CHECK:        rtsd
+}
+
+define void @putfsl(i32 %value, i32 %port)
+{
+    ; CHECK:        putfsl:
+    call void @llvm.mblaze.fsl.put(i32 %value, i32 %port)
+    ; CHECK:        putd
+    call void @llvm.mblaze.fsl.aput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   aputd
+    call void @llvm.mblaze.fsl.cput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   cputd
+    call void @llvm.mblaze.fsl.caput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   caputd
+    call void @llvm.mblaze.fsl.nput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   nputd
+    call void @llvm.mblaze.fsl.naput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   naputd
+    call void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   ncputd
+    call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port)
+    ; CHECK-NEXT:   ncaputd
+    call void @llvm.mblaze.fsl.tput(i32 %port)
+    ; CHECK-NEXT:   tputd
+    call void @llvm.mblaze.fsl.taput(i32 %port)
+    ; CHECK-NEXT:   taputd
+    call void @llvm.mblaze.fsl.tcput(i32 %port)
+    ; CHECK-NEXT:   tcputd
+    call void @llvm.mblaze.fsl.tcaput(i32 %port)
+    ; CHECK-NEXT:   tcaputd
+    call void @llvm.mblaze.fsl.tnput(i32 %port)
+    ; CHECK-NEXT:   tnputd
+    call void @llvm.mblaze.fsl.tnaput(i32 %port)
+    ; CHECK-NEXT:   tnaputd
+    call void @llvm.mblaze.fsl.tncput(i32 %port)
+    ; CHECK-NEXT:   tncputd
+    call void @llvm.mblaze.fsl.tncaput(i32 %port)
+    ; CHECK-NEXT:   tncaputd
+    ret void
+    ; CHECK:        rtsd
+}
+
+define void @putfsl_const(i32 %value)
+{
+    ; CHECK:        putfsl_const:
+    call void @llvm.mblaze.fsl.put(i32 %value, i32 1)
+    ; CHECK-NOT:    putd
+    ; CHECK:        put
+    call void @llvm.mblaze.fsl.aput(i32 %value, i32 1)
+    ; CHECK-NOT:    aputd
+    ; CHECK:        aput
+    call void @llvm.mblaze.fsl.cput(i32 %value, i32 1)
+    ; CHECK-NOT:    cputd
+    ; CHECK:        cput
+    call void @llvm.mblaze.fsl.caput(i32 %value, i32 1)
+    ; CHECK-NOT:    caputd
+    ; CHECK:        caput
+    call void @llvm.mblaze.fsl.nput(i32 %value, i32 1)
+    ; CHECK-NOT:    nputd
+    ; CHECK:        nput
+    call void @llvm.mblaze.fsl.naput(i32 %value, i32 1)
+    ; CHECK-NOT:    naputd
+    ; CHECK:        naput
+    call void @llvm.mblaze.fsl.ncput(i32 %value, i32 1)
+    ; CHECK-NOT:    ncputd
+    ; CHECK:        ncput
+    call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 1)
+    ; CHECK-NOT:    ncaputd
+    ; CHECK:        ncaput
+    call void @llvm.mblaze.fsl.tput(i32 1)
+    ; CHECK-NOT:    tputd
+    ; CHECK:        tput
+    call void @llvm.mblaze.fsl.taput(i32 1)
+    ; CHECK-NOT:    taputd
+    ; CHECK:        taput
+    call void @llvm.mblaze.fsl.tcput(i32 1)
+    ; CHECK-NOT:    tcputd
+    ; CHECK:        tcput
+    call void @llvm.mblaze.fsl.tcaput(i32 1)
+    ; CHECK-NOT:    tcaputd
+    ; CHECK:        tcaput
+    call void @llvm.mblaze.fsl.tnput(i32 1)
+    ; CHECK-NOT:    tnputd
+    ; CHECK:        tnput
+    call void @llvm.mblaze.fsl.tnaput(i32 1)
+    ; CHECK-NOT:    tnaputd
+    ; CHECK:        tnaput
+    call void @llvm.mblaze.fsl.tncput(i32 1)
+    ; CHECK-NOT:    tncputd
+    ; CHECK:        tncput
+    call void @llvm.mblaze.fsl.tncaput(i32 1)
+    ; CHECK-NOT:    tncaputd
+    ; CHECK:        tncaput
+    ret void
+    ; CHECK:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/imm.ll b/test/CodeGen/MBlaze/imm.ll
new file mode 100644
index 0000000..85fad17
--- /dev/null
+++ b/test/CodeGen/MBlaze/imm.ll
@@ -0,0 +1,70 @@
+; Ensure that all immediate values that are 32-bits or less can be loaded 
+; using a single instruction and that immediate values 64-bits or less can
+; be loaded using two instructions.
+;
+; RUN: llc < %s -march=mblaze | FileCheck %s
+; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s
+
+define i8 @retimm_i8() {
+    ; CHECK:        retimm_i8:
+    ; CHECK:        add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_i8:
+    ; FPU:          add
+    ; FPU-NEXT:     rtsd
+    ret i8 123
+}
+
+define i16 @retimm_i16() {
+    ; CHECK:        retimm_i16:
+    ; CHECK:        add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_i16:
+    ; FPU:          add
+    ; FPU-NEXT:     rtsd
+    ret i16 38212
+}
+
+define i32 @retimm_i32() {
+    ; CHECK:        retimm_i32:
+    ; CHECK:        add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_i32:
+    ; FPU:          add
+    ; FPU-NEXT:     rtsd
+    ret i32 2938128
+}
+
+define i64 @retimm_i64() {
+    ; CHECK:        retimm_i64:
+    ; CHECK:        add
+    ; CHECK-NEXT:   add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_i64:
+    ; FPU:          add
+    ; FPU-NEXT:     add
+    ; FPU-NEXT:     rtsd
+    ret i64 94581823
+}
+
+define float @retimm_float() {
+    ; CHECK:        retimm_float:
+    ; CHECK:        add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_float:
+    ; FPU:          or
+    ; FPU:          rtsd
+    ret float 12.0
+}
+
+define double @retimm_double() {
+    ; CHECK:        retimm_double:
+    ; CHECK:        add
+    ; CHECK-NEXT:   add
+    ; CHECK-NEXT:   rtsd
+    ; FPU:          retimm_double:
+    ; FPU:          add
+    ; FPU-NEXT:     add
+    ; FPU-NEXT:     rtsd
+    ret double 598382.39283873
+}
diff --git a/test/CodeGen/MBlaze/jumptable.ll b/test/CodeGen/MBlaze/jumptable.ll
new file mode 100644
index 0000000..3f27c12
--- /dev/null
+++ b/test/CodeGen/MBlaze/jumptable.ll
@@ -0,0 +1,79 @@
+; Ensure that jump tables can be handled by the mblaze backend. The
+; jump table should be lowered to a "br" instruction using one of the
+; available registers.
+;
+; RUN: llc < %s -march=mblaze | FileCheck %s
+
+define i32 @jmptable(i32 %arg)
+{
+    ; CHECK:        jmptable:
+    switch i32 %arg, label %DEFAULT [ i32 0, label %L0
+                                      i32 1, label %L1
+                                      i32 2, label %L2
+                                      i32 3, label %L3
+                                      i32 4, label %L4
+                                      i32 5, label %L5
+                                      i32 6, label %L6
+                                      i32 7, label %L7
+                                      i32 8, label %L8
+                                      i32 9, label %L9 ]
+
+    ; CHECK:        lw [[REG:r[0-9]*]]
+    ; CHECK:        br [[REG]]
+L0:
+    %var0 = add i32 %arg, 0
+    br label %DONE
+
+L1:
+    %var1 = add i32 %arg, 1
+    br label %DONE
+
+L2:
+    %var2 = add i32 %arg, 2
+    br label %DONE
+
+L3:
+    %var3 = add i32 %arg, 3
+    br label %DONE
+
+L4:
+    %var4 = add i32 %arg, 4
+    br label %DONE
+
+L5:
+    %var5 = add i32 %arg, 5
+    br label %DONE
+
+L6:
+    %var6 = add i32 %arg, 6
+    br label %DONE
+
+L7:
+    %var7 = add i32 %arg, 7
+    br label %DONE
+
+L8:
+    %var8 = add i32 %arg, 8
+    br label %DONE
+
+L9:
+    %var9 = add i32 %arg, 9
+    br label %DONE
+
+DEFAULT:
+    unreachable
+
+DONE:
+    %rval = phi i32 [ %var0, %L0 ],
+                    [ %var1, %L1 ],
+                    [ %var2, %L2 ],
+                    [ %var3, %L3 ],
+                    [ %var4, %L4 ],
+                    [ %var5, %L5 ],
+                    [ %var6, %L6 ],
+                    [ %var7, %L7 ],
+                    [ %var8, %L8 ],
+                    [ %var9, %L9 ]
+    ret i32 %rval
+    ; CHECK:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/loop.ll b/test/CodeGen/MBlaze/loop.ll
new file mode 100644
index 0000000..b473020
--- /dev/null
+++ b/test/CodeGen/MBlaze/loop.ll
@@ -0,0 +1,47 @@
+; Test some complicated looping constructs to ensure that they
+; compile successfully and that some sort of branching is used
+; in the resulting code.
+;
+; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
+
+declare i32 @printf(i8*, ...)
+@MSG = internal constant [19 x i8] c"Message: %d %d %d\0A\00"
+
+define i32 @loop(i32 %a, i32 %b)
+{
+    ; CHECK:        loop:
+entry:
+    br label %loop_outer
+
+loop_outer:
+    %outer.0 = phi i32 [ 0, %entry ], [ %outer.2, %loop_outer_finish ]
+    br label %loop_inner
+
+loop_inner:
+    %inner.0 = phi i32 [ %a, %loop_outer ], [ %inner.3, %loop_inner_finish ]
+    %inner.1 = phi i32 [ %b, %loop_outer ], [ %inner.4, %loop_inner_finish ]
+    %inner.2 = phi i32 [  0, %loop_outer ], [ %inner.5, %loop_inner_finish ]
+    %inner.3 = add i32 %inner.0, %inner.1
+    %inner.4 = mul i32 %inner.2, 11
+    br label %loop_inner_finish
+
+loop_inner_finish:
+    %inner.5 = add i32 %inner.2, 1
+    ; CHECK:        addi {{.*, 1}}
+
+    call i32 (i8*,...)* @printf( i8* getelementptr([19 x i8]* @MSG,i32 0,i32 0),
+                                 i32 %inner.0, i32 %inner.1, i32 %inner.2 )
+    ; CHECK:        brlid
+
+    %inner.6 = icmp eq i32 %inner.5, 100
+    ; CHECK:        cmp
+
+    br i1 %inner.6, label %loop_inner, label %loop_outer_finish
+    ; CHECK:        {{beq|bne}}
+
+loop_outer_finish:
+    %outer.1 = add i32 %outer.0, 1
+    %outer.2 = urem i32 %outer.1, 1500
+    br label %loop_outer
+    ; CHECK:        br
+}
diff --git a/test/CodeGen/MBlaze/mul.ll b/test/CodeGen/MBlaze/mul.ll
new file mode 100644
index 0000000..65d3e22
--- /dev/null
+++ b/test/CodeGen/MBlaze/mul.ll
@@ -0,0 +1,51 @@
+; Ensure that multiplication is lowered to function calls when the multiplier
+; unit is not available in the hardware and that function calls are not used
+; when the multiplier unit is available in the hardware.
+;
+; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
+; RUN: llc < %s -march=mblaze -mattr=+mul | FileCheck -check-prefix=MUL %s
+
+define i8 @test_i8(i8 %a, i8 %b) {
+    ; FUN:        test_i8:
+    ; MUL:        test_i8:
+
+    %tmp.1 = mul i8 %a, %b
+    ; FUN-NOT:    mul
+    ; FUN:        brlid
+    ; MUL-NOT:    brlid
+    ; MUL:        mul
+
+    ret i8 %tmp.1
+    ; FUN:        rtsd
+    ; MUL:        rtsd
+}
+
+define i16 @test_i16(i16 %a, i16 %b) {
+    ; FUN:        test_i16:
+    ; MUL:        test_i16:
+
+    %tmp.1 = mul i16 %a, %b
+    ; FUN-NOT:    mul
+    ; FUN:        brlid
+    ; MUL-NOT:    brlid
+    ; MUL:        mul
+
+    ret i16 %tmp.1
+    ; FUN:        rtsd
+    ; MUL:        rtsd
+}
+
+define i32 @test_i32(i32 %a, i32 %b) {
+    ; FUN:        test_i32:
+    ; MUL:        test_i32:
+
+    %tmp.1 = mul i32 %a, %b
+    ; FUN-NOT:    mul
+    ; FUN:        brlid
+    ; MUL-NOT:    brlid
+    ; MUL:        mul
+
+    ret i32 %tmp.1
+    ; FUN:        rtsd
+    ; MUL:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/mul64.ll b/test/CodeGen/MBlaze/mul64.ll
new file mode 100644
index 0000000..e0ef413
--- /dev/null
+++ b/test/CodeGen/MBlaze/mul64.ll
@@ -0,0 +1,23 @@
+; Ensure that multiplication is lowered to function calls when the 64-bit
+; multiplier unit is not available in the hardware and that function calls
+; are not used when the 64-bit multiplier unit is available in the hardware.
+;
+; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
+; RUN: llc < %s -march=mblaze -mattr=+mul,+mul64 | \
+; RUN:      FileCheck -check-prefix=MUL %s
+
+define i64 @test_i64(i64 %a, i64 %b) {
+    ; FUN:        test_i64:
+    ; MUL:        test_i64:
+
+    %tmp.1 = mul i64 %a, %b
+    ; FUN-NOT:    mul
+    ; FUN:        brlid
+    ; MUL-NOT:    brlid
+    ; MUL:        mulh
+    ; MUL:        mul
+
+    ret i64 %tmp.1
+    ; FUN:        rtsd
+    ; MUL:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/select.ll b/test/CodeGen/MBlaze/select.ll
new file mode 100644
index 0000000..47a88a1
--- /dev/null
+++ b/test/CodeGen/MBlaze/select.ll
@@ -0,0 +1,15 @@
+; Ensure that the select instruction is supported and is lowered to 
+; some sort of branch instruction.
+;
+; RUN: llc < %s -march=mblaze | FileCheck %s
+
+define i32 @testsel(i32 %a, i32 %b)
+{
+    ; CHECK:        testsel:
+    %tmp.1 = icmp eq i32 %a, %b
+    ; CHECK:        cmp
+    %tmp.2 = select i1 %tmp.1, i32 %a, i32 %b
+    ; CHECK:        {{bne|beq}}
+    ret i32 %tmp.2
+    ; CHECK:        rtsd
+}
diff --git a/test/CodeGen/MBlaze/shift.ll b/test/CodeGen/MBlaze/shift.ll
new file mode 100644
index 0000000..186115e
--- /dev/null
+++ b/test/CodeGen/MBlaze/shift.ll
@@ -0,0 +1,117 @@
+; Ensure that shifts are lowered to loops when the barrel shifter unit is
+; not available in the hardware and that loops are not used when the
+; barrel shifter unit is available in the hardware.
+;
+; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
+; RUN: llc < %s -march=mblaze -mattr=+barrel | FileCheck -check-prefix=SHT %s
+
+define i8 @test_i8(i8 %a, i8 %b) {
+    ; FUN:        test_i8:
+    ; SHT:        test_i8:
+
+    %tmp.1 = shl i8 %a, %b
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    bnei
+    ; SHT:        bsll
+
+    ret i8 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}
+
+define i8 @testc_i8(i8 %a, i8 %b) {
+    ; FUN:        testc_i8:
+    ; SHT:        testc_i8:
+
+    %tmp.1 = shl i8 %a, 5
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    add
+    ; SHT-NOT:    bnei
+    ; SHT:        bslli
+
+    ret i8 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}
+
+define i16 @test_i16(i16 %a, i16 %b) {
+    ; FUN:        test_i16:
+    ; SHT:        test_i16:
+
+    %tmp.1 = shl i16 %a, %b
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    bnei
+    ; SHT:        bsll
+
+    ret i16 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}
+
+define i16 @testc_i16(i16 %a, i16 %b) {
+    ; FUN:        testc_i16:
+    ; SHT:        testc_i16:
+
+    %tmp.1 = shl i16 %a, 5
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    add
+    ; SHT-NOT:    bnei
+    ; SHT:        bslli
+
+    ret i16 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}
+
+define i32 @test_i32(i32 %a, i32 %b) {
+    ; FUN:        test_i32:
+    ; SHT:        test_i32:
+
+    %tmp.1 = shl i32 %a, %b
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    bnei
+    ; SHT:        bsll
+
+    ret i32 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}
+
+define i32 @testc_i32(i32 %a, i32 %b) {
+    ; FUN:        testc_i32:
+    ; SHT:        testc_i32:
+
+    %tmp.1 = shl i32 %a, 5
+    ; FUN-NOT:    bsll
+    ; FUN:        andi
+    ; FUN:        add
+    ; FUN:        bnei
+    ; SHT-NOT:    andi
+    ; SHT-NOT:    add
+    ; SHT-NOT:    bnei
+    ; SHT:        bslli
+
+    ret i32 %tmp.1
+    ; FUN:        rtsd
+    ; SHT:        rtsd
+}