mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-10 13:40:25 +00:00
string in valgrind.pc.in, so that they describe Valgrind as a "dynamic binary instrumentation framework", and don't mention platforms at all. I had to tweak the regtest filters a bit for this. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3178
166 lines
4.4 KiB
ArmAsm
166 lines
4.4 KiB
ArmAsm
|
|
##--------------------------------------------------------------------##
|
|
##--- The core dispatch loop, for jumping to a code address. ---##
|
|
##--- amd64/dispatch.S ---##
|
|
##--------------------------------------------------------------------##
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2000-2004 Julian Seward
|
|
jseward@acm.org
|
|
|
|
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 "core_asm.h"
|
|
#include "amd64_private_asm.h"
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- The dispatch loop. ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
#define TT_LOOKUP(reg, fail) \
|
|
movq %rax, reg; \
|
|
andq $VG_TT_FAST_MASK, reg; \
|
|
movq VG_(tt_fast)(,reg,8), reg; \
|
|
cmpq %rax, (reg); \
|
|
jnz fail
|
|
|
|
.globl VG_(run_innerloop)
|
|
VG_(run_innerloop):
|
|
/* %rdi holds guest_state */
|
|
|
|
/* ----- entry point to VG_(run_innerloop) ----- */
|
|
pushq %rbx
|
|
pushq %rcx
|
|
pushq %rdx
|
|
pushq %rsi
|
|
pushq %rbp
|
|
pushq %r8
|
|
pushq %r9
|
|
pushq %r10
|
|
pushq %r11
|
|
pushq %r12
|
|
pushq %r13
|
|
pushq %r14
|
|
pushq %r15
|
|
pushq %rdi
|
|
|
|
/* 0(%rsp) holds cached copy of guest_state */
|
|
|
|
/* Set up the guest state pointer */
|
|
movq %rdi, %rbp
|
|
|
|
/* fetch %RIP into %rax */
|
|
movq VG_(instr_ptr_offset), %rsi
|
|
movq (%rbp, %rsi, 1), %rax
|
|
|
|
/* fall into main loop */
|
|
|
|
/* Here, %rax is the only live (real) register. The entire
|
|
simulated state is saved in the ThreadState. */
|
|
|
|
dispatch_boring:
|
|
/* save the jump address in the guest state */
|
|
movq VG_(instr_ptr_offset), %rsi
|
|
movq %rax, (%rbp, %rsi, 1)
|
|
|
|
/* Are we out of timeslice? If yes, defer to scheduler. */
|
|
subl $1, VG_(dispatch_ctr)
|
|
|
|
jz counter_is_zero
|
|
/* try a fast lookup in the translation cache */
|
|
TT_LOOKUP(%rbx, fast_lookup_failed)
|
|
|
|
/* Found a match. Call the tce.payload field. The magic 12
|
|
value is offsetof(TCEntry,payload) on a 64-bit platform. */
|
|
addq $12, %rbx
|
|
call *%rbx
|
|
|
|
/*
|
|
%rax holds destination (original) address.
|
|
%rbp indicates further details of the control transfer
|
|
requested to the address in %rax.
|
|
|
|
If rbp is unchanged (== * 0(%rsp)), just jump next to %rax.
|
|
|
|
Otherwise fall out, back to the scheduler, and let it
|
|
figure out what to do next.
|
|
*/
|
|
|
|
cmpq 0(%rsp), %rbp
|
|
jz dispatch_boring
|
|
|
|
jmp dispatch_exceptional
|
|
|
|
|
|
fast_lookup_failed:
|
|
/* %RIP is up to date here since dispatch_boring dominates */
|
|
addl $1, VG_(dispatch_ctr)
|
|
movq $VG_TRC_INNER_FASTMISS, %rax
|
|
jmp run_innerloop_exit
|
|
|
|
counter_is_zero:
|
|
/* %RIP is up to date here since dispatch_boring dominates */
|
|
addl $1, VG_(dispatch_ctr)
|
|
movq $VG_TRC_INNER_COUNTERZERO, %rax
|
|
jmp run_innerloop_exit
|
|
|
|
run_innerloop_exit:
|
|
popq %rdi
|
|
popq %r15
|
|
popq %r14
|
|
popq %r13
|
|
popq %r12
|
|
popq %r11
|
|
popq %r10
|
|
popq %r9
|
|
popq %r8
|
|
popq %rbp
|
|
popq %rsi
|
|
popq %rdx
|
|
popq %rcx
|
|
popq %rbx
|
|
ret
|
|
|
|
|
|
|
|
/* Other ways of getting out of the inner loop. Placed out-of-line to
|
|
make it look cleaner.
|
|
*/
|
|
dispatch_exceptional:
|
|
/* this is jumped to only, not fallen-through from above */
|
|
cmpq $VG_TRC_INNER_COUNTERZERO, %rbp
|
|
jz counter_is_zero
|
|
|
|
/* save %rax in %RIP and defer to sched */
|
|
movq VG_(instr_ptr_offset), %rsi
|
|
movq 0(%rsp), %rdi
|
|
movq %rax, (%rdi, %rsi, 1)
|
|
movq %rbp, %rax
|
|
jmp run_innerloop_exit
|
|
|
|
/* Let the linker know we don't need an executable stack */
|
|
.section .note.GNU-stack,"",@progbits
|
|
|
|
##--------------------------------------------------------------------##
|
|
##--- end ---##
|
|
##--------------------------------------------------------------------##
|