1; Test that the FP64A ABI performs double precision moves via a spill/reload. 2; The requirement is really that odd-numbered double precision registers do not 3; use mfc1/mtc1 to move the bottom 32-bits (because the hardware will redirect 4; this to the top 32-bits of the even register) but we have to make the decision 5; before register allocation so we do this for all double-precision values. 6 7; We don't test MIPS32r1 since support for 64-bit coprocessors (such as a 64-bit 8; FPU) on a 32-bit architecture was added in MIPS32r2. 9 10; RUN: not --crash llc -march=mips -mcpu=mips32 -mattr=fp64 < %s 2>&1 | FileCheck %s -check-prefix=32R1-FP64 11; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,32R2-NO-FP64A-BE 12; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefixes=ALL,32R2-FP64A 13; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,32R2-NO-FP64A-LE 14; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefixes=ALL,32R2-FP64A 15 16; RUN: llc -march=mips64 -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,64-NO-FP64A 17; RUN: not --crash llc -march=mips64 -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A 18; RUN: llc -march=mips64el -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,64-NO-FP64A 19; RUN: not --crash llc -march=mips64el -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A 20 21; 32R1-FP64: LLVM ERROR: FPU with 64-bit registers is not available on MIPS32 pre revision 2. Use -mcpu=mips32r2 or greater. 22; 64-FP64A: LLVM ERROR: -mattr=+nooddspreg requires the O32 ABI. 23 24declare double @dbl(); 25 26define double @call1(double %d, ...) { 27 ret double %d 28 29; ALL-LABEL: call1: 30 31; 32R2-NO-FP64A-LE-NOT: addiu $sp, $sp 32; 32R2-NO-FP64A-LE: mtc1 $4, $f0 33; 32R2-NO-FP64A-LE: mthc1 $5, $f0 34 35; 32R2-NO-FP64A-BE-NOT: addiu $sp, $sp 36; 32R2-NO-FP64A-BE: mtc1 $5, $f0 37; 32R2-NO-FP64A-BE: mthc1 $4, $f0 38 39; 32R2-FP64A: addiu $sp, $sp, -8 40; 32R2-FP64A: sw $4, 0($sp) 41; 32R2-FP64A: sw $5, 4($sp) 42; 32R2-FP64A: ldc1 $f0, 0($sp) 43 44; 64-NO-FP64A: daddiu $sp, $sp, -64 45; 64-NO-FP64A: mov.d $f0, $f12 46} 47 48define double @call2(i32 %i, double %d) { 49 ret double %d 50 51; ALL-LABEL: call2: 52 53; 32R2-NO-FP64A-LE: mtc1 $6, $f0 54; 32R2-NO-FP64A-LE: mthc1 $7, $f0 55 56; 32R2-NO-FP64A-BE: mtc1 $7, $f0 57; 32R2-NO-FP64A-BE: mthc1 $6, $f0 58 59; 32R2-FP64A: addiu $sp, $sp, -8 60; 32R2-FP64A: sw $6, 0($sp) 61; 32R2-FP64A: sw $7, 4($sp) 62; 32R2-FP64A: ldc1 $f0, 0($sp) 63 64; 64-NO-FP64A-NOT: daddiu $sp, $sp 65; 64-NO-FP64A: mov.d $f0, $f13 66} 67 68define double @call3(float %f1, float %f2, double %d) { 69 ret double %d 70 71; ALL-LABEL: call3: 72 73; 32R2-NO-FP64A-LE: mtc1 $6, $f0 74; 32R2-NO-FP64A-LE: mthc1 $7, $f0 75 76; 32R2-NO-FP64A-BE: mtc1 $7, $f0 77; 32R2-NO-FP64A-BE: mthc1 $6, $f0 78 79; 32R2-FP64A: addiu $sp, $sp, -8 80; 32R2-FP64A: sw $6, 0($sp) 81; 32R2-FP64A: sw $7, 4($sp) 82; 32R2-FP64A: ldc1 $f0, 0($sp) 83 84; 64-NO-FP64A-NOT: daddiu $sp, $sp 85; 64-NO-FP64A: mov.d $f0, $f14 86} 87 88define double @call4(float %f, double %d, ...) { 89 ret double %d 90 91; ALL-LABEL: call4: 92 93; 32R2-NO-FP64A-LE: mtc1 $6, $f0 94; 32R2-NO-FP64A-LE: mthc1 $7, $f0 95 96; 32R2-NO-FP64A-BE: mtc1 $7, $f0 97; 32R2-NO-FP64A-BE: mthc1 $6, $f0 98 99; 32R2-FP64A: addiu $sp, $sp, -8 100; 32R2-FP64A: sw $6, 0($sp) 101; 32R2-FP64A: sw $7, 4($sp) 102; 32R2-FP64A: ldc1 $f0, 0($sp) 103 104; 64-NO-FP64A: daddiu $sp, $sp, -48 105; 64-NO-FP64A: mov.d $f0, $f13 106} 107 108define double @call5(double %a, double %b, ...) { 109 %1 = fsub double %a, %b 110 ret double %1 111 112; ALL-LABEL: call5: 113 114; 32R2-NO-FP64A-LE-DAG: mtc1 $4, $[[T0:f[0-9]+]] 115; 32R2-NO-FP64A-LE-DAG: mthc1 $5, $[[T0:f[0-9]+]] 116; 32R2-NO-FP64A-LE-DAG: mtc1 $6, $[[T1:f[0-9]+]] 117; 32R2-NO-FP64A-LE-DAG: mthc1 $7, $[[T1:f[0-9]+]] 118; 32R2-NO-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]] 119 120; 32R2-NO-FP64A-BE-DAG: mtc1 $5, $[[T0:f[0-9]+]] 121; 32R2-NO-FP64A-BE-DAG: mthc1 $4, $[[T0:f[0-9]+]] 122; 32R2-NO-FP64A-BE-DAG: mtc1 $7, $[[T1:f[0-9]+]] 123; 32R2-NO-FP64A-BE-DAG: mthc1 $6, $[[T1:f[0-9]+]] 124; 32R2-NO-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]] 125 126; 32R2-FP64A: addiu $sp, $sp, -8 127; 32R2-FP64A: sw $6, 0($sp) 128; 32R2-FP64A: sw $7, 4($sp) 129; 32R2-FP64A: ldc1 $[[T1:f[0-9]+]], 0($sp) 130; 32R2-FP64A: sw $4, 0($sp) 131; 32R2-FP64A: sw $5, 4($sp) 132; 32R2-FP64A: ldc1 $[[T0:f[0-9]+]], 0($sp) 133; 32R2-FP64A: sub.d $f0, $[[T0]], $[[T1]] 134 135; 64-NO-FP64A: sub.d $f0, $f12, $f13 136} 137 138define double @move_from(double %d) { 139 %1 = call double @dbl() 140 %2 = call double @call2(i32 0, double %1) 141 ret double %2 142 143; ALL-LABEL: move_from: 144 145; 32R2-NO-FP64A-LE-DAG: mfc1 $6, $f0 146; 32R2-NO-FP64A-LE-DAG: mfhc1 $7, $f0 147 148; 32R2-NO-FP64A-BE-DAG: mfc1 $7, $f0 149; 32R2-NO-FP64A-BE-DAG: mfhc1 $6, $f0 150 151; 32R2-FP64A: addiu $sp, $sp, -32 152; 32R2-FP64A: sdc1 $f0, 16($sp) 153; 32R2-FP64A: lw $6, 16($sp) 154; FIXME: This store is redundant 155; 32R2-FP64A: sdc1 $f0, 16($sp) 156; 32R2-FP64A: lw $7, 20($sp) 157 158; 64-NO-FP64A: mov.d $f13, $f0 159} 160