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// Based on contents of creg select the minimum integer
131// At the end of the macro the original value of creg is lost
132.macro MINint dreg,rreg,sreg,creg
133  .set push
134  .set noat
135#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
136  .ifc \dreg, \rreg
137  selnez \dreg, \rreg, \creg
138  seleqz \creg, \sreg, \creg
139  .else
140  seleqz \dreg, \sreg, \creg
141  selnez \creg, \rreg, \creg
142  .endif
143  or     \dreg, \dreg, \creg
144#else
145  movn   \dreg, \rreg, \creg
146  movz   \dreg, \sreg, \creg
147#endif
148  .set pop
149.endm
150
151// Find minimum of two signed registers
152.macro MINs dreg,rreg,sreg
153  .set push
154  .set noat
155  slt    $at, \rreg, \sreg
156  MINint \dreg, \rreg, \sreg, $at
157  .set pop
158.endm
159
160// Find minimum of two unsigned registers
161.macro MINu dreg,rreg,sreg
162  .set push
163  .set noat
164  sltu   $at, \rreg, \sreg
165  MINint \dreg, \rreg, \sreg, $at
166  .set pop
167.endm
168
169#endif  // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
170