1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
/*
* 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_MIPS_ASM_SUPPORT_MIPS_S_
#define ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
#include "asm_support_mips.h"
// Define special registers.
// Register holding suspend check count down.
#define rSUSPEND $s0
// Register holding Thread::Current().
#define rSELF $s1
// Declare a function called name, doesn't set up $gp.
.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
.type \name, %function
.global \name
// Cache alignment for function entry.
.balign 16
\name:
.cfi_startproc
// Ensure we get a sane starting CFA.
.cfi_def_cfa $sp, \cfa_offset
.endm
// Declare a function called name, doesn't set up $gp.
.macro ENTRY_NO_GP name
ENTRY_NO_GP_CUSTOM_CFA \name, 0
.endm
// Declare a function called name, sets up $gp.
.macro ENTRY name
ENTRY_NO_GP \name
// Load $gp. We expect that ".set noreorder" is in effect.
.cpload $t9
// Declare a local convenience label to be branched to when $gp is already set up.
.L\name\()_gp_set:
.endm
.macro END name
.cfi_endproc
.size \name, .-\name
.endm
.macro UNIMPLEMENTED name
ENTRY \name
break
break
END \name
.endm
#if defined(__mips_isa_rev) && __mips_isa_rev > 2
/* mips32r5 & mips32r6 have mthc1 op, and have 64-bit fp regs,
and in FPXX abi we avoid referring to odd-numbered fp regs */
/* LDu: Load 64-bit floating-point value to float reg feven,
from unaligned (mod-4-aligned) mem location disp(base) */
.macro LDu feven,fodd,disp,base,temp
l.s \feven, \disp(\base)
lw \temp, \disp+4(\base)
mthc1 \temp, \feven
.endm
/* SDu: Store 64-bit floating-point value from float reg feven,
to unaligned (mod-4-aligned) mem location disp(base) */
.macro SDu feven,fodd,disp,base,temp
mfhc1 \temp, \feven
s.s \feven, \disp(\base)
sw \temp, \disp+4(\base)
.endm
/* MTD: Move double, from general regpair (reven,rodd)
to float regpair (feven,fodd) */
.macro MTD reven,rodd,feven,fodd
mtc1 \reven, \feven
mthc1 \rodd, \feven
.endm
#else
/* mips32r1 has no mthc1 op;
mips32r1 and mips32r2 use 32-bit floating point register mode (FR=0),
and always hold doubles as (feven, fodd) fp reg pair */
.macro LDu feven,fodd,disp,base,temp
l.s \feven, \disp(\base)
l.s \fodd, \disp+4(\base)
.endm
.macro SDu feven,fodd,disp,base,temp
s.s \feven, \disp(\base)
s.s \fodd, \disp+4(\base)
.endm
.macro MTD reven,rodd,feven,fodd
mtc1 \reven, \feven
mtc1 \rodd, \fodd
.endm
#endif /* mips_isa_rev */
// Macros to poison (negate) the reference for heap poisoning.
.macro POISON_HEAP_REF rRef
#ifdef USE_HEAP_POISONING
subu \rRef, $zero, \rRef
#endif // USE_HEAP_POISONING
.endm
// Macros to unpoison (negate) the reference for heap poisoning.
.macro UNPOISON_HEAP_REF rRef
#ifdef USE_HEAP_POISONING
subu \rRef, $zero, \rRef
#endif // USE_HEAP_POISONING
.endm
// Byte size of the instructions (un)poisoning heap references.
#ifdef USE_HEAP_POISONING
#define HEAP_POISON_INSTR_SIZE 4
#else
#define HEAP_POISON_INSTR_SIZE 0
#endif // USE_HEAP_POISONING
// Based on contents of creg select the minimum integer
// At the end of the macro the original value of creg is lost
.macro MINint dreg,rreg,sreg,creg
.set push
.set noat
#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
.ifc \dreg, \rreg
selnez \dreg, \rreg, \creg
seleqz \creg, \sreg, \creg
.else
seleqz \dreg, \sreg, \creg
selnez \creg, \rreg, \creg
.endif
or \dreg, \dreg, \creg
#else
movn \dreg, \rreg, \creg
movz \dreg, \sreg, \creg
#endif
.set pop
.endm
// Find minimum of two signed registers
.macro MINs dreg,rreg,sreg
.set push
.set noat
slt $at, \rreg, \sreg
MINint \dreg, \rreg, \sreg, $at
.set pop
.endm
// Find minimum of two unsigned registers
.macro MINu dreg,rreg,sreg
.set push
.set noat
sltu $at, \rreg, \sreg
MINint \dreg, \rreg, \sreg, $at
.set pop
.endm
// This utility macro is used to check whether the address contained in
// a register is suitably aligned. Default usage is confirm that the
// address stored in $sp is a multiple of 16. It can be used for other
// alignments, and for other base address registers, if needed.
//
// Enable this macro by running the shell command:
//
// export ART_MIPS32_CHECK_ALIGNMENT=true
//
// NOTE: The value of alignment must be a power of 2, and must fit in an
// unsigned 15-bit integer. The macro won't behave as expected if these
// conditions aren't met.
//
.macro CHECK_ALIGNMENT ba=$sp, tmp=$at, alignment=16
#ifdef ART_MIPS32_CHECK_ALIGNMENT
.set push
.set noat
.set noreorder
andi \tmp, \ba, \alignment-1
beqz \tmp, .+12 # Skip break instruction if base address register (ba) is aligned
nop
break
.set pop
#endif
.endm
#endif // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
|