Fix spelling and grammar in a comment.
[oota-llvm.git] / lib / Target / PowerPC / PPCInstrInfo.td
index 1591148b880c9a5da86e960de90b6fd6e1141a4a..04968edf34de9d226de885ef7f8f23f138c81332 100644 (file)
@@ -2,8 +2,8 @@
 // 
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 // 
 //===----------------------------------------------------------------------===//
 //
@@ -20,11 +20,9 @@ include "PPCInstrFormats.td"
 def SDT_PPCstfiwx : SDTypeProfile<0, 2, [ // stfiwx
   SDTCisVT<0, f64>, SDTCisPtrTy<1>
 ]>;
-def SDT_PPCShiftOp : SDTypeProfile<1, 2, [   // PPCshl, PPCsra, PPCsrl
-  SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>
-]>;
-def SDT_PPCCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
-
+def SDT_PPCCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
+def SDT_PPCCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>,
+                                         SDTCisVT<1, i32> ]>;
 def SDT_PPCvperm   : SDTypeProfile<1, 3, [
   SDTCisVT<3, v16i8>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>
 ]>;
@@ -44,6 +42,21 @@ def SDT_PPCstbrx : SDTypeProfile<0, 4, [
   SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
 ]>;
 
+
+def SDT_PPClarx : SDTypeProfile<1, 2, [
+  SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
+]>;
+def SDT_PPCstcx : SDTypeProfile<0, 3, [
+  SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
+]>;
+def SDT_PPCcmp_unres : SDTypeProfile<0, 3, [
+  SDTCisSameAs<0, 1>, SDTCisInt<1>, SDTCisVT<2, i32>
+]>;
+
+def SDT_PPCTC_ret : SDTypeProfile<0, 2, [
+  SDTCisPtrTy<0>, SDTCisVT<1, i32>
+]>;
+
 //===----------------------------------------------------------------------===//
 // PowerPC specific DAG Nodes.
 //
@@ -51,7 +64,23 @@ def SDT_PPCstbrx : SDTypeProfile<0, 4, [
 def PPCfcfid  : SDNode<"PPCISD::FCFID" , SDTFPUnaryOp, []>;
 def PPCfctidz : SDNode<"PPCISD::FCTIDZ", SDTFPUnaryOp, []>;
 def PPCfctiwz : SDNode<"PPCISD::FCTIWZ", SDTFPUnaryOp, []>;
-def PPCstfiwx : SDNode<"PPCISD::STFIWX", SDT_PPCstfiwx, [SDNPHasChain]>;
+def PPCstfiwx : SDNode<"PPCISD::STFIWX", SDT_PPCstfiwx,
+                       [SDNPHasChain, SDNPMayStore]>;
+
+// This sequence is used for long double->int conversions.  It changes the
+// bits in the FPSCR which is not modelled.  
+def PPCmffs   : SDNode<"PPCISD::MFFS", SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>,
+                        [SDNPOutFlag]>;
+def PPCmtfsb0 : SDNode<"PPCISD::MTFSB0", SDTypeProfile<0, 1, [SDTCisInt<0>]>,
+                       [SDNPInFlag, SDNPOutFlag]>;
+def PPCmtfsb1 : SDNode<"PPCISD::MTFSB1", SDTypeProfile<0, 1, [SDTCisInt<0>]>,
+                       [SDNPInFlag, SDNPOutFlag]>;
+def PPCfaddrtz: SDNode<"PPCISD::FADDRTZ", SDTFPBinOp,
+                       [SDNPInFlag, SDNPOutFlag]>;
+def PPCmtfsf  : SDNode<"PPCISD::MTFSF", SDTypeProfile<1, 3, 
+                       [SDTCisVT<0, f64>, SDTCisInt<1>, SDTCisVT<2, f64>,
+                        SDTCisVT<3, f64>]>,
+                       [SDNPInFlag]>;
 
 def PPCfsel   : SDNode<"PPCISD::FSEL",  
    // Type constraint for fsel.
@@ -67,18 +96,19 @@ def PPCvperm    : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>;
 
 // These nodes represent the 32-bit PPC shifts that operate on 6-bit shift
 // amounts.  These nodes are generated by the multi-precision shift code.
-def PPCsrl        : SDNode<"PPCISD::SRL"       , SDT_PPCShiftOp>;
-def PPCsra        : SDNode<"PPCISD::SRA"       , SDT_PPCShiftOp>;
-def PPCshl        : SDNode<"PPCISD::SHL"       , SDT_PPCShiftOp>;
+def PPCsrl        : SDNode<"PPCISD::SRL"       , SDTIntShiftOp>;
+def PPCsra        : SDNode<"PPCISD::SRA"       , SDTIntShiftOp>;
+def PPCshl        : SDNode<"PPCISD::SHL"       , SDTIntShiftOp>;
 
 def PPCextsw_32   : SDNode<"PPCISD::EXTSW_32"  , SDTIntUnaryOp>;
-def PPCstd_32     : SDNode<"PPCISD::STD_32"    , SDTStore, [SDNPHasChain]>;
+def PPCstd_32     : SDNode<"PPCISD::STD_32"    , SDTStore,
+                           [SDNPHasChain, SDNPMayStore]>;
 
 // These are target-independent nodes, but have target-specific formats.
-def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,
-                           [SDNPHasChain, SDNPOutFlag]>;
-def callseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_PPCCallSeq,
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeqStart,
                            [SDNPHasChain, SDNPOutFlag]>;
+def callseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_PPCCallSeqEnd,
+                           [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
 
 def SDT_PPCCall   : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
 def PPCcall_Macho : SDNode<"PPCISD::CALL_Macho", SDT_PPCCall,
@@ -87,14 +117,20 @@ def PPCcall_ELF   : SDNode<"PPCISD::CALL_ELF", SDT_PPCCall,
                            [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
 def PPCmtctr      : SDNode<"PPCISD::MTCTR", SDT_PPCCall,
                            [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
-def PPCbctrl_Macho  : SDNode<"PPCISD::BCTRL_Macho", SDTRet,
-                          [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+def PPCbctrl_Macho  : SDNode<"PPCISD::BCTRL_Macho", SDTNone,
+                           [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
 
-def PPCbctrl_ELF  : SDNode<"PPCISD::BCTRL_ELF", SDTRet,
-                          [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+def PPCbctrl_ELF  : SDNode<"PPCISD::BCTRL_ELF", SDTNone,
+                           [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
 
-def retflag       : SDNode<"PPCISD::RET_FLAG", SDTRet,
-                          [SDNPHasChain, SDNPOptInFlag]>;
+def retflag       : SDNode<"PPCISD::RET_FLAG", SDTNone,
+                           [SDNPHasChain, SDNPOptInFlag]>;
+
+def PPCtc_return : SDNode<"PPCISD::TC_RETURN", SDT_PPCTC_ret,
+                        [SDNPHasChain,  SDNPOptInFlag]>;
+
+def PPCtailcall : SDNode<"PPCISD::TAILCALL",     SDT_PPCCall,
+                        [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
 
 def PPCvcmp       : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>;
 def PPCvcmp_o     : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>;
@@ -102,8 +138,17 @@ def PPCvcmp_o     : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>;
 def PPCcondbranch : SDNode<"PPCISD::COND_BRANCH", SDT_PPCcondbr,
                            [SDNPHasChain, SDNPOptInFlag]>;
 
-def PPClbrx       : SDNode<"PPCISD::LBRX", SDT_PPClbrx, [SDNPHasChain]>;
-def PPCstbrx      : SDNode<"PPCISD::STBRX", SDT_PPCstbrx, [SDNPHasChain]>;
+def PPClbrx       : SDNode<"PPCISD::LBRX", SDT_PPClbrx,
+                           [SDNPHasChain, SDNPMayLoad]>;
+def PPCstbrx      : SDNode<"PPCISD::STBRX", SDT_PPCstbrx,
+                           [SDNPHasChain, SDNPMayStore]>;
+
+def PPClarx      : SDNode<"PPCISD::LARX", SDT_PPClarx,
+                          [SDNPHasChain, SDNPMayLoad]>;
+def PPCstcx      : SDNode<"PPCISD::STCX", SDT_PPCstcx,
+                          [SDNPHasChain, SDNPMayStore]>;
+def PPCcmp_unres  : SDNode<"PPCISD::CMP_UNRESERVE", SDT_PPCcmp_unres,
+                           [SDNPHasChain]>;
 
 // Instructions to support dynamic alloca.
 def SDTDynOp  : SDTypeProfile<1, 2, []>;
@@ -273,7 +318,7 @@ def memrix : Operand<iPTR> {   // memri where the imm is shifted 2 bits.
 // PowerPC Predicate operand.  20 = (0<<5)|20 = always, CR0 is a dummy reg
 // that doesn't matter.
 def pred : PredicateOperand<OtherVT, (ops imm, CRRC),
-                                     (ops (i32 20), CR0)> {
+                                     (ops (i32 20), (i32 zero_reg))> {
   let PrintMethod = "printPredicateOperand";
 }
 
@@ -289,6 +334,8 @@ def iaddroff : ComplexPattern<iPTR, 1, "SelectAddrImmOffs", [], []>;
 //===----------------------------------------------------------------------===//
 // PowerPC Instruction Predicate Definitions.
 def FPContractions : Predicate<"!NoExcessFPPrecision">;
+def In32BitMode  : Predicate<"!PPCSubTarget.isPPC64()">;
+def In64BitMode  : Predicate<"PPCSubTarget.isPPC64()">;
 
 
 //===----------------------------------------------------------------------===//
@@ -301,9 +348,9 @@ let Defs = [R1], Uses = [R1] in {
 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins u16imm:$amt),
                               "${:comment} ADJCALLSTACKDOWN",
                               [(callseq_start imm:$amt)]>;
-def ADJCALLSTACKUP   : Pseudo<(outs), (ins u16imm:$amt),
+def ADJCALLSTACKUP   : Pseudo<(outs), (ins u16imm:$amt1, u16imm:$amt2),
                               "${:comment} ADJCALLSTACKUP",
-                              [(callseq_end imm:$amt)]>;
+                              [(callseq_end imm:$amt1, imm:$amt2)]>;
 }
 
 def UPDATE_VRSAVE    : Pseudo<(outs GPRC:$rD), (ins GPRC:$rS),
@@ -316,16 +363,6 @@ def DYNALLOC : Pseudo<(outs GPRC:$result), (ins GPRC:$negsize, memri:$fpsi),
                        [(set GPRC:$result,
                              (PPCdynalloc GPRC:$negsize, iaddr:$fpsi))]>;
                          
-def IMPLICIT_DEF_GPRC: Pseudo<(outs GPRC:$rD), (ins),
-                              "${:comment}IMPLICIT_DEF_GPRC $rD",
-                              [(set GPRC:$rD, (undef))]>;
-def IMPLICIT_DEF_F8  : Pseudo<(outs F8RC:$rD), (ins),
-                              "${:comment} IMPLICIT_DEF_F8 $rD",
-                              [(set F8RC:$rD, (undef))]>;
-def IMPLICIT_DEF_F4  : Pseudo<(outs F4RC:$rD), (ins),
-                              "${:comment} IMPLICIT_DEF_F4 $rD",
-                              [(set F4RC:$rD, (undef))]>;
-
 // SELECT_CC_* - Used to implement the SELECT_CC DAG operation.  Expanded by the
 // scheduler into a branch sequence.
 let usesCustomDAGSchedInserter = 1,    // Expanded by the scheduler.
@@ -347,16 +384,20 @@ let usesCustomDAGSchedInserter = 1,    // Expanded by the scheduler.
                               []>;
 }
 
+// SPILL_CR - Indicate that we're dumping the CR register, so we'll need to
+// scavenge a register for it.
+def SPILL_CR : Pseudo<(outs), (ins GPRC:$cond, memri:$F),
+                     "${:comment} SPILL_CR $cond $F", []>;
+
 let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7 in {
   let isReturn = 1 in
     def BLR : XLForm_2_br<19, 16, 0, (outs), (ins pred:$p),
                           "b${p:cc}lr ${p:reg}", BrB, 
                           [(retflag)]>;
-  def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>;
+  let isBranch = 1, isIndirectBranch = 1 in
+    def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>;
 }
 
-
-
 let Defs = [LR] in
   def MovePCtoLR : Pseudo<(outs), (ins piclabel:$label), "bl $label", []>,
                    PPC970_Unit_BRU;
@@ -383,7 +424,9 @@ let isCall = 1, PPC970_Unit = 7,
           F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,
           V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,
           LR,CTR,
-          CR0,CR1,CR5,CR6,CR7] in {
+          CR0,CR1,CR5,CR6,CR7,
+          CR0LT,CR0GT,CR0EQ,CR0UN,CR1LT,CR1GT,CR1EQ,CR1UN,CR5LT,CR5GT,CR5EQ,
+          CR5UN,CR6LT,CR6GT,CR6EQ,CR6UN,CR7LT,CR7GT,CR7EQ,CR7UN] in {
   // Convenient aliases for call instructions
   def BL_Macho  : IForm<18, 0, 1,
                         (outs), (ins calltarget:$func, variable_ops), 
@@ -394,7 +437,7 @@ let isCall = 1, PPC970_Unit = 7,
   def BCTRL_Macho : XLForm_2_ext<19, 528, 20, 0, 1, 
                                  (outs), (ins variable_ops),
                                  "bctrl", BrB,
-                                 [(PPCbctrl_Macho)]>;
+                                 [(PPCbctrl_Macho)]>, Requires<[In32BitMode]>;
 }
 
 // ELF ABI Calls.
@@ -404,7 +447,9 @@ let isCall = 1, PPC970_Unit = 7,
           F0,F1,F2,F3,F4,F5,F6,F7,F8,
           V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,
           LR,CTR,
-          CR0,CR1,CR5,CR6,CR7] in {
+          CR0,CR1,CR5,CR6,CR7,
+          CR0LT,CR0GT,CR0EQ,CR0UN,CR1LT,CR1GT,CR1EQ,CR1UN,CR5LT,CR5GT,CR5EQ,
+          CR5UN,CR6LT,CR6GT,CR6EQ,CR6UN,CR7LT,CR7GT,CR7EQ,CR7UN] in {
   // Convenient aliases for call instructions
   def BL_ELF  : IForm<18, 0, 1,
                       (outs), (ins calltarget:$func, variable_ops), 
@@ -416,9 +461,49 @@ let isCall = 1, PPC970_Unit = 7,
   def BCTRL_ELF : XLForm_2_ext<19, 528, 20, 0, 1,
                                (outs), (ins variable_ops),
                                "bctrl", BrB,
-                               [(PPCbctrl_ELF)]>;
+                               [(PPCbctrl_ELF)]>, Requires<[In32BitMode]>;
 }
 
+
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
+def TCRETURNdi :Pseudo< (outs),
+                        (ins calltarget:$dst, i32imm:$offset, variable_ops),
+                 "#TC_RETURNd $dst $offset",
+                 []>;
+
+
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
+def TCRETURNai :Pseudo<(outs), (ins aaddr:$func, i32imm:$offset, variable_ops),
+                 "#TC_RETURNa $func $offset",
+                 [(PPCtc_return (i32 imm:$func), imm:$offset)]>;
+
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
+def TCRETURNri : Pseudo<(outs), (ins CTRRC:$dst, i32imm:$offset, variable_ops),
+                 "#TC_RETURNr $dst $offset",
+                 []>;
+
+
+let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7, isBranch = 1,
+    isIndirectBranch = 1, isCall = 1, isReturn = 1  in
+def TAILBCTR : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>,
+     Requires<[In32BitMode]>;
+
+
+
+let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7,
+    isBarrier = 1, isCall = 1, isReturn = 1 in
+def TAILB   : IForm<18, 0, 0, (outs), (ins calltarget:$dst),
+                  "b $dst", BrB,
+                  []>;
+
+
+let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7,
+    isBarrier = 1, isCall = 1, isReturn = 1 in
+def TAILBA   : IForm<18, 0, 0, (outs), (ins aaddr:$dst),
+                  "ba $dst", BrB,
+                  []>;
+
+
 // DCB* instructions.
 def DCBA   : DCB_Form<758, 0, (outs), (ins memrr:$dst),
                       "dcba $dst", LdStDCBF, [(int_ppc_dcba xoaddr:$dst)]>,
@@ -445,12 +530,30 @@ def DCBZL  : DCB_Form<1014, 1, (outs), (ins memrr:$dst),
                       "dcbzl $dst", LdStDCBF, [(int_ppc_dcbzl xoaddr:$dst)]>,
                       PPC970_DGroup_Single;
 
+// Atomic operations.
+def LWARX : Pseudo<(outs GPRC:$rD), (ins memrr:$ptr, i32imm:$label),
+                   "\nLa${label}_entry:\n\tlwarx $rD, $ptr",
+                   [(set GPRC:$rD, (PPClarx xoaddr:$ptr, imm:$label))]>;
+
+let Defs = [CR0] in {
+def STWCX : Pseudo<(outs), (ins GPRC:$rS, memrr:$dst, i32imm:$label),
+                  "stwcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
+                   [(PPCstcx GPRC:$rS, xoaddr:$dst, imm:$label)]>;
+
+def CMP_UNRESw : Pseudo<(outs), (ins GPRC:$rA, GPRC:$rB, i32imm:$label),
+                         "cmpw $rA, $rB\n\tbne- La${label}_exit",
+                         [(PPCcmp_unres GPRC:$rA, GPRC:$rB, imm:$label)]>;
+def CMP_UNRESwi : Pseudo<(outs), (ins GPRC:$rA, s16imm:$imm, i32imm:$label),
+                         "cmpwi $rA, $imm\n\tbne- La${label}_exit",
+                         [(PPCcmp_unres GPRC:$rA, immSExt16:$imm, imm:$label)]>;
+}
+
 //===----------------------------------------------------------------------===//
 // PPC32 Load Instructions.
 //
 
 // Unindexed (r+i) Loads. 
-let isLoad = 1, PPC970_Unit = 2 in {
+let isSimpleLoad = 1, PPC970_Unit = 2 in {
 def LBZ : DForm_1<34, (outs GPRC:$rD), (ins memri:$src),
                   "lbz $rD, $src", LdStGeneral,
                   [(set GPRC:$rD, (zextloadi8 iaddr:$src))]>;
@@ -507,7 +610,7 @@ def LFDU : DForm_1<51, (outs F8RC:$rD, ptr_rc:$ea_result), (ins memri:$addr),
 
 // Indexed (r+r) Loads.
 //
-let isLoad = 1, PPC970_Unit = 2 in {
+let isSimpleLoad = 1, PPC970_Unit = 2 in {
 def LBZX : XForm_1<31,  87, (outs GPRC:$rD), (ins memrr:$src),
                    "lbzx $rD, $src", LdStGeneral,
                    [(set GPRC:$rD, (zextloadi8 xaddr:$src))]>;
@@ -543,7 +646,7 @@ def LFDX   : XForm_25<31, 599, (outs F8RC:$frD), (ins memrr:$src),
 //
 
 // Unindexed (r+i) Stores.
-let isStore = 1, PPC970_Unit = 2 in {
+let PPC970_Unit = 2 in {
 def STB  : DForm_1<38, (outs), (ins GPRC:$rS, memri:$src),
                    "stb $rS, $src", LdStGeneral,
                    [(truncstorei8 GPRC:$rS, iaddr:$src)]>;
@@ -562,7 +665,7 @@ def STFD : DForm_1<54, (outs), (ins F8RC:$rS, memri:$dst),
 }
 
 // Unindexed (r+i) Stores with Update (preinc).
-let isStore = 1, PPC970_Unit = 2 in {
+let PPC970_Unit = 2 in {
 def STBU  : DForm_1<39, (outs ptr_rc:$ea_res), (ins GPRC:$rS,
                              symbolLo:$ptroff, ptr_rc:$ptrreg),
                     "stbu $rS, $ptroff($ptrreg)", LdStGeneral,
@@ -600,7 +703,7 @@ def STFDU : DForm_1<37, (outs ptr_rc:$ea_res), (ins F8RC:$rS,
 
 // Indexed (r+r) Stores.
 //
-let isStore = 1, PPC970_Unit = 2 in {
+let PPC970_Unit = 2 in {
 def STBX  : XForm_8<31, 215, (outs), (ins GPRC:$rS, memrr:$dst),
                    "stbx $rS, $dst", LdStGeneral,
                    [(truncstorei8 GPRC:$rS, xaddr:$dst)]>, 
@@ -613,9 +716,12 @@ def STWX  : XForm_8<31, 151, (outs), (ins GPRC:$rS, memrr:$dst),
                    "stwx $rS, $dst", LdStGeneral,
                    [(store GPRC:$rS, xaddr:$dst)]>,
                    PPC970_DGroup_Cracked;
+                   
+let mayStore = 1 in {
 def STWUX : XForm_8<31, 183, (outs), (ins GPRC:$rS, GPRC:$rA, GPRC:$rB),
                    "stwux $rS, $rA, $rB", LdStGeneral,
                    []>;
+}
 def STHBRX: XForm_8<31, 918, (outs), (ins GPRC:$rS, memrr:$dst),
                    "sthbrx $rS, $dst", LdStGeneral,
                    [(PPCstbrx GPRC:$rS, xoaddr:$dst, srcvalue:$dummy, i16)]>, 
@@ -628,6 +734,7 @@ def STWBRX: XForm_8<31, 662, (outs), (ins GPRC:$rS, memrr:$dst),
 def STFIWX: XForm_28<31, 983, (outs), (ins F8RC:$frS, memrr:$dst),
                      "stfiwx $frS, $dst", LdStUX,
                      [(PPCstfiwx F8RC:$frS, xoaddr:$dst)]>;
+                     
 def STFSX : XForm_28<31, 663, (outs), (ins F4RC:$frS, memrr:$dst),
                      "stfsx $frS, $dst", LdStUX,
                      [(store F4RC:$frS, xaddr:$dst)]>;
@@ -665,12 +772,15 @@ def MULLI  : DForm_2< 7, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm),
 def SUBFIC : DForm_2< 8, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm),
                      "subfic $rD, $rA, $imm", IntGeneral,
                      [(set GPRC:$rD, (subc immSExt16:$imm, GPRC:$rA))]>;
-def LI  : DForm_2_r0<14, (outs GPRC:$rD), (ins symbolLo:$imm),
-                     "li $rD, $imm", IntGeneral,
-                     [(set GPRC:$rD, immSExt16:$imm)]>;
-def LIS : DForm_2_r0<15, (outs GPRC:$rD), (ins symbolHi:$imm),
-                     "lis $rD, $imm", IntGeneral,
-                     [(set GPRC:$rD, imm16ShiftedSExt:$imm)]>;
+
+let isReMaterializable = 1 in {
+  def LI  : DForm_2_r0<14, (outs GPRC:$rD), (ins symbolLo:$imm),
+                       "li $rD, $imm", IntGeneral,
+                       [(set GPRC:$rD, immSExt16:$imm)]>;
+  def LIS : DForm_2_r0<15, (outs GPRC:$rD), (ins symbolHi:$imm),
+                       "lis $rD, $imm", IntGeneral,
+                       [(set GPRC:$rD, imm16ShiftedSExt:$imm)]>;
+}
 }
 
 let PPC970_Unit = 1 in {  // FXU Operations.
@@ -828,11 +938,17 @@ def MCRF   : XLForm_3<19, 0, (outs CRRC:$BF), (ins CRRC:$BFA),
                       "mcrf $BF, $BFA", BrMCR>,
              PPC970_DGroup_First, PPC970_Unit_CRU;
 
-def CREQV  : XLForm_1<19, 289, (outs CRRC:$CRD), (ins CRRC:$CRA, CRRC:$CRB),
+def CREQV  : XLForm_1<19, 289, (outs CRBITRC:$CRD),
+                               (ins CRBITRC:$CRA, CRBITRC:$CRB),
                       "creqv $CRD, $CRA, $CRB", BrCR,
                       []>;
 
-def SETCR  : XLForm_1_ext<19, 289, (outs CRRC:$dst), (ins),
+def CROR  : XLForm_1<19, 449, (outs CRBITRC:$CRD),
+                               (ins CRBITRC:$CRA, CRBITRC:$CRB),
+                      "cror $CRD, $CRA, $CRB", BrCR,
+                      []>;
+
+def CRSET  : XLForm_1_ext<19, 289, (outs CRBITRC:$dst), (ins),
               "creqv $dst, $dst, $dst", BrCR,
               []>;
 
@@ -873,6 +989,37 @@ def MFOCRF: XFXForm_5a<31, 19, (outs GPRC:$rT), (ins crbitm:$FXM),
                        "mfcr $rT, $FXM", SprMFCR>,
             PPC970_DGroup_First, PPC970_Unit_CRU;
 
+// Instructions to manipulate FPSCR.  Only long double handling uses these.
+// FPSCR is not modelled; we use the SDNode Flag to keep things in order.
+
+def MFFS   : XForm_42<63, 583, (outs F8RC:$rT), (ins), 
+                       "mffs $rT", IntMFFS,
+                       [(set F8RC:$rT, (PPCmffs))]>,
+             PPC970_DGroup_Single, PPC970_Unit_FPU;
+def MTFSB0 : XForm_43<63, 70, (outs), (ins u5imm:$FM),
+                       "mtfsb0 $FM", IntMTFSB0,
+                      [(PPCmtfsb0 (i32 imm:$FM))]>,
+             PPC970_DGroup_Single, PPC970_Unit_FPU;
+def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM),
+                       "mtfsb1 $FM", IntMTFSB0,
+                      [(PPCmtfsb1 (i32 imm:$FM))]>,
+             PPC970_DGroup_Single, PPC970_Unit_FPU;
+def FADDrtz: AForm_2<63, 21,
+                    (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB),
+                    "fadd $FRT, $FRA, $FRB", FPGeneral,
+                    [(set F8RC:$FRT, (PPCfaddrtz F8RC:$FRA, F8RC:$FRB))]>,
+             PPC970_DGroup_Single, PPC970_Unit_FPU;
+// MTFSF does not actually produce an FP result.  We pretend it copies
+// input reg B to the output.  If we didn't do this it would look like the
+// instruction had no outputs (because we aren't modelling the FPSCR) and
+// it would be deleted.
+def MTFSF  : XFLForm<63, 711, (outs F8RC:$FRA),
+                              (ins i32imm:$FM, F8RC:$rT, F8RC:$FRB),
+                       "mtfsf $FM, $rT", "$FRB = $FRA", IntMTFSB0,
+                       [(set F8RC:$FRA, (PPCmtfsf (i32 imm:$FM), 
+                                                   F8RC:$rT, F8RC:$FRB))]>,
+             PPC970_DGroup_Single, PPC970_Unit_FPU;
+
 let PPC970_Unit = 1 in {  // FXU Operations.
 
 // XO-Form instructions.  Arithmetic instructions that can set overflow bit
@@ -1115,6 +1262,18 @@ def : Pat<(PPCcall_ELF (i32 tglobaladdr:$dst)),
 def : Pat<(PPCcall_ELF (i32 texternalsym:$dst)),
           (BL_ELF texternalsym:$dst)>;
 
+
+def : Pat<(PPCtc_return (i32 tglobaladdr:$dst),  imm:$imm),
+          (TCRETURNdi tglobaladdr:$dst, imm:$imm)>;
+
+def : Pat<(PPCtc_return (i32 texternalsym:$dst), imm:$imm),
+          (TCRETURNdi texternalsym:$dst, imm:$imm)>;
+
+def : Pat<(PPCtc_return CTRRC:$dst, imm:$imm),
+          (TCRETURNri CTRRC:$dst, imm:$imm)>;
+
+
+
 // Hi and Lo for Darwin Global Addresses.
 def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
 def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
@@ -1168,5 +1327,9 @@ def : Pat<(extloadf32 iaddr:$src),
 def : Pat<(extloadf32 xaddr:$src),
           (FMRSD (LFSX xaddr:$src))>;
 
+// Atomic operations
+def : Pat<(PPCcmp_unres immSExt16:$imm, GPRC:$rA, imm:$label),
+          (CMP_UNRESwi GPRC:$rA, immSExt16:$imm, imm:$label)>;
+
 include "PPCInstrAltivec.td"
 include "PPCInstr64Bit.td"