blob: 0ce7745120c4bc530ec230c611987e491b62124a [file] [log] [blame]
Douglas Leung200f0402016-02-25 20:05:47 -08001/*
2 * Copyright (C) 2016 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/*
18 Art assembly interpreter notes:
19
20 First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
21 handle invoke, allows higher-level code to create frame & shadow frame.
22
23 Once that's working, support direct entry code & eliminate shadow frame (and
24 excess locals allocation.
25
26 Some (hopefully) temporary ugliness. We'll treat rFP as pointing to the
27 base of the vreg array within the shadow frame. Access the other fields,
28 dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue
29 the shadow frame mechanism of double-storing object references - via rFP &
30 number_of_vregs_.
31
32 */
33
34#include "asm_support.h"
35
36#if (__mips==32) && (__mips_isa_rev>=2)
37#define MIPS32REVGE2 /* mips32r2 and greater */
38#if (__mips==32) && (__mips_isa_rev>=5)
39#define FPU64 /* 64 bit FPU */
40#if (__mips==32) && (__mips_isa_rev>=6)
41#define MIPS32REVGE6 /* mips32r6 and greater */
42#endif
43#endif
44#endif
45
46/* MIPS definitions and declarations
47
48 reg nick purpose
49 s0 rPC interpreted program counter, used for fetching instructions
50 s1 rFP interpreted frame pointer, used for accessing locals and args
51 s2 rSELF self (Thread) pointer
52 s3 rIBASE interpreted instruction base pointer, used for computed goto
53 s4 rINST first 16-bit code unit of current instruction
Douglas Leung020b18a2016-06-03 18:05:35 -070054 s5 rOBJ object pointer
Douglas Leung200f0402016-02-25 20:05:47 -080055 s6 rREFS base of object references in shadow frame (ideally, we'll get rid of this later).
Douglas Leung020b18a2016-06-03 18:05:35 -070056 s7 rTEMP used as temp storage that can survive a function call
57 s8 rPROFILE branch profiling countdown
58
Douglas Leung200f0402016-02-25 20:05:47 -080059*/
60
61/* single-purpose registers, given names for clarity */
62#define rPC s0
63#define rFP s1
64#define rSELF s2
65#define rIBASE s3
66#define rINST s4
67#define rOBJ s5
68#define rREFS s6
69#define rTEMP s7
Douglas Leung020b18a2016-06-03 18:05:35 -070070#define rPROFILE s8
Douglas Leung200f0402016-02-25 20:05:47 -080071
72#define rARG0 a0
73#define rARG1 a1
74#define rARG2 a2
75#define rARG3 a3
76#define rRESULT0 v0
77#define rRESULT1 v1
78
79/* GP register definitions */
80#define zero $$0 /* always zero */
81#define AT $$at /* assembler temp */
82#define v0 $$2 /* return value */
83#define v1 $$3
84#define a0 $$4 /* argument registers */
85#define a1 $$5
86#define a2 $$6
87#define a3 $$7
88#define t0 $$8 /* temp registers (not saved across subroutine calls) */
89#define t1 $$9
90#define t2 $$10
91#define t3 $$11
92#define t4 $$12
93#define t5 $$13
94#define t6 $$14
95#define t7 $$15
96#define ta0 $$12 /* alias */
97#define ta1 $$13
98#define ta2 $$14
99#define ta3 $$15
100#define s0 $$16 /* saved across subroutine calls (callee saved) */
101#define s1 $$17
102#define s2 $$18
103#define s3 $$19
104#define s4 $$20
105#define s5 $$21
106#define s6 $$22
107#define s7 $$23
108#define t8 $$24 /* two more temp registers */
109#define t9 $$25
110#define k0 $$26 /* kernel temporary */
111#define k1 $$27
112#define gp $$28 /* global pointer */
113#define sp $$29 /* stack pointer */
114#define s8 $$30 /* one more callee saved */
115#define ra $$31 /* return address */
116
117/* FP register definitions */
118#define fv0 $$f0
119#define fv0f $$f1
120#define fv1 $$f2
121#define fv1f $$f3
122#define fa0 $$f12
123#define fa0f $$f13
124#define fa1 $$f14
125#define fa1f $$f15
126#define ft0 $$f4
127#define ft0f $$f5
128#define ft1 $$f6
129#define ft1f $$f7
130#define ft2 $$f8
131#define ft2f $$f9
132#define ft3 $$f10
133#define ft3f $$f11
134#define ft4 $$f16
135#define ft4f $$f17
136#define ft5 $$f18
137#define ft5f $$f19
138#define fs0 $$f20
139#define fs0f $$f21
140#define fs1 $$f22
141#define fs1f $$f23
142#define fs2 $$f24
143#define fs2f $$f25
144#define fs3 $$f26
145#define fs3f $$f27
146#define fs4 $$f28
147#define fs4f $$f29
148#define fs5 $$f30
149#define fs5f $$f31
150
151#ifndef MIPS32REVGE6
152#define fcc0 $$fcc0
153#define fcc1 $$fcc1
154#endif
155
Alexey Frunze84603bf2016-10-21 19:54:43 -0700156#ifdef MIPS32REVGE2
157#define SEB(rd, rt) \
158 seb rd, rt
159#define SEH(rd, rt) \
160 seh rd, rt
161#define INSERT_HIGH_HALF(rd_lo, rt_hi) \
162 ins rd_lo, rt_hi, 16, 16
163#else
164#define SEB(rd, rt) \
165 sll rd, rt, 24; \
166 sra rd, rd, 24
167#define SEH(rd, rt) \
168 sll rd, rt, 16; \
169 sra rd, rd, 16
170/* Clobbers rt_hi on pre-R2. */
171#define INSERT_HIGH_HALF(rd_lo, rt_hi) \
172 sll rt_hi, rt_hi, 16; \
173 or rd_lo, rt_hi
174#endif
175
176#ifdef FPU64
177#define MOVE_TO_FPU_HIGH(r, flo, fhi) \
178 mthc1 r, flo
179#else
180#define MOVE_TO_FPU_HIGH(r, flo, fhi) \
181 mtc1 r, fhi
182#endif
183
184#ifdef MIPS32REVGE6
185#define JR(rt) \
186 jic rt, 0
187#define LSA(rd, rs, rt, sa) \
188 .if sa; \
189 lsa rd, rs, rt, sa; \
190 .else; \
191 addu rd, rs, rt; \
192 .endif
193#else
194#define JR(rt) \
195 jalr zero, rt
196#define LSA(rd, rs, rt, sa) \
197 .if sa; \
198 .set push; \
199 .set noat; \
200 sll AT, rs, sa; \
201 addu rd, AT, rt; \
202 .set pop; \
203 .else; \
204 addu rd, rs, rt; \
205 .endif
206#endif
207
Douglas Leung200f0402016-02-25 20:05:47 -0800208/*
209 * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
210 * to access other shadow frame fields, we need to use a backwards offset. Define those here.
211 */
212#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
213#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
214#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
215#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
216#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
217#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
218#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
219#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
Douglas Leung020b18a2016-06-03 18:05:35 -0700220#define OFF_FP_SHADOWFRAME OFF_FP(0)
Douglas Leung200f0402016-02-25 20:05:47 -0800221
222#define MTERP_PROFILE_BRANCHES 1
223#define MTERP_LOGGING 0
224
225/*
226 * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
227 * be done *before* something throws.
228 *
229 * It's okay to do this more than once.
230 *
231 * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
232 * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
233 * offset into the code_items_[] array. For effiency, we will "export" the
234 * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
235 * to convert to a dex pc when needed.
236 */
237#define EXPORT_PC() \
238 sw rPC, OFF_FP_DEX_PC_PTR(rFP)
239
240#define EXPORT_DEX_PC(tmp) \
Alexey Frunze84603bf2016-10-21 19:54:43 -0700241 lw tmp, OFF_FP_CODE_ITEM(rFP); \
242 sw rPC, OFF_FP_DEX_PC_PTR(rFP); \
243 addu tmp, CODEITEM_INSNS_OFFSET; \
244 subu tmp, rPC, tmp; \
245 sra tmp, tmp, 1; \
246 sw tmp, OFF_FP_DEX_PC(rFP)
Douglas Leung200f0402016-02-25 20:05:47 -0800247
248/*
249 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
250 */
251#define FETCH_INST() lhu rINST, (rPC)
252
253/*
254 * Fetch the next instruction from the specified offset. Advances rPC
255 * to point to the next instruction. "_count" is in 16-bit code units.
256 *
257 * This must come AFTER anything that can throw an exception, or the
258 * exception catch may miss. (This also implies that it must come after
259 * EXPORT_PC().)
260 */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700261#define FETCH_ADVANCE_INST(_count) \
262 lhu rINST, ((_count)*2)(rPC); \
Douglas Leung200f0402016-02-25 20:05:47 -0800263 addu rPC, rPC, ((_count) * 2)
264
265/*
Douglas Leung200f0402016-02-25 20:05:47 -0800266 * Similar to FETCH_ADVANCE_INST, but does not update rPC. Used to load
267 * rINST ahead of possible exception point. Be sure to manually advance rPC
268 * later.
269 */
270#define PREFETCH_INST(_count) lhu rINST, ((_count)*2)(rPC)
271
272/* Advance rPC by some number of code units. */
273#define ADVANCE(_count) addu rPC, rPC, ((_count) * 2)
274
275/*
276 * Fetch the next instruction from an offset specified by rd. Updates
277 * rPC to point to the next instruction. "rd" must specify the distance
278 * in bytes, *not* 16-bit code units, and may be a signed value.
279 */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700280#define FETCH_ADVANCE_INST_RB(rd) \
281 addu rPC, rPC, rd; \
Douglas Leung200f0402016-02-25 20:05:47 -0800282 lhu rINST, (rPC)
283
284/*
285 * Fetch a half-word code unit from an offset past the current PC. The
286 * "_count" value is in 16-bit code units. Does not advance rPC.
287 *
288 * The "_S" variant works the same but treats the value as signed.
289 */
290#define FETCH(rd, _count) lhu rd, ((_count) * 2)(rPC)
291#define FETCH_S(rd, _count) lh rd, ((_count) * 2)(rPC)
292
293/*
294 * Fetch one byte from an offset past the current PC. Pass in the same
295 * "_count" as you would for FETCH, and an additional 0/1 indicating which
296 * byte of the halfword you want (lo/hi).
297 */
298#define FETCH_B(rd, _count, _byte) lbu rd, ((_count) * 2 + _byte)(rPC)
299
300/*
301 * Put the instruction's opcode field into the specified register.
302 */
303#define GET_INST_OPCODE(rd) and rd, rINST, 0xFF
304
305/*
Alexey Frunze84603bf2016-10-21 19:54:43 -0700306 * Transform opcode into branch target address.
Douglas Leung200f0402016-02-25 20:05:47 -0800307 */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700308#define GET_OPCODE_TARGET(rd) \
309 sll rd, rd, ${handler_size_bits}; \
310 addu rd, rIBASE, rd
Douglas Leung200f0402016-02-25 20:05:47 -0800311
312/*
313 * Begin executing the opcode in rd.
314 */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700315#define GOTO_OPCODE(rd) \
316 GET_OPCODE_TARGET(rd); \
317 JR(rd)
Douglas Leung200f0402016-02-25 20:05:47 -0800318
319/*
320 * Get/set the 32-bit value from a Dalvik register.
321 */
322#define GET_VREG(rd, rix) LOAD_eas2(rd, rFP, rix)
323
Alexey Frunze84603bf2016-10-21 19:54:43 -0700324#define GET_VREG_F(rd, rix) \
325 .set noat; \
326 EAS2(AT, rFP, rix); \
327 l.s rd, (AT); \
328 .set at
Douglas Leung200f0402016-02-25 20:05:47 -0800329
Alexey Frunze84603bf2016-10-21 19:54:43 -0700330#ifdef MIPS32REVGE6
331#define SET_VREG(rd, rix) \
332 lsa t8, rix, rFP, 2; \
333 sw rd, 0(t8); \
334 lsa t8, rix, rREFS, 2; \
335 sw zero, 0(t8)
336#else
337#define SET_VREG(rd, rix) \
338 .set noat; \
Douglas Leung200f0402016-02-25 20:05:47 -0800339 sll AT, rix, 2; \
340 addu t8, rFP, AT; \
341 sw rd, 0(t8); \
342 addu t8, rREFS, AT; \
343 .set at; \
344 sw zero, 0(t8)
Alexey Frunze84603bf2016-10-21 19:54:43 -0700345#endif
Douglas Leung200f0402016-02-25 20:05:47 -0800346
Alexey Frunze84603bf2016-10-21 19:54:43 -0700347#ifdef MIPS32REVGE6
348#define SET_VREG_OBJECT(rd, rix) \
349 lsa t8, rix, rFP, 2; \
350 sw rd, 0(t8); \
351 lsa t8, rix, rREFS, 2; \
352 sw rd, 0(t8)
353#else
354#define SET_VREG_OBJECT(rd, rix) \
355 .set noat; \
356 sll AT, rix, 2; \
357 addu t8, rFP, AT; \
358 sw rd, 0(t8); \
359 addu t8, rREFS, AT; \
360 .set at; \
361 sw rd, 0(t8)
362#endif
363
364#ifdef MIPS32REVGE6
365#define SET_VREG64(rlo, rhi, rix) \
366 lsa t8, rix, rFP, 2; \
367 sw rlo, 0(t8); \
368 sw rhi, 4(t8); \
369 lsa t8, rix, rREFS, 2; \
370 sw zero, 0(t8); \
371 sw zero, 4(t8)
372#else
373#define SET_VREG64(rlo, rhi, rix) \
374 .set noat; \
Douglas Leung200f0402016-02-25 20:05:47 -0800375 sll AT, rix, 2; \
376 addu t8, rFP, AT; \
377 sw rlo, 0(t8); \
378 sw rhi, 4(t8); \
379 addu t8, rREFS, AT; \
380 .set at; \
381 sw zero, 0(t8); \
382 sw zero, 4(t8)
Alexey Frunze84603bf2016-10-21 19:54:43 -0700383#endif
Douglas Leung200f0402016-02-25 20:05:47 -0800384
Alexey Frunze84603bf2016-10-21 19:54:43 -0700385#ifdef MIPS32REVGE6
386#define SET_VREG_F(rd, rix) \
387 lsa t8, rix, rFP, 2; \
388 s.s rd, 0(t8); \
389 lsa t8, rix, rREFS, 2; \
390 sw zero, 0(t8)
391#else
392#define SET_VREG_F(rd, rix) \
393 .set noat; \
394 sll AT, rix, 2; \
395 addu t8, rFP, AT; \
396 s.s rd, 0(t8); \
397 addu t8, rREFS, AT; \
398 .set at; \
399 sw zero, 0(t8)
400#endif
401
402#ifdef MIPS32REVGE6
403#define SET_VREG64_F(rlo, rhi, rix) \
404 lsa t8, rix, rFP, 2; \
405 .set noat; \
406 mfhc1 AT, rlo; \
407 s.s rlo, 0(t8); \
408 sw AT, 4(t8); \
409 .set at; \
410 lsa t8, rix, rREFS, 2; \
411 sw zero, 0(t8); \
412 sw zero, 4(t8)
413#elif defined(FPU64)
414#define SET_VREG64_F(rlo, rhi, rix) \
415 .set noat; \
Douglas Leung200f0402016-02-25 20:05:47 -0800416 sll AT, rix, 2; \
417 addu t8, rREFS, AT; \
418 sw zero, 0(t8); \
419 sw zero, 4(t8); \
420 addu t8, rFP, AT; \
421 mfhc1 AT, rlo; \
422 sw AT, 4(t8); \
423 .set at; \
424 s.s rlo, 0(t8)
425#else
Alexey Frunze84603bf2016-10-21 19:54:43 -0700426#define SET_VREG64_F(rlo, rhi, rix) \
427 .set noat; \
Douglas Leung200f0402016-02-25 20:05:47 -0800428 sll AT, rix, 2; \
429 addu t8, rFP, AT; \
430 s.s rlo, 0(t8); \
431 s.s rhi, 4(t8); \
432 addu t8, rREFS, AT; \
433 .set at; \
434 sw zero, 0(t8); \
435 sw zero, 4(t8)
436#endif
437
Douglas Leung200f0402016-02-25 20:05:47 -0800438/* Combination of the SET_VREG and GOTO_OPCODE functions to save 1 instruction */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700439#ifdef MIPS32REVGE6
440#define SET_VREG_GOTO(rd, rix, dst) \
441 .set noreorder; \
442 GET_OPCODE_TARGET(dst); \
443 lsa t8, rix, rFP, 2; \
444 sw rd, 0(t8); \
445 lsa t8, rix, rREFS, 2; \
446 jalr zero, dst; \
447 sw zero, 0(t8); \
448 .set reorder
449#else
450#define SET_VREG_GOTO(rd, rix, dst) \
451 .set noreorder; \
452 GET_OPCODE_TARGET(dst); \
Douglas Leung200f0402016-02-25 20:05:47 -0800453 .set noat; \
454 sll AT, rix, 2; \
455 addu t8, rFP, AT; \
456 sw rd, 0(t8); \
457 addu t8, rREFS, AT; \
458 .set at; \
459 jalr zero, dst; \
460 sw zero, 0(t8); \
461 .set reorder
Alexey Frunze84603bf2016-10-21 19:54:43 -0700462#endif
463
464/* Combination of the SET_VREG_OBJECT and GOTO_OPCODE functions to save 1 instruction */
465#ifdef MIPS32REVGE6
466#define SET_VREG_OBJECT_GOTO(rd, rix, dst) \
467 .set noreorder; \
468 GET_OPCODE_TARGET(dst); \
469 lsa t8, rix, rFP, 2; \
470 sw rd, 0(t8); \
471 lsa t8, rix, rREFS, 2; \
472 jalr zero, dst; \
473 sw rd, 0(t8); \
474 .set reorder
475#else
476#define SET_VREG_OBJECT_GOTO(rd, rix, dst) \
477 .set noreorder; \
478 GET_OPCODE_TARGET(dst); \
479 .set noat; \
480 sll AT, rix, 2; \
481 addu t8, rFP, AT; \
482 sw rd, 0(t8); \
483 addu t8, rREFS, AT; \
484 .set at; \
485 jalr zero, dst; \
486 sw rd, 0(t8); \
487 .set reorder
488#endif
Douglas Leung200f0402016-02-25 20:05:47 -0800489
490/* Combination of the SET_VREG64 and GOTO_OPCODE functions to save 1 instruction */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700491#ifdef MIPS32REVGE6
492#define SET_VREG64_GOTO(rlo, rhi, rix, dst) \
493 .set noreorder; \
494 GET_OPCODE_TARGET(dst); \
495 lsa t8, rix, rFP, 2; \
496 sw rlo, 0(t8); \
497 sw rhi, 4(t8); \
498 lsa t8, rix, rREFS, 2; \
499 sw zero, 0(t8); \
500 jalr zero, dst; \
501 sw zero, 4(t8); \
502 .set reorder
503#else
504#define SET_VREG64_GOTO(rlo, rhi, rix, dst) \
505 .set noreorder; \
506 GET_OPCODE_TARGET(dst); \
Douglas Leung200f0402016-02-25 20:05:47 -0800507 .set noat; \
508 sll AT, rix, 2; \
509 addu t8, rFP, AT; \
510 sw rlo, 0(t8); \
511 sw rhi, 4(t8); \
512 addu t8, rREFS, AT; \
513 .set at; \
514 sw zero, 0(t8); \
515 jalr zero, dst; \
516 sw zero, 4(t8); \
517 .set reorder
Alexey Frunze84603bf2016-10-21 19:54:43 -0700518#endif
Douglas Leung200f0402016-02-25 20:05:47 -0800519
Alexey Frunze84603bf2016-10-21 19:54:43 -0700520/* Combination of the SET_VREG_F and GOTO_OPCODE functions to save 1 instruction */
521#ifdef MIPS32REVGE6
522#define SET_VREG_F_GOTO(rd, rix, dst) \
523 .set noreorder; \
524 GET_OPCODE_TARGET(dst); \
525 lsa t8, rix, rFP, 2; \
526 s.s rd, 0(t8); \
527 lsa t8, rix, rREFS, 2; \
528 jalr zero, dst; \
529 sw zero, 0(t8); \
530 .set reorder
531#else
532#define SET_VREG_F_GOTO(rd, rix, dst) \
533 .set noreorder; \
534 GET_OPCODE_TARGET(dst); \
535 .set noat; \
Douglas Leung200f0402016-02-25 20:05:47 -0800536 sll AT, rix, 2; \
537 addu t8, rFP, AT; \
538 s.s rd, 0(t8); \
539 addu t8, rREFS, AT; \
540 .set at; \
Alexey Frunze84603bf2016-10-21 19:54:43 -0700541 jalr zero, dst; \
542 sw zero, 0(t8); \
543 .set reorder
544#endif
545
546/* Combination of the SET_VREG64_F and GOTO_OPCODE functions to save 1 instruction */
547#ifdef MIPS32REVGE6
548#define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
549 .set noreorder; \
550 GET_OPCODE_TARGET(dst); \
551 lsa t8, rix, rFP, 2; \
552 .set noat; \
553 mfhc1 AT, rlo; \
554 s.s rlo, 0(t8); \
555 sw AT, 4(t8); \
556 .set at; \
557 lsa t8, rix, rREFS, 2; \
558 sw zero, 0(t8); \
559 jalr zero, dst; \
560 sw zero, 4(t8); \
561 .set reorder
562#elif defined(FPU64)
563#define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
564 .set noreorder; \
565 GET_OPCODE_TARGET(dst); \
566 .set noat; \
567 sll AT, rix, 2; \
568 addu t8, rREFS, AT; \
569 sw zero, 0(t8); \
570 sw zero, 4(t8); \
571 addu t8, rFP, AT; \
572 mfhc1 AT, rlo; \
573 sw AT, 4(t8); \
574 .set at; \
575 jalr zero, dst; \
576 s.s rlo, 0(t8); \
577 .set reorder
578#else
579#define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
580 .set noreorder; \
581 GET_OPCODE_TARGET(dst); \
582 .set noat; \
583 sll AT, rix, 2; \
584 addu t8, rFP, AT; \
585 s.s rlo, 0(t8); \
586 s.s rhi, 4(t8); \
587 addu t8, rREFS, AT; \
588 .set at; \
589 sw zero, 0(t8); \
590 jalr zero, dst; \
591 sw zero, 4(t8); \
592 .set reorder
593#endif
Douglas Leung200f0402016-02-25 20:05:47 -0800594
595#define GET_OPA(rd) srl rd, rINST, 8
596#ifdef MIPS32REVGE2
597#define GET_OPA4(rd) ext rd, rINST, 8, 4
598#else
599#define GET_OPA4(rd) GET_OPA(rd); and rd, 0xf
600#endif
601#define GET_OPB(rd) srl rd, rINST, 12
602
603/*
Alexey Frunze84603bf2016-10-21 19:54:43 -0700604 * Form an Effective Address rd = rbase + roff<<shift;
605 * Uses reg AT on pre-R6.
Douglas Leung200f0402016-02-25 20:05:47 -0800606 */
Alexey Frunze84603bf2016-10-21 19:54:43 -0700607#define EASN(rd, rbase, roff, shift) LSA(rd, roff, rbase, shift)
Douglas Leung200f0402016-02-25 20:05:47 -0800608
609#define EAS1(rd, rbase, roff) EASN(rd, rbase, roff, 1)
610#define EAS2(rd, rbase, roff) EASN(rd, rbase, roff, 2)
611#define EAS3(rd, rbase, roff) EASN(rd, rbase, roff, 3)
612#define EAS4(rd, rbase, roff) EASN(rd, rbase, roff, 4)
613
Alexey Frunze84603bf2016-10-21 19:54:43 -0700614#define LOAD_eas2(rd, rbase, roff) \
615 .set noat; \
616 EAS2(AT, rbase, roff); \
617 lw rd, 0(AT); \
Douglas Leung200f0402016-02-25 20:05:47 -0800618 .set at
619
Alexey Frunze84603bf2016-10-21 19:54:43 -0700620#define STORE_eas2(rd, rbase, roff) \
621 .set noat; \
622 EAS2(AT, rbase, roff); \
623 sw rd, 0(AT); \
624 .set at
Douglas Leung200f0402016-02-25 20:05:47 -0800625
626#define LOAD_RB_OFF(rd, rbase, off) lw rd, off(rbase)
627#define STORE_RB_OFF(rd, rbase, off) sw rd, off(rbase)
628
Alexey Frunze84603bf2016-10-21 19:54:43 -0700629#define STORE64_off(rlo, rhi, rbase, off) \
630 sw rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800631 sw rhi, (off+4)(rbase)
Alexey Frunze84603bf2016-10-21 19:54:43 -0700632#define LOAD64_off(rlo, rhi, rbase, off) \
633 lw rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800634 lw rhi, (off+4)(rbase)
635
636#define STORE64(rlo, rhi, rbase) STORE64_off(rlo, rhi, rbase, 0)
637#define LOAD64(rlo, rhi, rbase) LOAD64_off(rlo, rhi, rbase, 0)
638
639#ifdef FPU64
Alexey Frunze84603bf2016-10-21 19:54:43 -0700640#define STORE64_off_F(rlo, rhi, rbase, off) \
641 s.s rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800642 .set noat; \
643 mfhc1 AT, rlo; \
644 sw AT, (off+4)(rbase); \
645 .set at
Alexey Frunze84603bf2016-10-21 19:54:43 -0700646#define LOAD64_off_F(rlo, rhi, rbase, off) \
647 l.s rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800648 .set noat; \
649 lw AT, (off+4)(rbase); \
650 mthc1 AT, rlo; \
651 .set at
652#else
Alexey Frunze84603bf2016-10-21 19:54:43 -0700653#define STORE64_off_F(rlo, rhi, rbase, off) \
654 s.s rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800655 s.s rhi, (off+4)(rbase)
Alexey Frunze84603bf2016-10-21 19:54:43 -0700656#define LOAD64_off_F(rlo, rhi, rbase, off) \
657 l.s rlo, off(rbase); \
Douglas Leung200f0402016-02-25 20:05:47 -0800658 l.s rhi, (off+4)(rbase)
659#endif
660
661#define STORE64_F(rlo, rhi, rbase) STORE64_off_F(rlo, rhi, rbase, 0)
662#define LOAD64_F(rlo, rhi, rbase) LOAD64_off_F(rlo, rhi, rbase, 0)
663
664
665#define LOAD_base_offMirrorArray_length(rd, rbase) LOAD_RB_OFF(rd, rbase, MIRROR_ARRAY_LENGTH_OFFSET)
666
667#define STACK_STORE(rd, off) sw rd, off(sp)
668#define STACK_LOAD(rd, off) lw rd, off(sp)
669#define CREATE_STACK(n) subu sp, sp, n
670#define DELETE_STACK(n) addu sp, sp, n
671
672#define LOAD_ADDR(dest, addr) la dest, addr
673#define LOAD_IMM(dest, imm) li dest, imm
674#define MOVE_REG(dest, src) move dest, src
675#define STACK_SIZE 128
676
677#define STACK_OFFSET_ARG04 16
678#define STACK_OFFSET_ARG05 20
679#define STACK_OFFSET_ARG06 24
680#define STACK_OFFSET_ARG07 28
681#define STACK_OFFSET_GP 84
682
683#define JAL(n) jal n
684#define BAL(n) bal n
685
686/*
687 * FP register usage restrictions:
688 * 1) We don't use the callee save FP registers so we don't have to save them.
689 * 2) We don't use the odd FP registers so we can share code with mips32r6.
690 */
691#define STACK_STORE_FULL() CREATE_STACK(STACK_SIZE); \
692 STACK_STORE(ra, 124); \
693 STACK_STORE(s8, 120); \
694 STACK_STORE(s0, 116); \
695 STACK_STORE(s1, 112); \
696 STACK_STORE(s2, 108); \
697 STACK_STORE(s3, 104); \
698 STACK_STORE(s4, 100); \
699 STACK_STORE(s5, 96); \
700 STACK_STORE(s6, 92); \
701 STACK_STORE(s7, 88);
702
703#define STACK_LOAD_FULL() STACK_LOAD(gp, STACK_OFFSET_GP); \
704 STACK_LOAD(s7, 88); \
705 STACK_LOAD(s6, 92); \
706 STACK_LOAD(s5, 96); \
707 STACK_LOAD(s4, 100); \
708 STACK_LOAD(s3, 104); \
709 STACK_LOAD(s2, 108); \
710 STACK_LOAD(s1, 112); \
711 STACK_LOAD(s0, 116); \
712 STACK_LOAD(s8, 120); \
713 STACK_LOAD(ra, 124); \
714 DELETE_STACK(STACK_SIZE)
Douglas Leung020b18a2016-06-03 18:05:35 -0700715
716#define REFRESH_IBASE() \
717 lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
Alexey Frunze84603bf2016-10-21 19:54:43 -0700718
719/* Constants for float/double_to_int/long conversions */
720#define INT_MIN 0x80000000
721#define INT_MIN_AS_FLOAT 0xCF000000
722#define INT_MIN_AS_DOUBLE_HIGH 0xC1E00000
723#define LONG_MIN_HIGH 0x80000000
724#define LONG_MIN_AS_FLOAT 0xDF000000
725#define LONG_MIN_AS_DOUBLE_HIGH 0xC3E00000