2 /*---------------------------------------------------------------*/
3 /*--- begin guest_mips_helpers.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2010-2017 RT-RK
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, see <http://www.gnu.org/licenses/>.
25 The GNU General Public License is contained in the file COPYING.
28 #include "libvex_basictypes.h"
29 #include "libvex_emnote.h"
30 #include "libvex_guest_mips32.h"
31 #include "libvex_guest_mips64.h"
32 #include "libvex_ir.h"
35 #include "main_util.h"
36 #include "main_globals.h"
37 #include "guest_generic_bb_to_IR.h"
38 #include "guest_mips_defs.h"
40 #if defined (__GNUC__)
41 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
46 /* This file contains helper functions for mips guest code. Calls to
47 these functions are generated by the back end.
50 #define ALWAYSDEFD32(field) \
51 { offsetof(VexGuestMIPS32State, field), \
52 (sizeof ((VexGuestMIPS32State*)0)->field) }
54 #define ALWAYSDEFD64(field) \
55 { offsetof(VexGuestMIPS64State, field), \
56 (sizeof ((VexGuestMIPS64State*)0)->field) }
58 IRExpr
*guest_mips32_spechelper(const HChar
* function_name
, IRExpr
** args
,
59 IRStmt
** precedingStmts
, Int n_precedingStmts
)
64 IRExpr
*guest_mips64_spechelper ( const HChar
* function_name
, IRExpr
** args
,
65 IRStmt
** precedingStmts
,
66 Int n_precedingStmts
)
71 /* VISIBLE TO LIBVEX CLIENT */
72 void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State
* vex_state
)
74 vex_state
->guest_r0
= 0; /* Hardwired to 0 */
75 vex_state
->guest_r1
= 0; /* Assembler temporary */
76 vex_state
->guest_r2
= 0; /* Values for function returns ... */
77 vex_state
->guest_r3
= 0; /* ...and expression evaluation */
78 vex_state
->guest_r4
= 0; /* Function arguments */
79 vex_state
->guest_r5
= 0;
80 vex_state
->guest_r6
= 0;
81 vex_state
->guest_r7
= 0;
82 vex_state
->guest_r8
= 0; /* Temporaries */
83 vex_state
->guest_r9
= 0;
84 vex_state
->guest_r10
= 0;
85 vex_state
->guest_r11
= 0;
86 vex_state
->guest_r12
= 0;
87 vex_state
->guest_r13
= 0;
88 vex_state
->guest_r14
= 0;
89 vex_state
->guest_r15
= 0;
90 vex_state
->guest_r16
= 0; /* Saved temporaries */
91 vex_state
->guest_r17
= 0;
92 vex_state
->guest_r18
= 0;
93 vex_state
->guest_r19
= 0;
94 vex_state
->guest_r20
= 0;
95 vex_state
->guest_r21
= 0;
96 vex_state
->guest_r22
= 0;
97 vex_state
->guest_r23
= 0;
98 vex_state
->guest_r24
= 0; /* Temporaries */
99 vex_state
->guest_r25
= 0;
100 vex_state
->guest_r26
= 0; /* Reserved for OS kernel */
101 vex_state
->guest_r27
= 0;
102 vex_state
->guest_r28
= 0; /* Global pointer */
103 vex_state
->guest_r29
= 0; /* Stack pointer */
104 vex_state
->guest_r30
= 0; /* Frame pointer */
105 vex_state
->guest_r31
= 0; /* Return address */
106 vex_state
->guest_PC
= 0; /* Program counter */
107 vex_state
->guest_HI
= 0; /* Multiply and divide register higher result */
108 vex_state
->guest_LO
= 0; /* Multiply and divide register lower result */
111 vex_state
->guest_f0
= 0x7ff800007ff80000ULL
; /* Floting point GP registers */
112 vex_state
->guest_f1
= 0x7ff800007ff80000ULL
;
113 vex_state
->guest_f2
= 0x7ff800007ff80000ULL
;
114 vex_state
->guest_f3
= 0x7ff800007ff80000ULL
;
115 vex_state
->guest_f4
= 0x7ff800007ff80000ULL
;
116 vex_state
->guest_f5
= 0x7ff800007ff80000ULL
;
117 vex_state
->guest_f6
= 0x7ff800007ff80000ULL
;
118 vex_state
->guest_f7
= 0x7ff800007ff80000ULL
;
119 vex_state
->guest_f8
= 0x7ff800007ff80000ULL
;
120 vex_state
->guest_f9
= 0x7ff800007ff80000ULL
;
121 vex_state
->guest_f10
= 0x7ff800007ff80000ULL
;
122 vex_state
->guest_f11
= 0x7ff800007ff80000ULL
;
123 vex_state
->guest_f12
= 0x7ff800007ff80000ULL
;
124 vex_state
->guest_f13
= 0x7ff800007ff80000ULL
;
125 vex_state
->guest_f14
= 0x7ff800007ff80000ULL
;
126 vex_state
->guest_f15
= 0x7ff800007ff80000ULL
;
127 vex_state
->guest_f16
= 0x7ff800007ff80000ULL
;
128 vex_state
->guest_f17
= 0x7ff800007ff80000ULL
;
129 vex_state
->guest_f18
= 0x7ff800007ff80000ULL
;
130 vex_state
->guest_f19
= 0x7ff800007ff80000ULL
;
131 vex_state
->guest_f20
= 0x7ff800007ff80000ULL
;
132 vex_state
->guest_f21
= 0x7ff800007ff80000ULL
;
133 vex_state
->guest_f22
= 0x7ff800007ff80000ULL
;
134 vex_state
->guest_f23
= 0x7ff800007ff80000ULL
;
135 vex_state
->guest_f24
= 0x7ff800007ff80000ULL
;
136 vex_state
->guest_f25
= 0x7ff800007ff80000ULL
;
137 vex_state
->guest_f26
= 0x7ff800007ff80000ULL
;
138 vex_state
->guest_f27
= 0x7ff800007ff80000ULL
;
139 vex_state
->guest_f28
= 0x7ff800007ff80000ULL
;
140 vex_state
->guest_f29
= 0x7ff800007ff80000ULL
;
141 vex_state
->guest_f30
= 0x7ff800007ff80000ULL
;
142 vex_state
->guest_f31
= 0x7ff800007ff80000ULL
;
144 vex_state
->guest_FIR
= 0; /* FP implementation and revision register */
145 vex_state
->guest_FCCR
= 0; /* FP condition codes register */
146 vex_state
->guest_FEXR
= 0; /* FP exceptions register */
147 vex_state
->guest_FENR
= 0; /* FP enables register */
148 vex_state
->guest_FCSR
= 0; /* FP control/status register */
149 vex_state
->guest_ULR
= 0; /* TLS */
151 /* Various pseudo-regs mandated by Vex or Valgrind. */
152 /* Emulation notes */
153 vex_state
->guest_EMNOTE
= 0;
155 /* For clflush: record start and length of area to invalidate */
156 vex_state
->guest_CMSTART
= 0;
157 vex_state
->guest_CMLEN
= 0;
158 vex_state
->host_EvC_COUNTER
= 0;
159 vex_state
->host_EvC_FAILADDR
= 0;
161 /* Used to record the unredirected guest address at the start of
162 a translation whose start has been redirected. By reading
163 this pseudo-register shortly afterwards, the translation can
164 find out what the corresponding no-redirection address was.
165 Note, this is only set for wrap-style redirects, not for
166 replace-style ones. */
167 vex_state
->guest_NRADDR
= 0;
169 vex_state
->guest_COND
= 0;
171 vex_state
->guest_CP0_status
= 0;
172 vex_state
->guest_CP0_Config5
= 0;
174 vex_state
->guest_LLaddr
= 0xFFFFFFFF;
175 vex_state
->guest_LLdata
= 0;
177 /* MIPS32 DSP ASE(r2) specific registers */
178 vex_state
->guest_DSPControl
= 0; /* DSPControl register */
179 vex_state
->guest_ac0
= 0; /* Accumulator 0 */
180 vex_state
->guest_ac1
= 0; /* Accumulator 1 */
181 vex_state
->guest_ac2
= 0; /* Accumulator 2 */
182 vex_state
->guest_ac3
= 0; /* Accumulator 3 */
184 vex_state
->guest_w0
.w64
[0] = 0;
185 vex_state
->guest_w0
.w64
[1] = 0;
186 vex_state
->guest_w1
.w64
[0] = 0;
187 vex_state
->guest_w1
.w64
[1] = 0;
188 vex_state
->guest_w2
.w64
[0] = 0;
189 vex_state
->guest_w2
.w64
[1] = 0;
192 void LibVEX_GuestMIPS64_initialise ( /*OUT*/ VexGuestMIPS64State
* vex_state
)
194 vex_state
->guest_r0
= 0; /* Hardwired to 0 */
195 vex_state
->guest_r1
= 0; /* Assembler temporary */
196 vex_state
->guest_r2
= 0; /* Values for function returns ... */
197 vex_state
->guest_r3
= 0;
198 vex_state
->guest_r4
= 0; /* Function arguments */
199 vex_state
->guest_r5
= 0;
200 vex_state
->guest_r6
= 0;
201 vex_state
->guest_r7
= 0;
202 vex_state
->guest_r8
= 0;
203 vex_state
->guest_r9
= 0;
204 vex_state
->guest_r10
= 0;
205 vex_state
->guest_r11
= 0;
206 vex_state
->guest_r12
= 0; /* Temporaries */
207 vex_state
->guest_r13
= 0;
208 vex_state
->guest_r14
= 0;
209 vex_state
->guest_r15
= 0;
210 vex_state
->guest_r16
= 0; /* Saved temporaries */
211 vex_state
->guest_r17
= 0;
212 vex_state
->guest_r18
= 0;
213 vex_state
->guest_r19
= 0;
214 vex_state
->guest_r20
= 0;
215 vex_state
->guest_r21
= 0;
216 vex_state
->guest_r22
= 0;
217 vex_state
->guest_r23
= 0;
218 vex_state
->guest_r24
= 0; /* Temporaries */
219 vex_state
->guest_r25
= 0;
220 vex_state
->guest_r26
= 0; /* Reserved for OS kernel */
221 vex_state
->guest_r27
= 0;
222 vex_state
->guest_r28
= 0; /* Global pointer */
223 vex_state
->guest_r29
= 0; /* Stack pointer */
224 vex_state
->guest_r30
= 0; /* Frame pointer */
225 vex_state
->guest_r31
= 0; /* Return address */
226 vex_state
->guest_PC
= 0; /* Program counter */
227 vex_state
->guest_HI
= 0; /* Multiply and divide register higher result */
228 vex_state
->guest_LO
= 0; /* Multiply and divide register lower result */
231 vex_state
->guest_f0
= 0x7ff800007ff80000ULL
; /* Floting point registers */
232 vex_state
->guest_f1
= 0x7ff800007ff80000ULL
;
233 vex_state
->guest_f2
= 0x7ff800007ff80000ULL
;
234 vex_state
->guest_f3
= 0x7ff800007ff80000ULL
;
235 vex_state
->guest_f4
= 0x7ff800007ff80000ULL
;
236 vex_state
->guest_f5
= 0x7ff800007ff80000ULL
;
237 vex_state
->guest_f6
= 0x7ff800007ff80000ULL
;
238 vex_state
->guest_f7
= 0x7ff800007ff80000ULL
;
239 vex_state
->guest_f8
= 0x7ff800007ff80000ULL
;
240 vex_state
->guest_f9
= 0x7ff800007ff80000ULL
;
241 vex_state
->guest_f10
= 0x7ff800007ff80000ULL
;
242 vex_state
->guest_f11
= 0x7ff800007ff80000ULL
;
243 vex_state
->guest_f12
= 0x7ff800007ff80000ULL
;
244 vex_state
->guest_f13
= 0x7ff800007ff80000ULL
;
245 vex_state
->guest_f14
= 0x7ff800007ff80000ULL
;
246 vex_state
->guest_f15
= 0x7ff800007ff80000ULL
;
247 vex_state
->guest_f16
= 0x7ff800007ff80000ULL
;
248 vex_state
->guest_f17
= 0x7ff800007ff80000ULL
;
249 vex_state
->guest_f18
= 0x7ff800007ff80000ULL
;
250 vex_state
->guest_f19
= 0x7ff800007ff80000ULL
;
251 vex_state
->guest_f20
= 0x7ff800007ff80000ULL
;
252 vex_state
->guest_f21
= 0x7ff800007ff80000ULL
;
253 vex_state
->guest_f22
= 0x7ff800007ff80000ULL
;
254 vex_state
->guest_f23
= 0x7ff800007ff80000ULL
;
255 vex_state
->guest_f24
= 0x7ff800007ff80000ULL
;
256 vex_state
->guest_f25
= 0x7ff800007ff80000ULL
;
257 vex_state
->guest_f26
= 0x7ff800007ff80000ULL
;
258 vex_state
->guest_f27
= 0x7ff800007ff80000ULL
;
259 vex_state
->guest_f28
= 0x7ff800007ff80000ULL
;
260 vex_state
->guest_f29
= 0x7ff800007ff80000ULL
;
261 vex_state
->guest_f30
= 0x7ff800007ff80000ULL
;
262 vex_state
->guest_f31
= 0x7ff800007ff80000ULL
;
264 vex_state
->guest_FIR
= 0; /* FP implementation and revision register */
265 vex_state
->guest_FCCR
= 0; /* FP condition codes register */
266 vex_state
->guest_FEXR
= 0; /* FP exceptions register */
267 vex_state
->guest_FENR
= 0; /* FP enables register */
268 vex_state
->guest_FCSR
= 0; /* FP control/status register */
270 vex_state
->guest_ULR
= 0;
272 /* Various pseudo-regs mandated by Vex or Valgrind. */
273 /* Emulation notes */
274 vex_state
->guest_EMNOTE
= 0;
276 /* For clflush: record start and length of area to invalidate */
277 vex_state
->guest_CMSTART
= 0;
278 vex_state
->guest_CMLEN
= 0;
279 vex_state
->host_EvC_COUNTER
= 0;
280 vex_state
->host_EvC_FAILADDR
= 0;
282 /* Used to record the unredirected guest address at the start of
283 a translation whose start has been redirected. By reading
284 this pseudo-register shortly afterwards, the translation can
285 find out what the corresponding no-redirection address was.
286 Note, this is only set for wrap-style redirects, not for
287 replace-style ones. */
288 vex_state
->guest_NRADDR
= 0;
290 vex_state
->guest_COND
= 0;
292 vex_state
->guest_CP0_status
= MIPS_CP0_STATUS_FR
;
294 vex_state
->guest_LLaddr
= 0xFFFFFFFFFFFFFFFFULL
;
295 vex_state
->guest_LLdata
= 0;
297 vex_state
->guest_MSACSR
= 0;
300 /*-----------------------------------------------------------*/
301 /*--- Describing the mips guest state, for the benefit ---*/
302 /*--- of iropt and instrumenters. ---*/
303 /*-----------------------------------------------------------*/
305 /* Figure out if any part of the guest state contained in minoff
306 .. maxoff requires precise memory exceptions. If in doubt return
307 True (but this generates significantly slower code).
309 We enforce precise exns for guest SP, PC.
311 Only SP is needed in mode VexRegUpdSpAtMemAccess.
313 Bool
guest_mips32_state_requires_precise_mem_exns (
314 Int minoff
, Int maxoff
, VexRegisterUpdates pxControl
317 Int sp_min
= offsetof(VexGuestMIPS32State
, guest_r29
);
318 Int sp_max
= sp_min
+ 4 - 1;
319 Int pc_min
= offsetof(VexGuestMIPS32State
, guest_PC
);
320 Int pc_max
= pc_min
+ 4 - 1;
322 if (maxoff
< sp_min
|| minoff
> sp_max
) {
323 /* no overlap with sp */
324 if (pxControl
== VexRegUpdSpAtMemAccess
)
325 return False
; /* We only need to check stack pointer. */
330 if (maxoff
< pc_min
|| minoff
> pc_max
) {
331 /* no overlap with pc */
336 /* We appear to need precise updates of R11 in order to get proper
337 stacktraces from non-optimised code. */
338 Int fp_min
= offsetof(VexGuestMIPS32State
, guest_r30
);
339 Int fp_max
= fp_min
+ 4 - 1;
341 if (maxoff
< fp_min
|| minoff
> fp_max
) {
342 /* no overlap with fp */
350 Bool
guest_mips64_state_requires_precise_mem_exns (
351 Int minoff
, Int maxoff
, VexRegisterUpdates pxControl
354 Int sp_min
= offsetof(VexGuestMIPS64State
, guest_r29
);
355 Int sp_max
= sp_min
+ 8 - 1;
356 Int pc_min
= offsetof(VexGuestMIPS64State
, guest_PC
);
357 Int pc_max
= pc_min
+ 8 - 1;
359 if ( maxoff
< sp_min
|| minoff
> sp_max
) {
360 /* no overlap with sp */
361 if (pxControl
== VexRegUpdSpAtMemAccess
)
362 return False
; /* We only need to check stack pointer. */
367 if ( maxoff
< pc_min
|| minoff
> pc_max
) {
368 /* no overlap with pc */
373 Int fp_min
= offsetof(VexGuestMIPS64State
, guest_r30
);
374 Int fp_max
= fp_min
+ 8 - 1;
376 if ( maxoff
< fp_min
|| minoff
> fp_max
) {
377 /* no overlap with fp */
385 VexGuestLayout mips32Guest_layout
= {
386 /* Total size of the guest state, in bytes. */
387 .total_sizeB
= sizeof(VexGuestMIPS32State
),
388 /* Describe the stack pointer. */
389 .offset_SP
= offsetof(VexGuestMIPS32State
, guest_r29
),
391 /* Describe the frame pointer. */
392 .offset_FP
= offsetof(VexGuestMIPS32State
, guest_r30
),
394 /* Describe the instruction pointer. */
395 .offset_IP
= offsetof(VexGuestMIPS32State
, guest_PC
),
397 /* Describe any sections to be regarded by Memcheck as
402 /* 0 */ ALWAYSDEFD32(guest_r0
),
403 /* 1 */ ALWAYSDEFD32(guest_r1
),
404 /* 2 */ ALWAYSDEFD32(guest_EMNOTE
),
405 /* 3 */ ALWAYSDEFD32(guest_CMSTART
),
406 /* 4 */ ALWAYSDEFD32(guest_CMLEN
),
407 /* 5 */ ALWAYSDEFD32(guest_r29
),
408 /* 6 */ ALWAYSDEFD32(guest_r31
),
409 /* 7 */ ALWAYSDEFD32(guest_ULR
)
413 VexGuestLayout mips64Guest_layout
= {
414 /* Total size of the guest state, in bytes. */
415 .total_sizeB
= sizeof(VexGuestMIPS64State
),
416 /* Describe the stack pointer. */
417 .offset_SP
= offsetof(VexGuestMIPS64State
, guest_r29
),
419 /* Describe the frame pointer. */
420 .offset_FP
= offsetof(VexGuestMIPS64State
, guest_r30
),
422 /* Describe the instruction pointer. */
423 .offset_IP
= offsetof(VexGuestMIPS64State
, guest_PC
),
425 /* Describe any sections to be regarded by Memcheck as
430 /* 0 */ ALWAYSDEFD64 (guest_r0
),
431 /* 1 */ ALWAYSDEFD64 (guest_EMNOTE
),
432 /* 2 */ ALWAYSDEFD64 (guest_CMSTART
),
433 /* 3 */ ALWAYSDEFD64 (guest_CMLEN
),
434 /* 4 */ ALWAYSDEFD64 (guest_r29
),
435 /* 5 */ ALWAYSDEFD64 (guest_r31
),
436 /* 6 */ ALWAYSDEFD64 (guest_ULR
)
440 #define ASM_VOLATILE_RDHWR(opcode) \
441 __asm__ __volatile__(".word 0x7C02003B | "#opcode" << 11 \n\t" \
445 HWord
mips_dirtyhelper_rdhwr ( UInt rd
)
447 #if defined(__mips__)
448 register HWord x
__asm__("v0") = 0;
451 case 0: /* x = CPUNum() */
452 ASM_VOLATILE_RDHWR(0); /* rdhwr v0, $0 */
455 case 1: /* x = SYNCI_Step() */
456 ASM_VOLATILE_RDHWR(1); /* rdhwr v0, $1 */
459 case 2: /* x = CC() */
460 ASM_VOLATILE_RDHWR(2); /* rdhwr v0, $2 */
463 case 3: /* x = CCRes() */
464 ASM_VOLATILE_RDHWR(3); /* rdhwr v0, $3 */
467 case 31: /* x = CVMX_get_cycles() */
468 ASM_VOLATILE_RDHWR(31); /* rdhwr v0, $31 */
481 #define ASM_VOLATILE_UNARY32(inst) \
482 __asm__ volatile(".set push" "\n\t" \
483 ".set hardfloat" "\n\t" \
484 "cfc1 $8, $31" "\n\t" \
485 "ctc1 %2, $31" "\n\t" \
486 "mtc1 %1, $f20" "\n\t" \
487 #inst" $f20, $f20" "\n\t" \
488 "cfc1 %0, $31" "\n\t" \
489 "ctc1 $8, $31" "\n\t" \
492 : "r" (loFsVal), "r" (fcsr) \
496 #define ASM_VOLATILE_UNARY32_DOUBLE(inst) \
497 __asm__ volatile(".set push" "\n\t" \
498 ".set hardfloat" "\n\t" \
499 "cfc1 $8, $31" "\n\t" \
500 "ctc1 %2, $31" "\n\t" \
501 "ldc1 $f20, 0(%1)" "\n\t" \
502 #inst" $f20, $f20" "\n\t" \
503 "cfc1 %0, $31" "\n\t" \
504 "ctc1 $8, $31" "\n\t" \
507 : "r" (&fsVal), "r" (fcsr) \
508 : "$8", "$f20", "$f21" \
511 #define ASM_VOLATILE_UNARY64(inst) \
512 __asm__ volatile(".set push" "\n\t" \
513 ".set hardfloat" "\n\t" \
514 ".set fp=64" "\n\t" \
515 "cfc1 $8, $31" "\n\t" \
516 "ctc1 %2, $31" "\n\t" \
517 "ldc1 $f24, 0(%1)" "\n\t" \
518 #inst" $f24, $f24" "\n\t" \
519 "cfc1 %0, $31" "\n\t" \
520 "ctc1 $8, $31" "\n\t" \
523 : "r" (&(addr[fs])), "r" (fcsr) \
527 #define ASM_VOLATILE_MSA_UNARY(inst) \
528 __asm__ volatile(".set push" "\n\t" \
529 ".set mips32r2" "\n\t" \
530 ".set hardfloat" "\n\t" \
531 ".set fp=64" "\n\t" \
533 ".set noreorder" "\n\t" \
534 "cfcmsa $t0, $1" "\n\t" \
535 "ctcmsa $1, %2" "\n\t" \
536 "ld.b $w24, 0(%1)" "\n\t" \
537 #inst" $w24, $w24" "\n\t" \
538 "cfcmsa %0, $1" "\n\t" \
539 "ctcmsa $1, $t0" "\n\t" \
542 : "r" (&(addr[ws])), "r" (msacsr) \
546 #define ASM_VOLATILE_BINARY32(inst) \
547 __asm__ volatile(".set push" "\n\t" \
548 ".set hardfloat" "\n\t" \
549 "cfc1 $8, $31" "\n\t" \
550 "ctc1 %3, $31" "\n\t" \
551 "mtc1 %1, $f20" "\n\t" \
552 "mtc1 %2, $f22" "\n\t" \
553 #inst" $f20, $f20, $f22" "\n\t" \
554 "cfc1 %0, $31" "\n\t" \
555 "ctc1 $8, $31" "\n\t" \
558 : "r" (loFsVal), "r" (loFtVal), "r" (fcsr) \
559 : "$8", "$f20", "$f22" \
562 #define ASM_VOLATILE_BINARY32_DOUBLE(inst) \
563 __asm__ volatile(".set push" "\n\t" \
564 ".set hardfloat" "\n\t" \
565 "cfc1 $8, $31" "\n\t" \
566 "ctc1 %3, $31" "\n\t" \
567 "ldc1 $f20, 0(%1)" "\n\t" \
568 "ldc1 $f22, 0(%2)" "\n\t" \
569 #inst" $f20, $f20, $f22" "\n\t" \
570 "cfc1 %0, $31" "\n\t" \
571 "ctc1 $8, $31" "\n\t" \
574 : "r" (&fsVal), "r" (&ftVal), "r" (fcsr) \
575 : "$8", "$f20", "$f21", "$f22", "$f23" \
578 #define ASM_VOLATILE_BINARY64(inst) \
579 __asm__ volatile(".set push" "\n\t" \
580 ".set hardfloat" "\n\t" \
581 "cfc1 $8, $31" "\n\t" \
582 "ctc1 %3, $31" "\n\t" \
583 "ldc1 $f24, 0(%1)" "\n\t" \
584 "ldc1 $f26, 0(%2)" "\n\t" \
585 #inst" $f24, $f24, $f26" "\n\t" \
586 "cfc1 %0, $31" "\n\t" \
587 "ctc1 $8, $31" "\n\t" \
590 : "r" (&(addr[fs])), "r" (&(addr[ft])), "r" (fcsr) \
591 : "$8", "$f24", "$f26" \
594 #define ASM_VOLATILE_MSA_BINARY(inst) \
595 __asm__ volatile(".set push" "\n\t" \
596 ".set mips32r2" "\n\t" \
597 ".set hardfloat" "\n\t" \
598 ".set fp=64" "\n\t" \
600 "cfcmsa $t0, $1" "\n\t" \
601 "ctcmsa $1, %3" "\n\t" \
602 "ld.b $w24, 0(%1)" "\n\t" \
603 "ld.b $w26, 0(%2)" "\n\t" \
604 #inst" $w24, $w24, $w26" "\n\t" \
605 "cfcmsa %0, $1" "\n\t" \
606 "ctcmsa $1, $t0" "\n\t" \
609 : "r" (&(addr[ws])), "r" (&(addr[wt])), "r" (msacsr)\
613 /* TODO: Add cases for all fpu instructions because all fpu instructions are
614 change the value of FCSR register. */
615 extern UInt
mips_dirtyhelper_calculate_FCSR_fp32 ( void* gs
, UInt fs
, UInt ft
,
619 #if defined(__mips__)
620 VexGuestMIPS32State
* guest_state
= (VexGuestMIPS32State
*)gs
;
621 UInt loFsVal
, hiFsVal
, loFtVal
, hiFtVal
;
622 #if defined (_MIPSEL)
623 ULong
*addr
= (ULong
*)&guest_state
->guest_f0
;
624 loFsVal
= (UInt
)addr
[fs
];
625 hiFsVal
= (UInt
)addr
[fs
+1];
626 loFtVal
= (UInt
)addr
[ft
];
627 hiFtVal
= (UInt
)addr
[ft
+1];
628 #elif defined (_MIPSEB)
629 UInt
*addr
= (UInt
*)&guest_state
->guest_f0
;
630 loFsVal
= (UInt
)addr
[fs
*2];
631 hiFsVal
= (UInt
)addr
[fs
*2+2];
632 loFtVal
= (UInt
)addr
[ft
*2];
633 hiFtVal
= (UInt
)addr
[ft
*2+2];
635 ULong fsVal
= ((ULong
) hiFsVal
) << 32 | loFsVal
;
636 ULong ftVal
= ((ULong
) hiFtVal
) << 32 | loFtVal
;
637 UInt fcsr
= guest_state
->guest_FCSR
;
640 ASM_VOLATILE_UNARY32_DOUBLE(round
.w
.d
)
643 ASM_VOLATILE_UNARY32(floor
.w
.s
)
646 ASM_VOLATILE_UNARY32_DOUBLE(floor
.w
.d
)
649 ASM_VOLATILE_UNARY32(trunc
.w
.s
)
652 ASM_VOLATILE_UNARY32_DOUBLE(trunc
.w
.d
)
655 ASM_VOLATILE_UNARY32(ceil
.w
.s
)
658 ASM_VOLATILE_UNARY32_DOUBLE(ceil
.w
.d
)
661 ASM_VOLATILE_UNARY32(cvt
.d
.s
)
664 ASM_VOLATILE_UNARY32(cvt
.d
.w
)
667 ASM_VOLATILE_UNARY32(cvt
.s
.w
)
670 ASM_VOLATILE_UNARY32_DOUBLE(cvt
.s
.d
)
673 ASM_VOLATILE_UNARY32(cvt
.w
.s
)
676 ASM_VOLATILE_UNARY32_DOUBLE(cvt
.w
.d
)
679 ASM_VOLATILE_UNARY32(round
.w
.s
)
682 ASM_VOLATILE_BINARY32(add
.s
)
685 ASM_VOLATILE_BINARY32_DOUBLE(add
.d
)
688 ASM_VOLATILE_BINARY32(sub
.s
)
691 ASM_VOLATILE_BINARY32_DOUBLE(sub
.d
)
694 ASM_VOLATILE_BINARY32(div
.s
)
704 /* TODO: Add cases for all fpu instructions because all fpu instructions are
705 change the value of FCSR register. */
706 extern UInt
mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs
, UInt fs
, UInt ft
,
710 #if defined(__mips__) && ((__mips == 64) || \
711 (defined(__mips_isa_rev) && (__mips_isa_rev >= 2)))
712 #if defined(VGA_mips32)
713 VexGuestMIPS32State
* guest_state
= (VexGuestMIPS32State
*)gs
;
715 VexGuestMIPS64State
* guest_state
= (VexGuestMIPS64State
*)gs
;
717 ULong
*addr
= (ULong
*)&guest_state
->guest_f0
;
718 UInt fcsr
= guest_state
->guest_FCSR
;
721 ASM_VOLATILE_UNARY64(round
.w
.d
)
724 ASM_VOLATILE_UNARY64(floor
.w
.s
)
727 ASM_VOLATILE_UNARY64(floor
.w
.d
)
730 ASM_VOLATILE_UNARY64(trunc
.w
.s
)
733 ASM_VOLATILE_UNARY64(trunc
.w
.d
)
736 ASM_VOLATILE_UNARY64(ceil
.w
.s
)
739 ASM_VOLATILE_UNARY64(ceil
.w
.d
)
742 ASM_VOLATILE_UNARY64(cvt
.d
.s
)
745 ASM_VOLATILE_UNARY64(cvt
.d
.w
)
748 ASM_VOLATILE_UNARY64(cvt
.s
.w
)
751 ASM_VOLATILE_UNARY64(cvt
.s
.d
)
754 ASM_VOLATILE_UNARY64(cvt
.w
.s
)
757 ASM_VOLATILE_UNARY64(cvt
.w
.d
)
760 ASM_VOLATILE_UNARY64(round
.w
.s
)
763 ASM_VOLATILE_UNARY64(ceil
.l
.s
)
766 ASM_VOLATILE_UNARY64(ceil
.l
.d
)
769 ASM_VOLATILE_UNARY64(cvt
.d
.l
)
772 ASM_VOLATILE_UNARY64(cvt
.l
.s
)
775 ASM_VOLATILE_UNARY64(cvt
.l
.d
)
778 ASM_VOLATILE_UNARY64(cvt
.s
.l
)
781 ASM_VOLATILE_UNARY64(floor
.l
.s
)
784 ASM_VOLATILE_UNARY64(floor
.l
.d
)
787 ASM_VOLATILE_UNARY64(round
.l
.s
)
790 ASM_VOLATILE_UNARY64(round
.l
.d
)
793 ASM_VOLATILE_UNARY64(trunc
.l
.s
)
796 ASM_VOLATILE_UNARY64(trunc
.l
.d
)
799 ASM_VOLATILE_BINARY64(add
.s
)
802 ASM_VOLATILE_BINARY64(add
.d
)
805 ASM_VOLATILE_BINARY64(sub
.s
)
808 ASM_VOLATILE_BINARY64(sub
.d
)
811 ASM_VOLATILE_BINARY64(div
.s
)
813 #if defined(__mips_isa_rev) && (__mips_isa_rev >= 6)
815 ASM_VOLATILE_UNARY64(rint
.s
)
818 ASM_VOLATILE_UNARY64(rint
.d
)
821 ASM_VOLATILE_BINARY64(max
.s
)
824 ASM_VOLATILE_BINARY64(max
.d
)
827 ASM_VOLATILE_BINARY64(min
.s
)
830 ASM_VOLATILE_BINARY64(min
.d
)
833 ASM_VOLATILE_BINARY64(maxa
.s
)
836 ASM_VOLATILE_BINARY64(maxa
.d
)
839 ASM_VOLATILE_BINARY64(mina
.s
)
842 ASM_VOLATILE_BINARY64(mina
.d
)
845 ASM_VOLATILE_BINARY64(cmp
.af
.s
)
848 ASM_VOLATILE_BINARY64(cmp
.af
.d
)
851 ASM_VOLATILE_BINARY64(cmp
.saf
.s
)
854 ASM_VOLATILE_BINARY64(cmp
.saf
.d
)
866 extern UInt
mips_dirtyhelper_calculate_MSACSR ( void* gs
, UInt ws
, UInt wt
,
869 /* GCC 4.8 and later support MIPS MSA. */
870 #if defined(__mips__) && (defined(__clang__) || (GCC_VERSION >= 408))
871 #if defined(VGA_mips32)
872 VexGuestMIPS32State
* guest_state
= (VexGuestMIPS32State
*)gs
;
874 VexGuestMIPS64State
* guest_state
= (VexGuestMIPS64State
*)gs
;
876 V128
*addr
= (V128
*)&guest_state
->guest_w0
;
877 UInt msacsr
= guest_state
->guest_MSACSR
;
881 ASM_VOLATILE_MSA_BINARY(fadd
.w
)
885 ASM_VOLATILE_MSA_BINARY(fadd
.d
)
889 ASM_VOLATILE_MSA_BINARY(fsub
.w
);
893 ASM_VOLATILE_MSA_BINARY(fsub
.d
);
897 ASM_VOLATILE_MSA_BINARY(fmul
.w
);
901 ASM_VOLATILE_MSA_BINARY(fmul
.d
);
905 ASM_VOLATILE_MSA_BINARY(fdiv
.w
);
909 ASM_VOLATILE_MSA_BINARY(fdiv
.d
);
913 ASM_VOLATILE_MSA_BINARY(fmadd
.w
);
917 ASM_VOLATILE_MSA_BINARY(fmadd
.d
);
921 ASM_VOLATILE_MSA_BINARY(fcaf
.w
);
925 ASM_VOLATILE_MSA_BINARY(fcaf
.d
);
929 ASM_VOLATILE_MSA_BINARY(fsaf
.w
);
933 ASM_VOLATILE_MSA_BINARY(fsaf
.d
);
937 ASM_VOLATILE_MSA_BINARY(fceq
.w
);
941 ASM_VOLATILE_MSA_BINARY(fceq
.d
);
945 ASM_VOLATILE_MSA_BINARY(fseq
.w
);
949 ASM_VOLATILE_MSA_BINARY(fseq
.d
);
953 ASM_VOLATILE_MSA_BINARY(fclt
.w
);
957 ASM_VOLATILE_MSA_BINARY(fclt
.d
);
961 ASM_VOLATILE_MSA_BINARY(fslt
.w
);
965 ASM_VOLATILE_MSA_BINARY(fslt
.d
);
969 ASM_VOLATILE_MSA_BINARY(fcle
.w
);
973 ASM_VOLATILE_MSA_BINARY(fcle
.d
);
977 ASM_VOLATILE_MSA_BINARY(fsle
.w
);
981 ASM_VOLATILE_MSA_BINARY(fsle
.d
);
985 ASM_VOLATILE_MSA_BINARY(fcne
.w
);
989 ASM_VOLATILE_MSA_BINARY(fcne
.d
);
993 ASM_VOLATILE_MSA_BINARY(fsne
.w
);
997 ASM_VOLATILE_MSA_BINARY(fsne
.d
);
1001 ASM_VOLATILE_MSA_BINARY(fexp2
.w
);
1005 ASM_VOLATILE_MSA_BINARY(fexp2
.d
);
1009 ASM_VOLATILE_MSA_BINARY(fmin
.w
);
1013 ASM_VOLATILE_MSA_BINARY(fmin
.d
);
1017 ASM_VOLATILE_MSA_BINARY(fmin_a
.w
);
1021 ASM_VOLATILE_MSA_BINARY(fmin_a
.d
);
1025 ASM_VOLATILE_MSA_BINARY(fcun
.w
);
1029 ASM_VOLATILE_MSA_BINARY(fcun
.d
);
1033 ASM_VOLATILE_MSA_BINARY(fsun
.w
);
1037 ASM_VOLATILE_MSA_BINARY(fsun
.d
);
1041 ASM_VOLATILE_MSA_BINARY(fcor
.w
);
1045 ASM_VOLATILE_MSA_BINARY(fcor
.d
);
1049 ASM_VOLATILE_MSA_BINARY(fsor
.w
);
1053 ASM_VOLATILE_MSA_BINARY(fsor
.d
);
1057 ASM_VOLATILE_MSA_BINARY(fcueq
.w
);
1061 ASM_VOLATILE_MSA_BINARY(fcueq
.d
);
1065 ASM_VOLATILE_MSA_BINARY(fsueq
.w
);
1069 ASM_VOLATILE_MSA_BINARY(fsueq
.d
);
1073 ASM_VOLATILE_MSA_BINARY(fcune
.w
);
1077 ASM_VOLATILE_MSA_BINARY(fcune
.d
);
1081 ASM_VOLATILE_MSA_BINARY(fsune
.w
);
1085 ASM_VOLATILE_MSA_BINARY(fsune
.d
);
1089 ASM_VOLATILE_MSA_BINARY(fcule
.w
);
1093 ASM_VOLATILE_MSA_BINARY(fcule
.d
);
1097 ASM_VOLATILE_MSA_BINARY(fsule
.w
);
1101 ASM_VOLATILE_MSA_BINARY(fsule
.d
);
1105 ASM_VOLATILE_MSA_BINARY(fcult
.w
);
1109 ASM_VOLATILE_MSA_BINARY(fcult
.d
);
1113 ASM_VOLATILE_MSA_BINARY(fsult
.w
);
1117 ASM_VOLATILE_MSA_BINARY(fsult
.d
);
1121 ASM_VOLATILE_MSA_BINARY(fmax
.w
);
1125 ASM_VOLATILE_MSA_BINARY(fmax
.d
);
1129 ASM_VOLATILE_MSA_BINARY(fmax_a
.w
);
1133 ASM_VOLATILE_MSA_BINARY(fmax_a
.d
);
1137 ASM_VOLATILE_MSA_UNARY(ffint_s
.w
);
1141 ASM_VOLATILE_MSA_UNARY(ffint_s
.d
);
1145 ASM_VOLATILE_MSA_UNARY(frcp
.w
);
1149 ASM_VOLATILE_MSA_UNARY(frcp
.d
);
1153 ASM_VOLATILE_MSA_UNARY(frsqrt
.w
);
1157 ASM_VOLATILE_MSA_UNARY(frsqrt
.d
);
1161 ASM_VOLATILE_MSA_UNARY(fsqrt
.w
);
1165 ASM_VOLATILE_MSA_UNARY(fsqrt
.d
);
1169 ASM_VOLATILE_MSA_UNARY(frint
.w
);
1173 ASM_VOLATILE_MSA_UNARY(frint
.d
);
1177 ASM_VOLATILE_MSA_UNARY(ftrunc_u
.w
);
1181 ASM_VOLATILE_MSA_UNARY(ftrunc_u
.d
);
1185 ASM_VOLATILE_MSA_UNARY(ftrunc_s
.w
);
1189 ASM_VOLATILE_MSA_UNARY(ftrunc_s
.d
);
1193 ASM_VOLATILE_MSA_BINARY(fexdo
.h
);
1197 ASM_VOLATILE_MSA_BINARY(fexdo
.w
);
1201 ASM_VOLATILE_MSA_UNARY(fexupr
.w
);
1205 ASM_VOLATILE_MSA_UNARY(fexupr
.d
);
1209 ASM_VOLATILE_MSA_UNARY(fexupl
.w
);
1213 ASM_VOLATILE_MSA_UNARY(fexupl
.d
);
1217 ASM_VOLATILE_MSA_BINARY(ftq
.h
);
1221 ASM_VOLATILE_MSA_BINARY(ftq
.w
);
1225 ASM_VOLATILE_MSA_UNARY(ffqr
.d
);
1229 ASM_VOLATILE_MSA_UNARY(ffqr
.w
);
1233 ASM_VOLATILE_MSA_UNARY(ffql
.d
);
1237 ASM_VOLATILE_MSA_UNARY(ffql
.w
);
1241 ASM_VOLATILE_MSA_UNARY(ftint_s
.d
);
1245 ASM_VOLATILE_MSA_UNARY(ftint_s
.w
);
1249 ASM_VOLATILE_MSA_UNARY(ftint_u
.d
);
1253 ASM_VOLATILE_MSA_UNARY(ftint_u
.w
);
1257 ASM_VOLATILE_MSA_UNARY(flog2
.d
);
1261 ASM_VOLATILE_MSA_UNARY(flog2
.w
);
1265 ASM_VOLATILE_MSA_UNARY(ffint_u
.d
);
1269 ASM_VOLATILE_MSA_UNARY(ffint_u
.w
);
1277 extern UInt
mips_dirtyhelper_get_MSAIR() {
1279 /* GCC 4.8 and later support MIPS MSA. */
1280 #if defined(__mips__) && (defined(__clang__) || (GCC_VERSION >= 408))
1281 __asm__
volatile(".set push \n\t"
1282 ".set mips32r2 \n\t"
1283 ".set hardfloat \n\t"
1286 ".set noreorder \n\t"
1287 "cfcmsa %0, $0 \n\t"
1297 /*---------------------------------------------------------------*/
1298 /*--- end guest_mips_helpers.c ---*/
1299 /*---------------------------------------------------------------*/