Mterp/arm: Add CFI directives.

Includes reworking of float_to_long and double_to_long to
elminate frame (as suggested by vmarko).

Test: m ART_TEST_INTERPRETER=true test-art-target (in progress)
Bug: 31456348
Change-Id: Ic4e985b977f76c4df926559b187d92d969206514
diff --git a/runtime/interpreter/mterp/arm/entry.S b/runtime/interpreter/mterp/arm/entry.S
index a6b131d..e53c054 100644
--- a/runtime/interpreter/mterp/arm/entry.S
+++ b/runtime/interpreter/mterp/arm/entry.S
@@ -31,10 +31,19 @@
  *
  */
 
-ExecuteMterpImpl:
-    .fnstart
-    .save {r3-r10,fp,lr}
+ENTRY ExecuteMterpImpl
     stmfd   sp!, {r3-r10,fp,lr}         @ save 10 regs, (r3 just to align 64)
+    .cfi_adjust_cfa_offset 40
+    .cfi_rel_offset r3, 0
+    .cfi_rel_offset r4, 4
+    .cfi_rel_offset r5, 8
+    .cfi_rel_offset r6, 12
+    .cfi_rel_offset r7, 16
+    .cfi_rel_offset r8, 20
+    .cfi_rel_offset r9, 24
+    .cfi_rel_offset r10, 28
+    .cfi_rel_offset fp, 32
+    .cfi_rel_offset lr, 36
 
     /* Remember the return register */
     str     r3, [r2, #SHADOWFRAME_RESULT_REGISTER_OFFSET]
diff --git a/runtime/interpreter/mterp/arm/footer.S b/runtime/interpreter/mterp/arm/footer.S
index cd32ea2..c6801e5 100644
--- a/runtime/interpreter/mterp/arm/footer.S
+++ b/runtime/interpreter/mterp/arm/footer.S
@@ -294,6 +294,5 @@
     mov     r0, rINST                               @ restore return value
     ldmfd   sp!, {r3-r10,fp,pc}                     @ restore 10 regs and return
 
-    .fnend
-    .size   ExecuteMterpImpl, .-ExecuteMterpImpl
+    END ExecuteMterpImpl
 
diff --git a/runtime/interpreter/mterp/arm/header.S b/runtime/interpreter/mterp/arm/header.S
index 039bcbe..597d9d4 100644
--- a/runtime/interpreter/mterp/arm/header.S
+++ b/runtime/interpreter/mterp/arm/header.S
@@ -287,3 +287,24 @@
 .macro REFRESH_IBASE
   ldr     rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET]
 .endm
+
+/*
+ * cfi support macros.
+ */
+.macro ENTRY name
+    .arm
+    .type \name, #function
+    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
+    .global \name
+    /* Cache alignment for function entry */
+    .balign 16
+\name:
+    .cfi_startproc
+    .fnstart
+.endm
+
+.macro END name
+    .fnend
+    .cfi_endproc
+    .size \name, .-\name
+.endm
diff --git a/runtime/interpreter/mterp/arm/op_double_to_long.S b/runtime/interpreter/mterp/arm/op_double_to_long.S
index b100810..19ff723 100644
--- a/runtime/interpreter/mterp/arm/op_double_to_long.S
+++ b/runtime/interpreter/mterp/arm/op_double_to_long.S
@@ -1,4 +1,3 @@
-@include "arm/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
 %include "arm/unopWide.S" {"instr":"bl      d2l_doconv"}
 
 %break
@@ -10,43 +9,25 @@
  * to modest integer.  The EABI convert function isn't doing this for us.
  */
 d2l_doconv:
-    stmfd   sp!, {r4, r5, lr}           @ save regs
-    mov     r3, #0x43000000             @ maxlong, as a double (high word)
-    add     r3, #0x00e00000             @  0x43e00000
-    mov     r2, #0                      @ maxlong, as a double (low word)
-    sub     sp, sp, #4                  @ align for EABI
-    mov     r4, r0                      @ save a copy of r0
-    mov     r5, r1                      @  and r1
-    bl      __aeabi_dcmpge              @ is arg >= maxlong?
-    cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
-    mvnne   r1, #0x80000000
-    bne     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    mov     r3, #0xc3000000             @ minlong, as a double (high word)
-    add     r3, #0x00e00000             @  0xc3e00000
-    mov     r2, #0                      @ minlong, as a double (low word)
-    bl      __aeabi_dcmple              @ is arg <= minlong?
-    cmp     r0, #0                      @ nonzero == yes
-    movne   r0, #0                      @ return minlong (8000000000000000)
-    movne   r1, #0x80000000
-    bne     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    mov     r2, r4                      @ compare against self
-    mov     r3, r5
-    bl      __aeabi_dcmpeq              @ is arg == self?
-    cmp     r0, #0                      @ zero == no
-    moveq   r1, #0                      @ return zero for NaN
-    beq     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    bl      __aeabi_d2lz                @ convert double to long
-
-1:
-    add     sp, sp, #4
-    ldmfd   sp!, {r4, r5, pc}
+    ubfx    r2, r1, #20, #11            @ grab the exponent
+    movw    r3, #0x43e
+    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
+    bhs     d2l_special_cases
+    b       __aeabi_d2lz                @ tail call to convert double to long
+d2l_special_cases:
+    movw    r3, #0x7ff
+    cmp     r2, r3
+    beq     d2l_maybeNaN                @ NaN?
+d2l_notNaN:
+    adds    r1, r1, r1                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adc     r0, r0, #0
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+d2l_maybeNaN:
+    orrs    r3, r0, r1, lsl #12
+    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
diff --git a/runtime/interpreter/mterp/arm/op_float_to_long.S b/runtime/interpreter/mterp/arm/op_float_to_long.S
index 5c8680f..1770ea0 100644
--- a/runtime/interpreter/mterp/arm/op_float_to_long.S
+++ b/runtime/interpreter/mterp/arm/op_float_to_long.S
@@ -1,4 +1,3 @@
-@include "arm/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
 %include "arm/unopWider.S" {"instr":"bl      f2l_doconv"}
 
 %break
@@ -10,30 +9,23 @@
  * to modest integer.  The EABI convert function isn't doing this for us.
  */
 f2l_doconv:
-    stmfd   sp!, {r4, lr}
-    mov     r1, #0x5f000000             @ (float)maxlong
-    mov     r4, r0
-    bl      __aeabi_fcmpge              @ is arg >= maxlong?
-    cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0                      @ return maxlong (7fffffff)
-    mvnne   r1, #0x80000000
-    popne   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, #0xdf000000             @ (float)minlong
-    bl      __aeabi_fcmple              @ is arg <= minlong?
-    cmp     r0, #0                      @ nonzero == yes
-    movne   r0, #0                      @ return minlong (80000000)
-    movne   r1, #0x80000000
-    popne   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r4
-    bl      __aeabi_fcmpeq              @ is arg == self?
-    cmp     r0, #0                      @ zero == no
-    moveq   r1, #0                      @ return zero for NaN
-    popeq   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    bl      __aeabi_f2lz                @ convert float to long
-    ldmfd   sp!, {r4, pc}
+    ubfx    r2, r0, #23, #8             @ grab the exponent
+    cmp     r2, #0xbe                   @ MININT < x > MAXINT?
+    bhs     f2l_special_cases
+    b       __aeabi_f2lz                @ tail call to convert float to long
+f2l_special_cases:
+    cmp     r2, #0xff                   @ NaN or infinity?
+    beq     f2l_maybeNaN
+f2l_notNaN:
+    adds    r0, r0, r0                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adcs    r0, r0, #0                  @ convert maxlong to minlong if exp negative
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+f2l_maybeNaN:
+    lsls    r3, r0, #9
+    beq     f2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 4d540d7..c80d6b9 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -295,6 +295,27 @@
   ldr     rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET]
 .endm
 
+/*
+ * cfi support macros.
+ */
+.macro ENTRY name
+    .arm
+    .type \name, #function
+    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
+    .global \name
+    /* Cache alignment for function entry */
+    .balign 16
+\name:
+    .cfi_startproc
+    .fnstart
+.endm
+
+.macro END name
+    .fnend
+    .cfi_endproc
+    .size \name, .-\name
+.endm
+
 /* File: arm/entry.S */
 /*
  * Copyright (C) 2016 The Android Open Source Project
@@ -329,10 +350,19 @@
  *
  */
 
-ExecuteMterpImpl:
-    .fnstart
-    .save {r3-r10,fp,lr}
+ENTRY ExecuteMterpImpl
     stmfd   sp!, {r3-r10,fp,lr}         @ save 10 regs, (r3 just to align 64)
+    .cfi_adjust_cfa_offset 40
+    .cfi_rel_offset r3, 0
+    .cfi_rel_offset r4, 4
+    .cfi_rel_offset r5, 8
+    .cfi_rel_offset r6, 12
+    .cfi_rel_offset r7, 16
+    .cfi_rel_offset r8, 20
+    .cfi_rel_offset r9, 24
+    .cfi_rel_offset r10, 28
+    .cfi_rel_offset fp, 32
+    .cfi_rel_offset lr, 36
 
     /* Remember the return register */
     str     r3, [r2, #SHADOWFRAME_RESULT_REGISTER_OFFSET]
@@ -3664,7 +3694,6 @@
     .balign 128
 .L_op_float_to_long: /* 0x88 */
 /* File: arm/op_float_to_long.S */
-@include "arm/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
 /* File: arm/unopWider.S */
     /*
      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
@@ -3742,7 +3771,6 @@
     .balign 128
 .L_op_double_to_long: /* 0x8b */
 /* File: arm/op_double_to_long.S */
-@include "arm/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
 /* File: arm/unopWide.S */
     /*
      * Generic 64-bit unary operation.  Provide an "instr" line that
@@ -7386,33 +7414,26 @@
  * to modest integer.  The EABI convert function isn't doing this for us.
  */
 f2l_doconv:
-    stmfd   sp!, {r4, lr}
-    mov     r1, #0x5f000000             @ (float)maxlong
-    mov     r4, r0
-    bl      __aeabi_fcmpge              @ is arg >= maxlong?
-    cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0                      @ return maxlong (7fffffff)
-    mvnne   r1, #0x80000000
-    popne   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, #0xdf000000             @ (float)minlong
-    bl      __aeabi_fcmple              @ is arg <= minlong?
-    cmp     r0, #0                      @ nonzero == yes
-    movne   r0, #0                      @ return minlong (80000000)
-    movne   r1, #0x80000000
-    popne   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r4
-    bl      __aeabi_fcmpeq              @ is arg == self?
-    cmp     r0, #0                      @ zero == no
-    moveq   r1, #0                      @ return zero for NaN
-    popeq   {r4, pc}
-
-    mov     r0, r4                      @ recover arg
-    bl      __aeabi_f2lz                @ convert float to long
-    ldmfd   sp!, {r4, pc}
+    ubfx    r2, r0, #23, #8             @ grab the exponent
+    cmp     r2, #0xbe                   @ MININT < x > MAXINT?
+    bhs     f2l_special_cases
+    b       __aeabi_f2lz                @ tail call to convert float to long
+f2l_special_cases:
+    cmp     r2, #0xff                   @ NaN or infinity?
+    beq     f2l_maybeNaN
+f2l_notNaN:
+    adds    r0, r0, r0                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adcs    r0, r0, #0                  @ convert maxlong to minlong if exp negative
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+f2l_maybeNaN:
+    lsls    r3, r0, #9
+    beq     f2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
 
 /* continuation for op_double_to_long */
 /*
@@ -7423,46 +7444,28 @@
  * to modest integer.  The EABI convert function isn't doing this for us.
  */
 d2l_doconv:
-    stmfd   sp!, {r4, r5, lr}           @ save regs
-    mov     r3, #0x43000000             @ maxlong, as a double (high word)
-    add     r3, #0x00e00000             @  0x43e00000
-    mov     r2, #0                      @ maxlong, as a double (low word)
-    sub     sp, sp, #4                  @ align for EABI
-    mov     r4, r0                      @ save a copy of r0
-    mov     r5, r1                      @  and r1
-    bl      __aeabi_dcmpge              @ is arg >= maxlong?
-    cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
-    mvnne   r1, #0x80000000
-    bne     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    mov     r3, #0xc3000000             @ minlong, as a double (high word)
-    add     r3, #0x00e00000             @  0xc3e00000
-    mov     r2, #0                      @ minlong, as a double (low word)
-    bl      __aeabi_dcmple              @ is arg <= minlong?
-    cmp     r0, #0                      @ nonzero == yes
-    movne   r0, #0                      @ return minlong (8000000000000000)
-    movne   r1, #0x80000000
-    bne     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    mov     r2, r4                      @ compare against self
-    mov     r3, r5
-    bl      __aeabi_dcmpeq              @ is arg == self?
-    cmp     r0, #0                      @ zero == no
-    moveq   r1, #0                      @ return zero for NaN
-    beq     1f
-
-    mov     r0, r4                      @ recover arg
-    mov     r1, r5
-    bl      __aeabi_d2lz                @ convert double to long
-
-1:
-    add     sp, sp, #4
-    ldmfd   sp!, {r4, r5, pc}
+    ubfx    r2, r1, #20, #11            @ grab the exponent
+    movw    r3, #0x43e
+    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
+    bhs     d2l_special_cases
+    b       __aeabi_d2lz                @ tail call to convert double to long
+d2l_special_cases:
+    movw    r3, #0x7ff
+    cmp     r2, r3
+    beq     d2l_maybeNaN                @ NaN?
+d2l_notNaN:
+    adds    r1, r1, r1                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adcs    r0, r0, #0
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+d2l_maybeNaN:
+    orrs    r3, r0, r1, lsl #12
+    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
 
     .size   artMterpAsmSisterStart, .-artMterpAsmSisterStart
     .global artMterpAsmSisterEnd
@@ -12115,6 +12118,17 @@
     cmp     rPROFILE, #0
     bgt     MterpProfileActive                      @ if > 0, we may have some counts to report.
     ldmfd   sp!, {r3-r10,fp,pc}                     @ restore 10 regs and return
+    .cfi_restore r3
+    .cfi_restore r4
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r9
+    .cfi_restore r9
+    .cfi_restore r10
+    .cfi_restore fp
+    .cfi_restore pc
+    .cfi_adjust_cfa_offset -40
 
 MterpProfileActive:
     mov     rINST, r0                               @ stash return value
@@ -12126,8 +12140,18 @@
     bl      MterpAddHotnessBatch                    @ (method, shadow_frame, self)
     mov     r0, rINST                               @ restore return value
     ldmfd   sp!, {r3-r10,fp,pc}                     @ restore 10 regs and return
+    .cfi_restore r3
+    .cfi_restore r4
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r9
+    .cfi_restore r9
+    .cfi_restore r10
+    .cfi_restore fp
+    .cfi_restore pc
+    .cfi_adjust_cfa_offset -40
 
-    .fnend
-    .size   ExecuteMterpImpl, .-ExecuteMterpImpl
+    END ExecuteMterpImpl
 
 
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index 146f309..7754b75 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -390,6 +390,8 @@
     assertLongEquals(9223372036854775807L, $opt$noinline$FloatToLong(9223372036854775807F));  // 2^63 - 1
     assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(-9223372036854775807F));  // -(2^63 - 1)
     assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(-9223372036854775808F));  // -(2^63)
+    assertLongEquals(9223371487098961920L, $opt$noinline$FloatToLong(9223371487098961920F));  // Math.nextAfter(2F^63, 0)
+    assertLongEquals(-9223371487098961920L, $opt$noinline$FloatToLong(-9223371487098961920F));  // Math.nextAfter(-2F^63, 0)
     assertLongEquals(0L, $opt$noinline$FloatToLong(Float.NaN));
     assertLongEquals(9223372036854775807L, $opt$noinline$FloatToLong(Float.POSITIVE_INFINITY));
     assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(Float.NEGATIVE_INFINITY));
@@ -469,6 +471,8 @@
     assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(-9223372036854775807D));  // -(2^63 - 1)
     assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(-9223372036854775808D));  // -(2^63)
     assertLongEquals(0L, $opt$noinline$DoubleToLong(Double.NaN));
+    assertLongEquals(9223372036854774784L, $opt$noinline$DoubleToLong(9223372036854774784D));  // Math.nextAfter(2D^63, 0)
+    assertLongEquals(-9223372036854774784L, $opt$noinline$DoubleToLong(-9223372036854774784D));  // Math.nextAfter(-2D^63, 0)
     assertLongEquals(9223372036854775807L, $opt$noinline$DoubleToLong(Double.POSITIVE_INFINITY));
     assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(Double.NEGATIVE_INFINITY));
   }