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