mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-01 19:29:22 +00:00
Summary: This is because the FP64A the hardware will redirect 32-bit reads/writes from/to odd-numbered registers to the upper 32-bits of the corresponding even register. In effect, simulating FR=0 mode when FR=0 mode is not available. Unfortunately, we have to make the decision to avoid mfc1/mtc1 before register allocation so we currently do this for even registers too. FPXX has a similar requirement on 32-bit architectures that lack mfhc1/mthc1 so this patch also handles the affected moves from the FPU for FPXX too. Moves to the FPU were supported by an earlier commit. Differential Revision: http://reviews.llvm.org/D4484 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212938 91177308-0d34-0410-b5e6-96231b3b80d8
198 lines
7.0 KiB
LLVM
198 lines
7.0 KiB
LLVM
; Test that the FP64A ABI performs double precision moves via a spill/reload.
|
|
; The requirement is really that odd-numbered double precision registers do not
|
|
; use mfc1/mtc1 to move the bottom 32-bits (because the hardware will redirect
|
|
; this to the top 32-bits of the even register) but we have to make the decision
|
|
; before register allocation so we do this for all double-precision values.
|
|
|
|
; We don't test MIPS32r1 since support for 64-bit coprocessors (such as a 64-bit
|
|
; FPU) on a 32-bit architecture was added in MIPS32r2.
|
|
; FIXME: We currently don't test that attempting to use FP64 on MIPS32r1 is an
|
|
; error either. This is because a large number of CodeGen tests are
|
|
; incorrectly using this case. We should fix those test cases then add
|
|
; this check here.
|
|
|
|
; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-BE
|
|
; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A-BE
|
|
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-LE
|
|
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A-LE
|
|
|
|
; RUN: llc -march=mips64 -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A
|
|
; RUN: not llc -march=mips64 -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A
|
|
; RUN: llc -march=mips64el -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A
|
|
; RUN: not llc -march=mips64el -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A
|
|
|
|
; 64-FP64A: LLVM ERROR: -mattr=+nooddspreg requires the O32 ABI.
|
|
|
|
declare double @dbl();
|
|
|
|
define double @call1(double %d, ...) {
|
|
ret double %d
|
|
|
|
; ALL-LABEL: call1:
|
|
|
|
; 32R2-NO-FP64A-LE-NOT: addiu $sp, $sp
|
|
; 32R2-NO-FP64A-LE: mtc1 $4, $f0
|
|
; 32R2-NO-FP64A-LE: mthc1 $5, $f0
|
|
|
|
; 32R2-NO-FP64A-BE-NOT: addiu $sp, $sp
|
|
; 32R2-NO-FP64A-BE: mtc1 $5, $f0
|
|
; 32R2-NO-FP64A-BE: mthc1 $4, $f0
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-LE: sw $4, 0($sp)
|
|
; 32R2-FP64A-LE: sw $5, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-BE: sw $5, 0($sp)
|
|
; 32R2-FP64A-BE: sw $4, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
|
|
|
|
; 64-NO-FP64A: daddiu $sp, $sp, -64
|
|
; 64-NO-FP64A: mov.d $f0, $f12
|
|
}
|
|
|
|
define double @call2(i32 %i, double %d) {
|
|
ret double %d
|
|
|
|
; ALL-LABEL: call2:
|
|
|
|
; 32R2-NO-FP64A-LE: mtc1 $6, $f0
|
|
; 32R2-NO-FP64A-LE: mthc1 $7, $f0
|
|
|
|
; 32R2-NO-FP64A-BE: mtc1 $7, $f0
|
|
; 32R2-NO-FP64A-BE: mthc1 $6, $f0
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-LE: sw $6, 0($sp)
|
|
; 32R2-FP64A-LE: sw $7, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-BE: sw $7, 0($sp)
|
|
; 32R2-FP64A-BE: sw $6, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
|
|
|
|
; 64-NO-FP64A-NOT: daddiu $sp, $sp
|
|
; 64-NO-FP64A: mov.d $f0, $f13
|
|
}
|
|
|
|
define double @call3(float %f1, float %f2, double %d) {
|
|
ret double %d
|
|
|
|
; ALL-LABEL: call3:
|
|
|
|
; 32R2-NO-FP64A-LE: mtc1 $6, $f0
|
|
; 32R2-NO-FP64A-LE: mthc1 $7, $f0
|
|
|
|
; 32R2-NO-FP64A-BE: mtc1 $7, $f0
|
|
; 32R2-NO-FP64A-BE: mthc1 $6, $f0
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-LE: sw $6, 0($sp)
|
|
; 32R2-FP64A-LE: sw $7, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-BE: sw $7, 0($sp)
|
|
; 32R2-FP64A-BE: sw $6, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
|
|
|
|
; 64-NO-FP64A-NOT: daddiu $sp, $sp
|
|
; 64-NO-FP64A: mov.d $f0, $f14
|
|
}
|
|
|
|
define double @call4(float %f, double %d, ...) {
|
|
ret double %d
|
|
|
|
; ALL-LABEL: call4:
|
|
|
|
; 32R2-NO-FP64A-LE: mtc1 $6, $f0
|
|
; 32R2-NO-FP64A-LE: mthc1 $7, $f0
|
|
|
|
; 32R2-NO-FP64A-BE: mtc1 $7, $f0
|
|
; 32R2-NO-FP64A-BE: mthc1 $6, $f0
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-LE: sw $6, 0($sp)
|
|
; 32R2-FP64A-LE: sw $7, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-BE: sw $7, 0($sp)
|
|
; 32R2-FP64A-BE: sw $6, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
|
|
|
|
; 64-NO-FP64A: daddiu $sp, $sp, -48
|
|
; 64-NO-FP64A: mov.d $f0, $f13
|
|
}
|
|
|
|
define double @call5(double %a, double %b, ...) {
|
|
%1 = fsub double %a, %b
|
|
ret double %1
|
|
|
|
; ALL-LABEL: call5:
|
|
|
|
; 32R2-NO-FP64A-LE-DAG: mtc1 $4, $[[T0:f[0-9]+]]
|
|
; 32R2-NO-FP64A-LE-DAG: mthc1 $5, $[[T0:f[0-9]+]]
|
|
; 32R2-NO-FP64A-LE-DAG: mtc1 $6, $[[T1:f[0-9]+]]
|
|
; 32R2-NO-FP64A-LE-DAG: mthc1 $7, $[[T1:f[0-9]+]]
|
|
; 32R2-NO-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]]
|
|
|
|
; 32R2-NO-FP64A-BE-DAG: mtc1 $5, $[[T0:f[0-9]+]]
|
|
; 32R2-NO-FP64A-BE-DAG: mthc1 $4, $[[T0:f[0-9]+]]
|
|
; 32R2-NO-FP64A-BE-DAG: mtc1 $7, $[[T1:f[0-9]+]]
|
|
; 32R2-NO-FP64A-BE-DAG: mthc1 $6, $[[T1:f[0-9]+]]
|
|
; 32R2-NO-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]]
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-LE: sw $6, 0($sp)
|
|
; 32R2-FP64A-LE: sw $7, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $[[T1:f[0-9]+]], 0($sp)
|
|
; 32R2-FP64A-LE: sw $4, 0($sp)
|
|
; 32R2-FP64A-LE: sw $5, 4($sp)
|
|
; 32R2-FP64A-LE: ldc1 $[[T0:f[0-9]+]], 0($sp)
|
|
; 32R2-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]]
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -8
|
|
; 32R2-FP64A-BE: sw $7, 0($sp)
|
|
; 32R2-FP64A-BE: sw $6, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $[[T1:f[0-9]+]], 0($sp)
|
|
; 32R2-FP64A-BE: sw $5, 0($sp)
|
|
; 32R2-FP64A-BE: sw $4, 4($sp)
|
|
; 32R2-FP64A-BE: ldc1 $[[T0:f[0-9]+]], 0($sp)
|
|
; 32R2-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]]
|
|
|
|
; 64-NO-FP64A: sub.d $f0, $f12, $f13
|
|
}
|
|
|
|
define double @move_from(double %d) {
|
|
%1 = call double @dbl()
|
|
%2 = call double @call2(i32 0, double %1)
|
|
ret double %2
|
|
|
|
; ALL-LABEL: move_from:
|
|
|
|
; 32R2-NO-FP64A-LE-DAG: mfc1 $6, $f0
|
|
; 32R2-NO-FP64A-LE-DAG: mfhc1 $7, $f0
|
|
|
|
; 32R2-NO-FP64A-BE-DAG: mfc1 $7, $f0
|
|
; 32R2-NO-FP64A-BE-DAG: mfhc1 $6, $f0
|
|
|
|
; 32R2-FP64A-LE: addiu $sp, $sp, -32
|
|
; 32R2-FP64A-LE: sdc1 $f0, 16($sp)
|
|
; 32R2-FP64A-LE: lw $6, 16($sp)
|
|
; FIXME: This store is redundant
|
|
; 32R2-FP64A-LE: sdc1 $f0, 16($sp)
|
|
; 32R2-FP64A-LE: lw $7, 20($sp)
|
|
|
|
; 32R2-FP64A-BE: addiu $sp, $sp, -32
|
|
; 32R2-FP64A-BE: sdc1 $f0, 16($sp)
|
|
; 32R2-FP64A-BE: lw $6, 20($sp)
|
|
; FIXME: This store is redundant
|
|
; 32R2-FP64A-BE: sdc1 $f0, 16($sp)
|
|
; 32R2-FP64A-BE: lw $7, 16($sp)
|
|
|
|
; 64-NO-FP64A: mov.d $f13, $f0
|
|
}
|