Index: lib/Target/Mips/Mips.td =================================================================== --- lib/Target/Mips/Mips.td +++ lib/Target/Mips/Mips.td @@ -61,6 +61,8 @@ "General Purpose Registers are 64-bit wide.">; def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", "Support 64-bit FP registers.">; +def FeatureFPXX : SubtargetFeature<"fpxx", "IsFPXX", "true", + "Support for FPXX.">; def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true", "IEEE 754-2008 NaN encoding.">; def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", Index: lib/Target/Mips/MipsCallingConv.td =================================================================== --- lib/Target/Mips/MipsCallingConv.td +++ lib/Target/Mips/MipsCallingConv.td @@ -239,6 +239,12 @@ def CSR_SingleFloatOnly : CalleeSavedRegs<(add (sequence "F%u", 31, 20), RA, FP, (sequence "S%u", 7, 0))>; +def CSR_O32_FPXX : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, + (sequence "S%u", 7, 0))>; + +def CSR_O32_FPXX_NoOdd : CalleeSavedRegs<(add F20, F22, F24, F26, F28, F30, + RA, FP, (sequence "S%u", 7, 0))>; + def CSR_O32 : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, (sequence "S%u", 7, 0))>; Index: lib/Target/Mips/MipsRegisterInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterInfo.cpp +++ lib/Target/Mips/MipsRegisterInfo.cpp @@ -93,6 +93,9 @@ if (Subtarget.isFP64bit()) return CSR_O32_FP64_SaveList; + if (Subtarget.isFPXX()) + return CSR_O32_FPXX_SaveList; + return CSR_O32_SaveList; } @@ -110,6 +113,9 @@ if (Subtarget.isFP64bit()) return CSR_O32_FP64_RegMask; + if (Subtarget.isFPXX()) + return CSR_O32_FPXX_NoOdd_RegMask; + return CSR_O32_RegMask; } Index: lib/Target/Mips/MipsSubtarget.h =================================================================== --- lib/Target/Mips/MipsSubtarget.h +++ lib/Target/Mips/MipsSubtarget.h @@ -59,6 +59,9 @@ // IsFP64bit - The target processor has 64-bit floating point registers. bool IsFP64bit; + // IsFPXX - MIPS O32 modeless ABI. + bool IsFPXX; + // IsNan2008 - IEEE 754-2008 NaN encoding. bool IsNaN2008bit; @@ -170,6 +173,7 @@ bool hasCnMips() const { return HasCnMips; } bool isLittle() const { return IsLittle; } + bool isFPXX() const { return IsFPXX; } bool isFP64bit() const { return IsFP64bit; } bool isNaN2008() const { return IsNaN2008bit; } bool isNotFP64bit() const { return !IsFP64bit; } Index: lib/Target/Mips/MipsSubtarget.cpp =================================================================== --- lib/Target/Mips/MipsSubtarget.cpp +++ lib/Target/Mips/MipsSubtarget.cpp @@ -86,6 +86,7 @@ InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false), RM(_RM), OverrideMode(NoOverride), TM(_TM), TargetTriple(TT) { + IsFPXX = false; std::string CPUName = CPU; CPUName = selectMipsCPU(TT, CPUName); Index: test/CodeGen/Mips/cconv/callee-saved-fpxx.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/cconv/callee-saved-fpxx.ll @@ -0,0 +1,62 @@ +; RUN: llc -march=mips -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX %s +; RUN: llc -march=mipsel -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX %s +; RUN: llc -march=mips -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX-INV %s +; RUN: llc -march=mipsel -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX-INV %s + +; RUN-TODO: llc -march=mips64 -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX %s +; RUN-TODO: llc -march=mips64el -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX %s +; RUN-TODO: llc -march=mips64 -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX-INV --check-prefix=O32-FPXX-INV %s +; RUN-TODO: llc -march=mips64el -mattr=+fpxx < %s | FileCheck --check-prefix=ALL --check-prefix=O32-FPXX-INV --check-prefix=O32-FPXX-INV %s + +define void @fpu_clobber() nounwind { +entry: + call void asm "# Clobber", "~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f12},~{$f13},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"() + ret void +} + +; O32-FPXX-LABEL: fpu_clobber: +; O32-FPXX-INV-NOT: sdc1 $f0, +; O32-FPXX-INV-NOT: sdc1 $f1, +; O32-FPXX-INV-NOT: sdc1 $f2, +; O32-FPXX-INV-NOT: sdc1 $f3, +; O32-FPXX-INV-NOT: sdc1 $f4, +; O32-FPXX-INV-NOT: sdc1 $f5, +; O32-FPXX-INV-NOT: sdc1 $f6, +; O32-FPXX-INV-NOT: sdc1 $f7, +; O32-FPXX-INV-NOT: sdc1 $f8, +; O32-FPXX-INV-NOT: sdc1 $f9, +; O32-FPXX-INV-NOT: sdc1 $f10, +; O32-FPXX-INV-NOT: sdc1 $f11, +; O32-FPXX-INV-NOT: sdc1 $f12, +; O32-FPXX-INV-NOT: sdc1 $f13, +; O32-FPXX-INV-NOT: sdc1 $f14, +; O32-FPXX-INV-NOT: sdc1 $f15, +; O32-FPXX-INV-NOT: sdc1 $f16, +; O32-FPXX-INV-NOT: sdc1 $f17, +; O32-FPXX-INV-NOT: sdc1 $f18, +; O32-FPXX-INV-NOT: sdc1 $f19, +; O32-FPXX-INV-NOT: sdc1 $f21, +; O32-FPXX-INV-NOT: sdc1 $f23, +; O32-FPXX-INV-NOT: sdc1 $f25, +; O32-FPXX-INV-NOT: sdc1 $f27, +; O32-FPXX-INV-NOT: sdc1 $f29, +; O32-FPXX-INV-NOT: sdc1 $f31, + +; O32-FPXX: addiu $sp, $sp, -48 +; O32-FPXX-DAG: sdc1 [[F20:\$f20]], [[OFF20:[0-9]+]]($sp) +; O32-FPXX-DAG: sdc1 [[F22:\$f22]], [[OFF22:[0-9]+]]($sp) +; O32-FPXX-DAG: sdc1 [[F24:\$f24]], [[OFF24:[0-9]+]]($sp) +; O32-FPXX-DAG: sdc1 [[F26:\$f26]], [[OFF26:[0-9]+]]($sp) +; O32-FPXX-DAG: sdc1 [[F28:\$f28]], [[OFF28:[0-9]+]]($sp) +; O32-FPXX-DAG: sdc1 [[F30:\$f30]], [[OFF30:[0-9]+]]($sp) +; O32-FPXX-DAG: ldc1 [[F20]], [[OFF20]]($sp) +; O32-FPXX-DAG: ldc1 [[F22]], [[OFF22]]($sp) +; O32-FPXX-DAG: ldc1 [[F24]], [[OFF24]]($sp) +; O32-FPXX-INV-NOT: sdc1 $f25, +; O32-FPXX-DAG: ldc1 [[F26]], [[OFF26]]($sp) +; O32-FPXX-INV-NOT: sdc1 $f27, +; O32-FPXX-DAG: ldc1 [[F28]], [[OFF28]]($sp) +; O32-FPXX-INV-NOT: sdc1 $f29, +; O32-FPXX-DAG: ldc1 [[F30]], [[OFF30]]($sp) +; O32-FPXX-INV-NOT: sdc1 $f31, +; O32-FPXX: addiu $sp, $sp, 48