| |
| /*---------------------------------------------------------------*/ |
| /*--- begin guest_mips_helpers.c ---*/ |
| /*---------------------------------------------------------------*/ |
| |
| /* |
| This file is part of Valgrind, a dynamic binary instrumentation |
| framework. |
| |
| Copyright (C) 2010-2012 RT-RK |
| mips-valgrind@rt-rk.com |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of the |
| License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| |
| #include "libvex_basictypes.h" |
| #include "libvex_emwarn.h" |
| #include "libvex_guest_mips32.h" |
| #include "libvex_ir.h" |
| #include "libvex.h" |
| |
| #include "main_util.h" |
| #include "guest_generic_bb_to_IR.h" |
| #include "guest_mips_defs.h" |
| |
| /* This file contains helper functions for mips guest code. Calls to |
| these functions are generated by the back end. |
| */ |
| |
| #define ALWAYSDEFD32(field) \ |
| { offsetof(VexGuestMIPS32State, field), \ |
| (sizeof ((VexGuestMIPS32State*)0)->field) } |
| |
| IRExpr *guest_mips32_spechelper(HChar * function_name, IRExpr ** args, |
| IRStmt ** precedingStmts, Int n_precedingStmts) |
| { |
| return NULL; |
| } |
| |
| /* VISIBLE TO LIBVEX CLIENT */ |
| void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state) |
| { |
| vex_state->guest_r0 = 0; /* Hardwired to 0 */ |
| vex_state->guest_r1 = 0; /* Assembler temporary */ |
| vex_state->guest_r2 = 0; /* Values for function returns ... */ |
| vex_state->guest_r3 = 0; /* ...and expression evaluation */ |
| vex_state->guest_r4 = 0; /* Function arguments */ |
| vex_state->guest_r5 = 0; |
| vex_state->guest_r6 = 0; |
| vex_state->guest_r7 = 0; |
| vex_state->guest_r8 = 0; /* Temporaries */ |
| vex_state->guest_r9 = 0; |
| vex_state->guest_r10 = 0; |
| vex_state->guest_r11 = 0; |
| vex_state->guest_r12 = 0; |
| vex_state->guest_r13 = 0; |
| vex_state->guest_r14 = 0; |
| vex_state->guest_r15 = 0; |
| vex_state->guest_r16 = 0; /* Saved temporaries */ |
| vex_state->guest_r17 = 0; |
| vex_state->guest_r18 = 0; |
| vex_state->guest_r19 = 0; |
| vex_state->guest_r20 = 0; |
| vex_state->guest_r21 = 0; |
| vex_state->guest_r22 = 0; |
| vex_state->guest_r23 = 0; |
| vex_state->guest_r24 = 0; /* Temporaries */ |
| vex_state->guest_r25 = 0; |
| vex_state->guest_r26 = 0; /* Reserved for OS kernel */ |
| vex_state->guest_r27 = 0; |
| vex_state->guest_r28 = 0; /* Global pointer */ |
| vex_state->guest_r29 = 0; /* Stack pointer */ |
| vex_state->guest_r30 = 0; /* Frame pointer */ |
| vex_state->guest_r31 = 0; /* Return address */ |
| vex_state->guest_PC = 0; /* Program counter */ |
| vex_state->guest_HI = 0; /* Multiply and divide register higher result */ |
| vex_state->guest_LO = 0; /* Multiply and divide register lower result */ |
| |
| /* FPU Registers */ |
| vex_state->guest_f0 = 0x7ff80000; /* Floting point general purpose registers */ |
| vex_state->guest_f1 = 0x7ff80000; |
| vex_state->guest_f2 = 0x7ff80000; |
| vex_state->guest_f3 = 0x7ff80000; |
| vex_state->guest_f4 = 0x7ff80000; |
| vex_state->guest_f5 = 0x7ff80000; |
| vex_state->guest_f6 = 0x7ff80000; |
| vex_state->guest_f7 = 0x7ff80000; |
| vex_state->guest_f8 = 0x7ff80000; |
| vex_state->guest_f9 = 0x7ff80000; |
| vex_state->guest_f10 = 0x7ff80000; |
| vex_state->guest_f11 = 0x7ff80000; |
| vex_state->guest_f12 = 0x7ff80000; |
| vex_state->guest_f13 = 0x7ff80000; |
| vex_state->guest_f14 = 0x7ff80000; |
| vex_state->guest_f15 = 0x7ff80000; |
| vex_state->guest_f16 = 0x7ff80000; |
| vex_state->guest_f17 = 0x7ff80000; |
| vex_state->guest_f18 = 0x7ff80000; |
| vex_state->guest_f19 = 0x7ff80000; |
| vex_state->guest_f20 = 0x7ff80000; |
| vex_state->guest_f21 = 0x7ff80000; |
| vex_state->guest_f22 = 0x7ff80000; |
| vex_state->guest_f23 = 0x7ff80000; |
| vex_state->guest_f24 = 0x7ff80000; |
| vex_state->guest_f25 = 0x7ff80000; |
| vex_state->guest_f26 = 0x7ff80000; |
| vex_state->guest_f27 = 0x7ff80000; |
| vex_state->guest_f28 = 0x7ff80000; |
| vex_state->guest_f29 = 0x7ff80000; |
| vex_state->guest_f30 = 0x7ff80000; |
| vex_state->guest_f31 = 0x7ff80000; |
| |
| vex_state->guest_FIR = 0; /* FP implementation and revision register */ |
| vex_state->guest_FCCR = 0; /* FP condition codes register */ |
| vex_state->guest_FEXR = 0; /* FP exceptions register */ |
| vex_state->guest_FENR = 0; /* FP enables register */ |
| vex_state->guest_FCSR = 0; /* FP control/status register */ |
| vex_state->guest_ULR = 0; /* TLS */ |
| |
| /* Various pseudo-regs mandated by Vex or Valgrind. */ |
| /* Emulation warnings */ |
| vex_state->guest_EMWARN = 0; |
| |
| /* For clflush: record start and length of area to invalidate */ |
| vex_state->guest_TISTART = 0; |
| vex_state->guest_TILEN = 0; |
| vex_state->host_EvC_COUNTER = 0; |
| vex_state->host_EvC_FAILADDR = 0; |
| |
| /* Used to record the unredirected guest address at the start of |
| a translation whose start has been redirected. By reading |
| this pseudo-register shortly afterwards, the translation can |
| find out what the corresponding no-redirection address was. |
| Note, this is only set for wrap-style redirects, not for |
| replace-style ones. */ |
| vex_state->guest_NRADDR = 0; |
| |
| vex_state->guest_COND = 0; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| /*--- Describing the mips guest state, for the benefit ---*/ |
| /*--- of iropt and instrumenters. ---*/ |
| /*-----------------------------------------------------------*/ |
| |
| /* Figure out if any part of the guest state contained in minoff |
| .. maxoff requires precise memory exceptions. If in doubt return |
| True (but this is generates significantly slower code). |
| |
| We enforce precise exns for guest SP, PC. |
| */ |
| Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff) |
| { |
| Int sp_min = offsetof(VexGuestMIPS32State, guest_r29); |
| Int sp_max = sp_min + 4 - 1; |
| Int pc_min = offsetof(VexGuestMIPS32State, guest_PC); |
| Int pc_max = pc_min + 4 - 1; |
| |
| if (maxoff < sp_min || minoff > sp_max) { |
| /* no overlap with sp */ |
| } else { |
| return True; |
| } |
| |
| if (maxoff < pc_min || minoff > pc_max) { |
| /* no overlap with pc */ |
| } else { |
| return True; |
| } |
| |
| /* We appear to need precise updates of R11 in order to get proper |
| stacktraces from non-optimised code. */ |
| Int fp_min = offsetof(VexGuestMIPS32State, guest_r30); |
| Int fp_max = fp_min + 4 - 1; |
| |
| if (maxoff < fp_min || minoff > fp_max) { |
| /* no overlap with fp */ |
| } else { |
| return True; |
| } |
| |
| return False; |
| } |
| |
| VexGuestLayout mips32Guest_layout = { |
| /* Total size of the guest state, in bytes. */ |
| .total_sizeB = sizeof(VexGuestMIPS32State), |
| /* Describe the stack pointer. */ |
| .offset_SP = offsetof(VexGuestMIPS32State, guest_r29), |
| .sizeof_SP = 4, |
| /* Describe the frame pointer. */ |
| .offset_FP = offsetof(VexGuestMIPS32State, guest_r30), |
| .sizeof_FP = 4, |
| /* Describe the instruction pointer. */ |
| .offset_IP = offsetof(VexGuestMIPS32State, guest_PC), |
| .sizeof_IP = 4, |
| /* Describe any sections to be regarded by Memcheck as |
| 'always-defined'. */ |
| .n_alwaysDefd = 8, |
| /* ? :( */ |
| .alwaysDefd = { |
| /* 0 */ ALWAYSDEFD32(guest_r0), |
| /* 1 */ ALWAYSDEFD32(guest_r1), |
| /* 2 */ ALWAYSDEFD32(guest_EMWARN), |
| /* 3 */ ALWAYSDEFD32(guest_TISTART), |
| /* 4 */ ALWAYSDEFD32(guest_TILEN), |
| /* 5 */ ALWAYSDEFD32(guest_r29), |
| /* 6 */ ALWAYSDEFD32(guest_r31), |
| /* 7 */ ALWAYSDEFD32(guest_ULR) |
| } |
| }; |
| |
| #define ASM_VOLATILE_CASE(rd, sel) \ |
| case rd: asm volatile ("mfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break; |
| |
| UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel) |
| { |
| UInt x = 0; |
| #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2)) |
| switch (sel) { |
| case 0: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 0); |
| ASM_VOLATILE_CASE(1, 0); |
| ASM_VOLATILE_CASE(2, 0); |
| ASM_VOLATILE_CASE(3, 0); |
| ASM_VOLATILE_CASE(4, 0); |
| ASM_VOLATILE_CASE(5, 0); |
| ASM_VOLATILE_CASE(6, 0); |
| ASM_VOLATILE_CASE(7, 0); |
| ASM_VOLATILE_CASE(8, 0); |
| ASM_VOLATILE_CASE(9, 0); |
| ASM_VOLATILE_CASE(10, 0); |
| ASM_VOLATILE_CASE(11, 0); |
| ASM_VOLATILE_CASE(12, 0); |
| ASM_VOLATILE_CASE(13, 0); |
| ASM_VOLATILE_CASE(14, 0); |
| ASM_VOLATILE_CASE(15, 0); |
| ASM_VOLATILE_CASE(16, 0); |
| ASM_VOLATILE_CASE(17, 0); |
| ASM_VOLATILE_CASE(18, 0); |
| ASM_VOLATILE_CASE(19, 0); |
| ASM_VOLATILE_CASE(20, 0); |
| ASM_VOLATILE_CASE(21, 0); |
| ASM_VOLATILE_CASE(22, 0); |
| ASM_VOLATILE_CASE(23, 0); |
| ASM_VOLATILE_CASE(24, 0); |
| ASM_VOLATILE_CASE(25, 0); |
| ASM_VOLATILE_CASE(26, 0); |
| ASM_VOLATILE_CASE(27, 0); |
| ASM_VOLATILE_CASE(28, 0); |
| ASM_VOLATILE_CASE(29, 0); |
| ASM_VOLATILE_CASE(30, 0); |
| ASM_VOLATILE_CASE(31, 0); |
| default: |
| break; |
| } |
| break; |
| case 1: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 1); |
| ASM_VOLATILE_CASE(1, 1); |
| ASM_VOLATILE_CASE(2, 1); |
| ASM_VOLATILE_CASE(3, 1); |
| ASM_VOLATILE_CASE(4, 1); |
| ASM_VOLATILE_CASE(5, 1); |
| ASM_VOLATILE_CASE(6, 1); |
| ASM_VOLATILE_CASE(7, 1); |
| ASM_VOLATILE_CASE(8, 1); |
| ASM_VOLATILE_CASE(9, 1); |
| ASM_VOLATILE_CASE(10, 1); |
| ASM_VOLATILE_CASE(11, 1); |
| ASM_VOLATILE_CASE(12, 1); |
| ASM_VOLATILE_CASE(13, 1); |
| ASM_VOLATILE_CASE(14, 1); |
| ASM_VOLATILE_CASE(15, 1); |
| ASM_VOLATILE_CASE(16, 1); |
| ASM_VOLATILE_CASE(17, 1); |
| ASM_VOLATILE_CASE(18, 1); |
| ASM_VOLATILE_CASE(19, 1); |
| ASM_VOLATILE_CASE(20, 1); |
| ASM_VOLATILE_CASE(21, 1); |
| ASM_VOLATILE_CASE(22, 1); |
| ASM_VOLATILE_CASE(23, 1); |
| ASM_VOLATILE_CASE(24, 1); |
| ASM_VOLATILE_CASE(25, 1); |
| ASM_VOLATILE_CASE(26, 1); |
| ASM_VOLATILE_CASE(27, 1); |
| ASM_VOLATILE_CASE(28, 1); |
| ASM_VOLATILE_CASE(29, 1); |
| ASM_VOLATILE_CASE(30, 1); |
| ASM_VOLATILE_CASE(31, 1); |
| default: |
| break; |
| } |
| break; |
| case 2: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 2); |
| ASM_VOLATILE_CASE(1, 2); |
| ASM_VOLATILE_CASE(2, 2); |
| ASM_VOLATILE_CASE(3, 1); |
| ASM_VOLATILE_CASE(4, 2); |
| ASM_VOLATILE_CASE(5, 2); |
| ASM_VOLATILE_CASE(6, 2); |
| ASM_VOLATILE_CASE(7, 2); |
| ASM_VOLATILE_CASE(8, 2); |
| ASM_VOLATILE_CASE(9, 2); |
| ASM_VOLATILE_CASE(10, 2); |
| ASM_VOLATILE_CASE(11, 2); |
| ASM_VOLATILE_CASE(12, 2); |
| ASM_VOLATILE_CASE(13, 2); |
| ASM_VOLATILE_CASE(14, 2); |
| ASM_VOLATILE_CASE(15, 2); |
| ASM_VOLATILE_CASE(16, 2); |
| ASM_VOLATILE_CASE(17, 2); |
| ASM_VOLATILE_CASE(18, 2); |
| ASM_VOLATILE_CASE(19, 2); |
| ASM_VOLATILE_CASE(20, 2); |
| ASM_VOLATILE_CASE(21, 2); |
| ASM_VOLATILE_CASE(22, 2); |
| ASM_VOLATILE_CASE(23, 2); |
| ASM_VOLATILE_CASE(24, 2); |
| ASM_VOLATILE_CASE(25, 2); |
| ASM_VOLATILE_CASE(26, 2); |
| ASM_VOLATILE_CASE(27, 2); |
| ASM_VOLATILE_CASE(28, 2); |
| ASM_VOLATILE_CASE(29, 2); |
| ASM_VOLATILE_CASE(30, 2); |
| ASM_VOLATILE_CASE(31, 2); |
| default: |
| break; |
| } |
| break; |
| case 3: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 3); |
| ASM_VOLATILE_CASE(1, 3); |
| ASM_VOLATILE_CASE(2, 3); |
| ASM_VOLATILE_CASE(3, 3); |
| ASM_VOLATILE_CASE(4, 3); |
| ASM_VOLATILE_CASE(5, 3); |
| ASM_VOLATILE_CASE(6, 3); |
| ASM_VOLATILE_CASE(7, 3); |
| ASM_VOLATILE_CASE(8, 3); |
| ASM_VOLATILE_CASE(9, 3); |
| ASM_VOLATILE_CASE(10, 3); |
| ASM_VOLATILE_CASE(11, 3); |
| ASM_VOLATILE_CASE(12, 3); |
| ASM_VOLATILE_CASE(13, 3); |
| ASM_VOLATILE_CASE(14, 3); |
| ASM_VOLATILE_CASE(15, 3); |
| ASM_VOLATILE_CASE(16, 3); |
| ASM_VOLATILE_CASE(17, 3); |
| ASM_VOLATILE_CASE(18, 3); |
| ASM_VOLATILE_CASE(19, 3); |
| ASM_VOLATILE_CASE(20, 3); |
| ASM_VOLATILE_CASE(21, 3); |
| ASM_VOLATILE_CASE(22, 3); |
| ASM_VOLATILE_CASE(23, 3); |
| ASM_VOLATILE_CASE(24, 3); |
| ASM_VOLATILE_CASE(25, 3); |
| ASM_VOLATILE_CASE(26, 3); |
| ASM_VOLATILE_CASE(27, 3); |
| ASM_VOLATILE_CASE(28, 3); |
| ASM_VOLATILE_CASE(29, 3); |
| ASM_VOLATILE_CASE(30, 3); |
| ASM_VOLATILE_CASE(31, 3); |
| default: |
| break; |
| } |
| break; |
| case 4: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 4); |
| ASM_VOLATILE_CASE(1, 4); |
| ASM_VOLATILE_CASE(2, 4); |
| ASM_VOLATILE_CASE(3, 4); |
| ASM_VOLATILE_CASE(4, 4); |
| ASM_VOLATILE_CASE(5, 4); |
| ASM_VOLATILE_CASE(6, 4); |
| ASM_VOLATILE_CASE(7, 4); |
| ASM_VOLATILE_CASE(8, 4); |
| ASM_VOLATILE_CASE(9, 4); |
| ASM_VOLATILE_CASE(10, 4); |
| ASM_VOLATILE_CASE(11, 4); |
| ASM_VOLATILE_CASE(12, 4); |
| ASM_VOLATILE_CASE(13, 4); |
| ASM_VOLATILE_CASE(14, 4); |
| ASM_VOLATILE_CASE(15, 4); |
| ASM_VOLATILE_CASE(16, 4); |
| ASM_VOLATILE_CASE(17, 4); |
| ASM_VOLATILE_CASE(18, 4); |
| ASM_VOLATILE_CASE(19, 4); |
| ASM_VOLATILE_CASE(20, 4); |
| ASM_VOLATILE_CASE(21, 4); |
| ASM_VOLATILE_CASE(22, 4); |
| ASM_VOLATILE_CASE(23, 4); |
| ASM_VOLATILE_CASE(24, 4); |
| ASM_VOLATILE_CASE(25, 4); |
| ASM_VOLATILE_CASE(26, 4); |
| ASM_VOLATILE_CASE(27, 4); |
| ASM_VOLATILE_CASE(28, 4); |
| ASM_VOLATILE_CASE(29, 4); |
| ASM_VOLATILE_CASE(30, 4); |
| ASM_VOLATILE_CASE(31, 4); |
| default: |
| break; |
| } |
| break; |
| case 5: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 5); |
| ASM_VOLATILE_CASE(1, 5); |
| ASM_VOLATILE_CASE(2, 5); |
| ASM_VOLATILE_CASE(3, 5); |
| ASM_VOLATILE_CASE(4, 5); |
| ASM_VOLATILE_CASE(5, 5); |
| ASM_VOLATILE_CASE(6, 5); |
| ASM_VOLATILE_CASE(7, 5); |
| ASM_VOLATILE_CASE(8, 5); |
| ASM_VOLATILE_CASE(9, 5); |
| ASM_VOLATILE_CASE(10, 5); |
| ASM_VOLATILE_CASE(11, 5); |
| ASM_VOLATILE_CASE(12, 5); |
| ASM_VOLATILE_CASE(13, 5); |
| ASM_VOLATILE_CASE(14, 5); |
| ASM_VOLATILE_CASE(15, 5); |
| ASM_VOLATILE_CASE(16, 5); |
| ASM_VOLATILE_CASE(17, 5); |
| ASM_VOLATILE_CASE(18, 5); |
| ASM_VOLATILE_CASE(19, 5); |
| ASM_VOLATILE_CASE(20, 5); |
| ASM_VOLATILE_CASE(21, 5); |
| ASM_VOLATILE_CASE(22, 5); |
| ASM_VOLATILE_CASE(23, 5); |
| ASM_VOLATILE_CASE(24, 5); |
| ASM_VOLATILE_CASE(25, 5); |
| ASM_VOLATILE_CASE(26, 5); |
| ASM_VOLATILE_CASE(27, 5); |
| ASM_VOLATILE_CASE(28, 5); |
| ASM_VOLATILE_CASE(29, 5); |
| ASM_VOLATILE_CASE(30, 5); |
| ASM_VOLATILE_CASE(31, 5); |
| default: |
| break; |
| } |
| break; |
| case 6: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 6); |
| ASM_VOLATILE_CASE(1, 6); |
| ASM_VOLATILE_CASE(2, 6); |
| ASM_VOLATILE_CASE(3, 6); |
| ASM_VOLATILE_CASE(4, 6); |
| ASM_VOLATILE_CASE(5, 6); |
| ASM_VOLATILE_CASE(6, 6); |
| ASM_VOLATILE_CASE(7, 6); |
| ASM_VOLATILE_CASE(8, 6); |
| ASM_VOLATILE_CASE(9, 6); |
| ASM_VOLATILE_CASE(10, 6); |
| ASM_VOLATILE_CASE(11, 6); |
| ASM_VOLATILE_CASE(12, 6); |
| ASM_VOLATILE_CASE(13, 6); |
| ASM_VOLATILE_CASE(14, 6); |
| ASM_VOLATILE_CASE(15, 6); |
| ASM_VOLATILE_CASE(16, 6); |
| ASM_VOLATILE_CASE(17, 6); |
| ASM_VOLATILE_CASE(18, 6); |
| ASM_VOLATILE_CASE(19, 6); |
| ASM_VOLATILE_CASE(20, 6); |
| ASM_VOLATILE_CASE(21, 6); |
| ASM_VOLATILE_CASE(22, 6); |
| ASM_VOLATILE_CASE(23, 6); |
| ASM_VOLATILE_CASE(24, 6); |
| ASM_VOLATILE_CASE(25, 6); |
| ASM_VOLATILE_CASE(26, 6); |
| ASM_VOLATILE_CASE(27, 6); |
| ASM_VOLATILE_CASE(28, 6); |
| ASM_VOLATILE_CASE(29, 6); |
| ASM_VOLATILE_CASE(30, 6); |
| ASM_VOLATILE_CASE(31, 6); |
| default: |
| break; |
| } |
| break; |
| case 7: |
| //__asm__("mfc0 %0, $1, 0" :"=r" (x)); |
| switch (rd) { |
| ASM_VOLATILE_CASE(0, 7); |
| ASM_VOLATILE_CASE(1, 7); |
| ASM_VOLATILE_CASE(2, 7); |
| ASM_VOLATILE_CASE(3, 7); |
| ASM_VOLATILE_CASE(4, 7); |
| ASM_VOLATILE_CASE(5, 7); |
| ASM_VOLATILE_CASE(6, 7); |
| ASM_VOLATILE_CASE(7, 7); |
| ASM_VOLATILE_CASE(8, 7); |
| ASM_VOLATILE_CASE(9, 7); |
| ASM_VOLATILE_CASE(10, 7); |
| ASM_VOLATILE_CASE(11, 7); |
| ASM_VOLATILE_CASE(12, 7); |
| ASM_VOLATILE_CASE(13, 7); |
| ASM_VOLATILE_CASE(14, 7); |
| ASM_VOLATILE_CASE(15, 7); |
| ASM_VOLATILE_CASE(16, 7); |
| ASM_VOLATILE_CASE(17, 7); |
| ASM_VOLATILE_CASE(18, 7); |
| ASM_VOLATILE_CASE(19, 7); |
| ASM_VOLATILE_CASE(20, 7); |
| ASM_VOLATILE_CASE(21, 7); |
| ASM_VOLATILE_CASE(22, 7); |
| ASM_VOLATILE_CASE(23, 7); |
| ASM_VOLATILE_CASE(24, 7); |
| ASM_VOLATILE_CASE(25, 7); |
| ASM_VOLATILE_CASE(26, 7); |
| ASM_VOLATILE_CASE(27, 7); |
| ASM_VOLATILE_CASE(28, 7); |
| ASM_VOLATILE_CASE(29, 7); |
| ASM_VOLATILE_CASE(30, 7); |
| ASM_VOLATILE_CASE(31, 7); |
| default: |
| break; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| #endif |
| return x; |
| } |
| |
| #undef ASM_VOLATILE_CASE |
| |
| #define ASM_VOLATILE_CASE(rd, sel) \ |
| case rd: asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break; |
| |
| #define ASM_VOLATILE_SYNC(stype) \ |
| asm volatile ("sync \n\t"); |
| |
| void mips32_dirtyhelper_sync(UInt stype) |
| { |
| #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2)) |
| ASM_VOLATILE_SYNC(0); |
| #endif |
| } |
| |
| /*---------------------------------------------------------------*/ |
| /*--- end guest_mips_helpers.c ---*/ |
| /*---------------------------------------------------------------*/ |