
Verification todo
~~~~~~~~~~~~~~~~~
check that illegal insns on all targets don't cause the _toIR.c's to
assert.  [DONE: amd64 x86 ppc32 ppc64 arm s390]

check also with --vex-guest-chase-cond=yes

check that all targets can run their insn set tests with
--vex-guest-max-insns=1.

all targets: run some tests using --profile-flags=... to exercise  
function patchProfInc_<arch> [DONE: amd64 x86 ppc32 ppc64 arm s390]

figure out if there is a way to write a test program that checks
that event checks are actually getting triggered


Cleanups
~~~~~~~~
host_arm_isel.c and host_arm_defs.c: get rid of global var arm_hwcaps.

host_x86_defs.c, host_amd64_defs.c: return proper VexInvalRange
records from the patchers, instead of {0,0}, so that transparent
self hosting works properly.

host_ppc_defs.h: is RdWrLR still needed?  If not delete.

ditto ARM, Ld8S

Comments that used to be in m_scheduler.c:
   tchaining tests:
   - extensive spinrounds
   - with sched quantum = 1  -- check that handle_noredir_jump
     doesn't return with INNER_COUNTERZERO
   other:
   - out of date comment w.r.t. bit 0 set in libvex_trc_values.h
   - can VG_TRC_BORING still happen?  if not, rm
   - memory leaks in m_transtab (InEdgeArr/OutEdgeArr leaking?)
   - move do_cacheflush out of m_transtab
   - more economical unchaining when nuking an entire sector
   - ditto w.r.t. cache flushes
   - verify case of 2 paths from A to B
   - check -- is IP_AT_SYSCALL still right?


Optimisations
~~~~~~~~~~~~~
ppc: chain_XDirect: generate short form jumps when possible

ppc64: immediate generation is terrible .. should be able
       to do better

arm codegen: Generate ORRS for CmpwNEZ32(Or32(x,y))

all targets: when nuking an entire sector, don't bother to undo the
patching for any translations within the sector (nor with their
invalidations).

(somewhat implausible) for jumps to disp_cp_indir, have multiple
copies of disp_cp_indir, one for each of the possible registers that
could have held the target guest address before jumping to the stub.
Then disp_cp_indir wouldn't have to reload it from memory each time.
Might also have the effect of spreading out the indirect mispredict
burden somewhat (across the multiple copies.)


Implementation notes
~~~~~~~~~~~~~~~~~~~~
T-chaining changes -- summary

* The code generators (host_blah_isel.c, host_blah_defs.[ch]) interact
  more closely with Valgrind than before.  In particular the
  instruction selectors must use one of 3 different kinds of
  control-transfer instructions: XDirect, XIndir and XAssisted.
  All archs must use these the same; no more ad-hoc control transfer
  instructions.
  (more detail below)


* With T-chaining, translations can jump between each other without
  going through the dispatcher loop every time.  This means that the
  event check (counter dec, and exit if negative) the dispatcher loop
  previously did now needs to be compiled into each translation.


* The assembly dispatcher code (dispatch-arch-os.S) is still
  present.  It still provides table lookup services for 
  indirect branches, but it also provides a new feature: 
  dispatch points, to which the generated code jumps.  There
  are 5:

  VG_(disp_cp_chain_me_to_slowEP):
  VG_(disp_cp_chain_me_to_fastEP):
    These are chain-me requests, used for Boring conditional and
    unconditional jumps to destinations known at JIT time.  The
    generated code calls these (doesn't jump to them) and the
    stub recovers the return address.  These calls never return;
    instead the call is done so that the stub knows where the
    calling point is.  It needs to know this so it can patch
    the calling point to the requested destination.
  VG_(disp_cp_xindir):
    Old-style table lookup and go; used for indirect jumps
  VG_(disp_cp_xassisted):
    Most general and slowest kind.  Can transfer to anywhere, but
    first returns to scheduler to do some other event (eg a syscall)
    before continuing.
  VG_(disp_cp_evcheck_fail):
    Code jumps here when the event check fails.


* new instructions in backends: XDirect, XIndir and XAssisted.
  XDirect is used for chainable jumps.  It is compiled into a
  call to VG_(disp_cp_chain_me_to_slowEP) or
  VG_(disp_cp_chain_me_to_fastEP).

  XIndir is used for indirect jumps.  It is compiled into a jump
  to VG_(disp_cp_xindir)

  XAssisted is used for "assisted" (do something first, then jump)
  transfers.  It is compiled into a jump to VG_(disp_cp_xassisted)

  All 3 of these may be conditional.

  More complexity: in some circumstances (no-redir translations)
  all transfers must be done with XAssisted.  In such cases the
  instruction selector will be told this.


* Patching: XDirect is compiled basically into
     %r11 = &VG_(disp_cp_chain_me_to_{slow,fast}EP)
     call *%r11
  Backends must provide a function (eg) chainXDirect_AMD64
  which converts it into a jump to a specified destination
     jmp $delta-of-PCs
  or
     %r11 = 64-bit immediate
     jmpq *%r11
  depending on branch distance.

  Backends must provide a function (eg) unchainXDirect_AMD64
  which restores the original call-to-the-stub version.


* Event checks.  Each translation now has two entry points,
  the slow one (slowEP) and fast one (fastEP).  Like this:

     slowEP:
        counter--
        if (counter < 0) goto VG_(disp_cp_evcheck_fail)
     fastEP:
        (rest of the translation)

  slowEP is used for control flow transfers that are or might be
  a back edge in the control flow graph.  Insn selectors are
  given the address of the highest guest byte in the block so
  they can determine which edges are definitely not back edges.

  The counter is placed in the first 8 bytes of the guest state,
  and the address of VG_(disp_cp_evcheck_fail) is placed in
  the next 8 bytes.  This allows very compact checks on all
  targets, since no immediates need to be synthesised, eg:

    decq 0(%baseblock-pointer)
    jns  fastEP
    jmpq *8(baseblock-pointer)
    fastEP:

  On amd64 a non-failing check is therefore 2 insns; all 3 occupy
  just 8 bytes.

  On amd64 the event check is created by a special single
  pseudo-instruction AMD64_EvCheck.


* BB profiling (for --profile-flags=).  The dispatch assembly
  dispatch-arch-os.S no longer deals with this and so is much
  simplified.  Instead the profile inc is compiled into each
  translation, as the insn immediately following the event
  check.  Again, on amd64 a pseudo-insn AMD64_ProfInc is used.
  Counters are now 64 bit even on 32 bit hosts, to avoid overflow.

  One complexity is that at JIT time it is not known where the
  address of the counter is.  To solve this, VexTranslateResult
  now returns the offset of the profile inc in the generated
  code.  When the counter address is known, VEX can be called
  again to patch it in.  Backends must supply eg
  patchProfInc_AMD64 to make this happen.


* Front end changes (guest_blah_toIR.c)

  The way the guest program counter is handled has changed
  significantly.  Previously, the guest PC was updated (in IR)
  at the start of each instruction, except for the first insn
  in an IRSB.  This is inconsistent and doesn't work with the
  new framework.

  Now, each instruction must update the guest PC as its last
  IR statement -- not its first.  And no special exemption for
  the first insn in the block.  As before most of these are
  optimised out by ir_opt, so no concerns about efficiency.

  As a logical side effect of this, exits (IRStmt_Exit) and the
  block-end transfer are both considered to write to the guest state
  (the guest PC) and so need to be told the offset of it.

  IR generators (eg disInstr_AMD64) are no longer allowed to set the
  IRSB::next, to specify the block-end transfer address.  Instead they
  now indicate, to the generic steering logic that drives them (iow,
  guest_generic_bb_to_IR.c), that the block has ended.  This then
  generates effectively "goto GET(PC)" (which, again, is optimised
  away).  What this does mean is that if the IR generator function
  ends the IR of the last instruction in the block with an incorrect
  assignment to the guest PC, execution will transfer to an incorrect
  destination -- making the error obvious quickly.
