products/Sources/formale Sprachen/C/Android/art/art/tools/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 4 kB image not shown  

 asm_support_arm.S

  Interaktion und
PortierbarkeitSparc
 

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_S_
#define ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_S_

#include "asm_support_arm.h"
#include "interpreter/cfi_asm_support.h"

// Define special registers.

// Register holding suspend check count down.
#define rSUSPEND r4
// Register holding Thread::Current().
#define rSELF r9

#ifdef RESERVE_MARKING_REGISTER
// Marking Register, holding Thread::Current()->GetIsGcMarking().
#define rMR r8
#endif

.syntax unified
.arch armv7-a
.arch_extension idiv
.thumb

.macro CFI_EXPRESSION_BREG n, b, offset
    .if (-0x40 <= (\offset)) && ((\offset) < 0x40)
        CFI_EXPRESSION_BREG_1(\n, \b, \offset)
    .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000)
        CFI_EXPRESSION_BREG_2(\n, \b, \offset)
    .else
        .error "Unsupported offset"
    .endif
.endm

.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size
    .if ((\size) < 0)
        .error "Size should be positive"
    .endif
    .if (((\offset) < -0x40) || ((\offset) >= 0x40))
        .error "Unsupported offset"
    .endif
    .if ((\size) < 0x80)
        CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size)
    .elseif ((\size) < 0x4000)
        CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size)
    .else
        .error "Unsupported size"
    .endif
.endm

.macro CFI_REMEMBER_STATE
    .cfi_remember_state
.endm

// The spec is not clear whether the CFA is part of the saved state and tools
// differ in the behaviour, so explicitly set the CFA to avoid any ambiguity.
// The restored CFA state should match the CFA state during CFI_REMEMBER_STATE.
.macro CFI_RESTORE_STATE_AND_DEF_CFA reg, offset
    .cfi_restore_state
    .cfi_def_cfa \reg, \offset
.endm

// Common ENTRY declaration code for ARM and thumb, an ENTRY should always be paired with an END.
.macro DEF_ENTRY thumb_or_arm, name, alignment
    \thumb_or_arm
// Clang ignores .thumb_func and requires an explicit .thumb. Investigate whether we should still
// carry around the .thumb_func.
    .ifc \thumb_or_arm, .thumb_func
        .thumb
    .endif
    .type \name, #function
    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
    .global \name
    .balign \alignment
\name:
    .cfi_startproc
    .fnstart
.endm

// A thumb2 style ENTRY.
.macro ENTRY name
    DEF_ENTRY .thumb_func, \name, 16
.endm
.macro ENTRY_ALIGNED name, alignment
    DEF_ENTRY .thumb_func, \name, \alignment
.endm

// A ARM style ENTRY.
.macro ARM_ENTRY name
    DEF_ENTRY .arm, \name, 16
.endm

// Terminate an ENTRY.
.macro END name
    .fnend
    .cfi_endproc
    .size \name, .-\name
.endm

// Declare an unimplemented ENTRY that will halt a debugger.
.macro UNIMPLEMENTED name
    ENTRY \name
    bkpt
    bkpt
    END \name
.endm

// Macro to poison (negate) the reference for heap poisoning.
.macro POISON_HEAP_REF rRef, s=""
#ifdef USE_HEAP_POISONING
    rsb\s \rRef, \rRef, #0
#endif  // USE_HEAP_POISONING
.endm

// Macro to unpoison (negate) the reference for heap poisoning.
.macro UNPOISON_HEAP_REF rRef, s=""
#ifdef USE_HEAP_POISONING
    rsb\s \rRef, \rRef, #0
#endif  // USE_HEAP_POISONING
.endm

.macro INCREASE_FRAME frame_adjustment
    sub sp, sp, #(\frame_adjustment)
    .cfi_adjust_cfa_offset (\frame_adjustment)
.endm

.macro DECREASE_FRAME frame_adjustment
    add sp, sp, #(\frame_adjustment)
    .cfi_adjust_cfa_offset -(\frame_adjustment)
.endm

.macro LOAD_RUNTIME_INSTANCE rDest
    movw \rDest, #:lower16:(_ZN3art7Runtime9instance_E - (. + 12))
    movt \rDest, #:upper16:(_ZN3art7Runtime9instance_E - (. + 8))
    add \rDest, pc
    ldr \rDest, [\rDest]
.endm

// Macro to refresh the Marking Register (R8).
//
// This macro must be called at the end of functions implementing
// entrypoints that possibly (directly or indirectly) perform a
// suspend check (before they return).
.macro REFRESH_MARKING_REGISTER
#ifdef RESERVE_MARKING_REGISTER
    ldr rMR, [rSELF, #THREAD_IS_GC_MARKING_OFFSET]
#endif
.endm

.macro CONDITIONAL_CBZ reg, reg_if, dest
.ifc \reg, \reg_if
    cbz \reg, \dest
.endif
.endm

.macro CONDITIONAL_CMPBZ reg, reg_if, dest
.ifc \reg, \reg_if
    cmp \reg, #0
    beq \dest
.endif
.endm

// Use CBZ if the register is in {r0, r7} otherwise compare and branch.
.macro SMART_CBZ reg, dest
    CONDITIONAL_CBZ \reg, r0, \dest
    CONDITIONAL_CBZ \reg, r1, \dest
    CONDITIONAL_CBZ \reg, r2, \dest
    CONDITIONAL_CBZ \reg, r3, \dest
    CONDITIONAL_CBZ \reg, r4, \dest
    CONDITIONAL_CBZ \reg, r5, \dest
    CONDITIONAL_CBZ \reg, r6, \dest
    CONDITIONAL_CBZ \reg, r7, \dest
    CONDITIONAL_CMPBZ \reg, r8, \dest
    CONDITIONAL_CMPBZ \reg, r9, \dest
    CONDITIONAL_CMPBZ \reg, r10, \dest
    CONDITIONAL_CMPBZ \reg, r11, \dest
    CONDITIONAL_CMPBZ \reg, r12, \dest
    CONDITIONAL_CMPBZ \reg, r13, \dest
    CONDITIONAL_CMPBZ \reg, r14, \dest
    CONDITIONAL_CMPBZ \reg, r15, \dest
.endm

    /*
     * Macro that sets up the callee save frame to conform with
     * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs), except for storing the method.
     */

.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
    // Note: We could avoid saving R8 in the case of Baker read
    // barriers, as it is overwritten by REFRESH_MARKING_REGISTER
    // later; but it's not worth handling this special case.
    push {r1-r3, r5-r8, r10-r11, lr}   @ 10 words of callee saves and args.
    .cfi_adjust_cfa_offset 40
    .cfi_rel_offset r5, 12
    .cfi_rel_offset r6, 16
    .cfi_rel_offset r7, 20
    .cfi_rel_offset r8, 24
    .cfi_rel_offset r10, 28
    .cfi_rel_offset r11, 32
    .cfi_rel_offset lr, 36
    vpush {s0-s15}                     @ 16 words of float args.
    .cfi_adjust_cfa_offset 64
    sub sp, #8                         @ 2 words of space, alignment padding and Method*
    .cfi_adjust_cfa_offset 8
    // Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 40 + 64 + 8)
#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(ARM) size not as expected."
#endif
.endm

.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME
    add  sp, #8                      @ rewind sp
    .cfi_adjust_cfa_offset -8
    vpop {s0-s15}
    .cfi_adjust_cfa_offset -64
    // Note: Likewise, we could avoid restoring R8 in the case of Baker
    // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER
    // later; but it's not worth handling this special case.
    pop {r1-r3, r5-r8, r10-r11, lr}  @ 10 words of callee saves and args.
    .cfi_restore r5
    .cfi_restore r6
    .cfi_restore r7
    .cfi_restore r8
    .cfi_restore r10
    .cfi_restore r11
    .cfi_restore lr
    .cfi_adjust_cfa_offset -40
.endm

    /*
     * Macro to spill the GPRs.
     */

.macro SPILL_ALL_CALLEE_SAVE_GPRS
    push {r4-r11, lr}                             @ 9 words (36 bytes) of callee saves.
    .cfi_adjust_cfa_offset 36
    .cfi_rel_offset r4, 0
    .cfi_rel_offset r5, 4
    .cfi_rel_offset r6, 8
    .cfi_rel_offset r7, 12
    .cfi_rel_offset r8, 16
    .cfi_rel_offset r9, 20
    .cfi_rel_offset r10, 24
    .cfi_rel_offset r11, 28
    .cfi_rel_offset lr, 32
.endm

    /*
     * Macro that sets up the callee save frame to conform with
     * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves)
     */

.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME rTemp
    SPILL_ALL_CALLEE_SAVE_GPRS                    @ 9 words (36 bytes) of callee saves.
    vpush {s16-s31}                               @ 16 words (64 bytes) of floats.
    .cfi_adjust_cfa_offset 64
    sub sp, #12                                   @ 3 words of space, bottom word will hold Method*
    .cfi_adjust_cfa_offset 12
    LOAD_RUNTIME_INSTANCE \rTemp                  @ Load Runtime::Current into rTemp.
    @ Load kSaveAllCalleeSaves Method* into rTemp.
    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET]
    str \rTemp, [sp, #0]                          @ Place Method* at bottom of stack.
    str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.

     // Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 36 + 64 + 12)
#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(ARM) size not as expected."
#endif
.endm

    /*
     * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
     * exception is Thread::Current()->exception_ when the runtime method frame is ready.
     */

.macro DELIVER_PENDING_EXCEPTION_FRAME_READY
    mov    r0, rSELF                           @ pass Thread::Current
    bl     artDeliverPendingExceptionFromCode  @ artDeliverPendingExceptionFromCode(Thread*)
    bl art_quick_do_long_jump                  @ (Context*)
    bkpt  // Unreached
.endm

    /*
     * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending
     * exception is Thread::Current()->exception_.
     */

.macro DELIVER_PENDING_EXCEPTION
    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r0       @ save callee saves for throw
    DELIVER_PENDING_EXCEPTION_FRAME_READY
.endm

.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg
    ldr \reg, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
    cbnz \reg, 1f
    bx lr
1:
    DELIVER_PENDING_EXCEPTION
.endm

.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION
    ldr ip, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
    cmp ip, #0
    bne 1f
    bx lr
1:
    DELIVER_PENDING_EXCEPTION
.endm

    /*
     * Macro that sets up the callee save frame to conform with
     * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly).
     */

.macro SETUP_SAVE_REFS_ONLY_FRAME rTemp
    // Note: We could avoid saving R8 in the case of Baker read
    // barriers, as it is overwritten by REFRESH_MARKING_REGISTER
    // later; but it's not worth handling this special case.
    push {r5-r8, r10-r11, lr}                     @ 7 words of callee saves
    .cfi_adjust_cfa_offset 28
    .cfi_rel_offset r5, 0
    .cfi_rel_offset r6, 4
    .cfi_rel_offset r7, 8
    .cfi_rel_offset r8, 12
    .cfi_rel_offset r10, 16
    .cfi_rel_offset r11, 20
    .cfi_rel_offset lr, 24
    sub sp, #4                                    @ bottom word will hold Method*
    .cfi_adjust_cfa_offset 4
    LOAD_RUNTIME_INSTANCE \rTemp                  @ Load Runtime::Current into rTemp.
    @ Load kSaveRefsOnly Method* into rTemp.
    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET]
    str \rTemp, [sp, #0]                          @ Place Method* at bottom of stack.
    str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.

    // Ugly compile-time check, but we only have the preprocessor.
#if (FRAME_SIZE_SAVE_REFS_ONLY != 28 + 4)
#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM) size not as expected."
#endif
.endm

.macro RESTORE_SAVE_REFS_ONLY_FRAME
    add sp, #4               @ bottom word holds Method*
    .cfi_adjust_cfa_offset -4
    // Note: Likewise, we could avoid restoring R8 in the case of Baker
    // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER
    // later; but it's not worth handling this special case.
    pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
    .cfi_restore r5
    .cfi_restore r6
    .cfi_restore r7
    .cfi_restore r8
    .cfi_restore r10
    .cfi_restore r11
    .cfi_restore lr
    .cfi_adjust_cfa_offset -28
.endm

// Locking is needed for both managed code and JNI stubs.
.macro LOCK_OBJECT_FAST_PATH obj, tmp1, tmp2, tmp3, slow_lock, can_be_null
    ldr    \tmp1, [rSELF, #THREAD_ID_OFFSET]
    .if \can_be_null
        cbz \obj, \slow_lock
    .endif
1:
    ldrex  \tmp2, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
    eor    \tmp3, \tmp2, \tmp1        @ Prepare the value to store if unlocked
                                      @   (thread id, count of 0 and preserved read barrier bits),
                                      @ or prepare to compare thread id for recursive lock check
                                      @   (lock_word.ThreadId() ^ self->ThreadId()).
    ands   ip, \tmp2, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  @ Test the non-gc bits.
    bne    2f                         @ Check if unlocked.
    @ unlocked case - store tmp3: original lock word plus thread id, preserved read barrier bits.
    strex  \tmp2, \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
    cbnz   \tmp2, 3f                   @ If store failed, retry.
    dmb    ish                        @ Full (LoadLoad|LoadStore) memory barrier.
    bx lr
2:  @ tmp2: original lock word, tmp1: thread_id, tmp3: tmp2 ^ tmp1
#if LOCK_WORD_THIN_LOCK_COUNT_SHIFT + LOCK_WORD_THIN_LOCK_COUNT_SIZE != LOCK_WORD_GC_STATE_SHIFT
#error "Expecting thin lock count and gc state in consecutive bits."
#endif
                                      @ Check lock word state and thread id together.
    bfc    \tmp3, \
           #LOCK_WORD_THIN_LOCK_COUNT_SHIFT, \
           #(LOCK_WORD_THIN_LOCK_COUNT_SIZE + LOCK_WORD_GC_STATE_SIZE)
    cbnz   \tmp3, \slow_lock          @ if either of the top two bits are set, or the lock word's
                                      @ thread id did not match, go slow path.
    add    \tmp3, \tmp2, #LOCK_WORD_THIN_LOCK_COUNT_ONE  @ Increment the recursive lock count.
                                      @ Extract the new thin lock count for overflow check.
    ubfx   \tmp2, \tmp3, #LOCK_WORD_THIN_LOCK_COUNT_SHIFT, #LOCK_WORD_THIN_LOCK_COUNT_SIZE
    cbz    \tmp2, \slow_lock          @ Zero as the new count indicates overflow, go slow path.
                                      @ strex necessary for read barrier bits.
    strex  \tmp2, \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
    cbnz   \tmp2, 3f                  @ If strex failed, retry.
    bx lr
3:
    b      1b                         @ retry
.endm

// Unlocking is needed for both managed code and JNI stubs.
.macro UNLOCK_OBJECT_FAST_PATH obj, tmp1, tmp2, tmp3, slow_unlock, can_be_null
    ldr    \tmp1, [rSELF, #THREAD_ID_OFFSET]
    .if \can_be_null
        cbz    \obj, \slow_unlock
    .endif
1:
#ifndef USE_READ_BARRIER
    ldr    \tmp2, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
#else
                                      @ Need to use atomic instructions for read barrier.
    ldrex  \tmp2, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
#endif
    eor    \tmp3, \tmp2, \tmp1        @ Prepare the value to store if simply locked
                                      @   (mostly 0s, and preserved read barrier bits),
                                      @ or prepare to compare thread id for recursive lock check
                                      @   (lock_word.ThreadId() ^ self->ThreadId()).
    ands   ip, \tmp3, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED  @ Test the non-gc bits.
    bne    2f                         @ Locked recursively or by other thread?
    @ Transition to unlocked.
    dmb    ish                        @ Full (LoadStore|StoreStore) memory barrier.
#ifndef USE_READ_BARRIER
    str    \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
#else
                                      @ strex necessary for read barrier bits
    strex  \tmp2, \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
    cbnz   \tmp2, 3f                  @ If the store failed, retry.
#endif
    bx     lr
2:  @ tmp2: original lock word, tmp1: thread_id, tmp3: tmp2 ^ tmp1
#if LOCK_WORD_THIN_LOCK_COUNT_SHIFT + LOCK_WORD_THIN_LOCK_COUNT_SIZE != LOCK_WORD_GC_STATE_SHIFT
#error "Expecting thin lock count and gc state in consecutive bits."
#endif
                                      @ Check lock word state and thread id together,
    bfc    \tmp3, \
           #LOCK_WORD_THIN_LOCK_COUNT_SHIFT, \
           #(LOCK_WORD_THIN_LOCK_COUNT_SIZE + LOCK_WORD_GC_STATE_SIZE)
    cbnz   \tmp3, \slow_unlock        @ if either of the top two bits are set, or the lock word's
                                      @ thread id did not match, go slow path.
    sub    \tmp3, \tmp2, #LOCK_WORD_THIN_LOCK_COUNT_ONE  @ Decrement recursive lock count.
#ifndef USE_READ_BARRIER
    str    \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
#else
                                      @ strex necessary for read barrier bits.
    strex  \tmp2, \tmp3, [\obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET]
    cbnz   \tmp2, 3f                  @ If the store failed, retry.
#endif
    bx     lr
3:
    b      1b                         @ retry
.endm

#endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_

Messung V0.5 in Prozent
C=89 H=96 G=92

¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.14Angebot  (Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-29) ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.