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, sets up $gp.
30.macro ENTRY name
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,0
39    // Load $gp. We expect that ".set noreorder" is in effect.
40    .cpload $t9
41    // Declare a local convenience label to be branched to when $gp is already set up.
42.L\name\()_gp_set:
43.endm
44
45     // Declare a function called name, doesn't set up $gp.
46.macro ENTRY_NO_GP name
47    .type \name, %function
48    .global \name
49    // Cache alignment for function entry.
50    .balign 16
51\name:
52    .cfi_startproc
53     // Ensure we get a sane starting CFA.
54    .cfi_def_cfa $sp,0
55.endm
56
57.macro END name
58    .cfi_endproc
59    .size \name, .-\name
60.endm
61
62.macro UNIMPLEMENTED name
63    ENTRY \name
64    break
65    break
66    END \name
67.endm
68
69#if defined(__mips_isa_rev) && __mips_isa_rev > 2
70  /* mips32r5 & mips32r6 have mthc1 op, and have 64-bit fp regs,
71     and in FPXX abi we avoid referring to odd-numbered fp regs */
72
73/* LDu: Load 64-bit floating-point value to float reg feven,
74   from unaligned (mod-4-aligned) mem location disp(base) */
75.macro LDu feven,fodd,disp,base,temp
76  l.s   \feven, \disp(\base)
77  lw    \temp, \disp+4(\base)
78  mthc1 \temp, \feven
79.endm
80
81/* SDu: Store 64-bit floating-point value from float reg feven,
82   to unaligned (mod-4-aligned) mem location disp(base) */
83.macro SDu feven,fodd,disp,base,temp
84  mfhc1 \temp, \feven
85  s.s   \feven, \disp(\base)
86  sw    \temp, \disp+4(\base)
87.endm
88
89/* MTD: Move double, from general regpair (reven,rodd)
90        to float regpair (feven,fodd) */
91.macro MTD reven,rodd,feven,fodd
92  mtc1  \reven, \feven
93  mthc1 \rodd, \feven
94.endm
95
96#else
97  /* mips32r1 has no mthc1 op;
98     mips32r1 and mips32r2 use 32-bit floating point register mode (FR=0),
99     and always hold doubles as (feven, fodd) fp reg pair */
100
101.macro LDu feven,fodd,disp,base,temp
102  l.s   \feven, \disp(\base)
103  l.s   \fodd,  \disp+4(\base)
104.endm
105
106.macro SDu feven,fodd,disp,base,temp
107  s.s   \feven, \disp(\base)
108  s.s   \fodd,  \disp+4(\base)
109.endm
110
111.macro MTD reven,rodd,feven,fodd
112  mtc1  \reven, \feven
113  mtc1  \rodd, \fodd
114.endm
115
116#endif  /* mips_isa_rev */
117
118// Macros to poison (negate) the reference for heap poisoning.
119.macro POISON_HEAP_REF rRef
120#ifdef USE_HEAP_POISONING
121    subu \rRef, $zero, \rRef
122#endif  // USE_HEAP_POISONING
123.endm
124
125// Macros to unpoison (negate) the reference for heap poisoning.
126.macro UNPOISON_HEAP_REF rRef
127#ifdef USE_HEAP_POISONING
128    subu \rRef, $zero, \rRef
129#endif  // USE_HEAP_POISONING
130.endm
131
132// Based on contents of creg select the minimum integer
133// At the end of the macro the original value of creg is lost
134.macro MINint dreg,rreg,sreg,creg
135  .set push
136  .set noat
137#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
138  .ifc \dreg, \rreg
139  selnez \dreg, \rreg, \creg
140  seleqz \creg, \sreg, \creg
141  .else
142  seleqz \dreg, \sreg, \creg
143  selnez \creg, \rreg, \creg
144  .endif
145  or     \dreg, \dreg, \creg
146#else
147  movn   \dreg, \rreg, \creg
148  movz   \dreg, \sreg, \creg
149#endif
150  .set pop
151.endm
152
153// Find minimum of two signed registers
154.macro MINs dreg,rreg,sreg
155  .set push
156  .set noat
157  slt    $at, \rreg, \sreg
158  MINint \dreg, \rreg, \sreg, $at
159  .set pop
160.endm
161
162// Find minimum of two unsigned registers
163.macro MINu dreg,rreg,sreg
164  .set push
165  .set noat
166  sltu   $at, \rreg, \sreg
167  MINint \dreg, \rreg, \sreg, $at
168  .set pop
169.endm
170
171#endif  // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
172