Exemplo n.º 1
0
static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB )
{
   /* -------------------- ppc64 -------------------- */

#  if defined(VGA_ppc64)

#  define GOF(_fieldname) \
      (offsetof(VexGuestPPC64State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestPPC64State*)0)->guest_##_fieldname))

   Int  sz   = szB;
   Int  o    = offset;
   tl_assert(sz > 0);
   tl_assert(host_is_big_endian());

   if (sz == 8 || sz == 4) {
      /* The point of this is to achieve
         if ((o == GOF(GPRn) && sz == 8) || (o == 4+GOF(GPRn) && sz == 4))
            return GOF(GPRn);
         by testing ox instead of o, and setting ox back 4 bytes when sz == 4.
      */
      Int ox = sz == 8 ? o : (o - 4);
      if (ox == GOF(GPR0)) return ox;
      if (ox == GOF(GPR1)) return ox;
      if (ox == GOF(GPR2)) return ox;
      if (ox == GOF(GPR3)) return ox;
      if (ox == GOF(GPR4)) return ox;
      if (ox == GOF(GPR5)) return ox;
      if (ox == GOF(GPR6)) return ox;
      if (ox == GOF(GPR7)) return ox;
      if (ox == GOF(GPR8)) return ox;
      if (ox == GOF(GPR9)) return ox;
      if (ox == GOF(GPR10)) return ox;
      if (ox == GOF(GPR11)) return ox;
      if (ox == GOF(GPR12)) return ox;
      if (ox == GOF(GPR13)) return ox;
      if (ox == GOF(GPR14)) return ox;
      if (ox == GOF(GPR15)) return ox;
      if (ox == GOF(GPR16)) return ox;
      if (ox == GOF(GPR17)) return ox;
      if (ox == GOF(GPR18)) return ox;
      if (ox == GOF(GPR19)) return ox;
      if (ox == GOF(GPR20)) return ox;
      if (ox == GOF(GPR21)) return ox;
      if (ox == GOF(GPR22)) return ox;
      if (ox == GOF(GPR23)) return ox;
      if (ox == GOF(GPR24)) return ox;
      if (ox == GOF(GPR25)) return ox;
      if (ox == GOF(GPR26)) return ox;
      if (ox == GOF(GPR27)) return ox;
      if (ox == GOF(GPR28)) return ox;
      if (ox == GOF(GPR29)) return ox;
      if (ox == GOF(GPR30)) return ox;
      if (ox == GOF(GPR31)) return ox;
   }

   if (o == GOF(LR)  && sz == 8) return o;
   if (o == GOF(CTR) && sz == 8) return o;

   if (o == GOF(CIA)       && sz == 8) return -1;
   if (o == GOF(IP_AT_SYSCALL) && sz == 8) return -1; /* slot unused */
   if (o == GOF(FPROUND)   && sz == 4) return -1;
   if (o == GOF(EMWARN)    && sz == 4) return -1;
   if (o == GOF(TISTART)   && sz == 8) return -1;
   if (o == GOF(TILEN)     && sz == 8) return -1;
   if (o == GOF(VSCR)      && sz == 4) return -1;
   if (o == GOF(VRSAVE)    && sz == 4) return -1;
   if (o == GOF(REDIR_SP)  && sz == 8) return -1;

   tl_assert(SZB(FPR0) == 8);
   if (o == GOF(FPR0) && sz == 8) return o;
   if (o == GOF(FPR1) && sz == 8) return o;
   if (o == GOF(FPR2) && sz == 8) return o;
   if (o == GOF(FPR3) && sz == 8) return o;
   if (o == GOF(FPR4) && sz == 8) return o;
   if (o == GOF(FPR5) && sz == 8) return o;
   if (o == GOF(FPR6) && sz == 8) return o;
   if (o == GOF(FPR7) && sz == 8) return o;
   if (o == GOF(FPR8) && sz == 8) return o;
   if (o == GOF(FPR9) && sz == 8) return o;
   if (o == GOF(FPR10) && sz == 8) return o;
   if (o == GOF(FPR11) && sz == 8) return o;
   if (o == GOF(FPR12) && sz == 8) return o;
   if (o == GOF(FPR13) && sz == 8) return o;
   if (o == GOF(FPR14) && sz == 8) return o;
   if (o == GOF(FPR15) && sz == 8) return o;
   if (o == GOF(FPR16) && sz == 8) return o;
   if (o == GOF(FPR17) && sz == 8) return o;
   if (o == GOF(FPR18) && sz == 8) return o;
   if (o == GOF(FPR19) && sz == 8) return o;
   if (o == GOF(FPR20) && sz == 8) return o;
   if (o == GOF(FPR21) && sz == 8) return o;
   if (o == GOF(FPR22) && sz == 8) return o;
   if (o == GOF(FPR23) && sz == 8) return o;
   if (o == GOF(FPR24) && sz == 8) return o;
   if (o == GOF(FPR25) && sz == 8) return o;
   if (o == GOF(FPR26) && sz == 8) return o;
   if (o == GOF(FPR27) && sz == 8) return o;
   if (o == GOF(FPR28) && sz == 8) return o;
   if (o == GOF(FPR29) && sz == 8) return o;
   if (o == GOF(FPR30) && sz == 8) return o;
   if (o == GOF(FPR31) && sz == 8) return o;

   /* For the various byte sized XER/CR pieces, use offset 8
      in VR0 .. VR31. */
   tl_assert(SZB(VR0) == 16);
   if (o == GOF(XER_SO) && sz == 1) return 8 +GOF(VR0);
   if (o == GOF(XER_OV) && sz == 1) return 8 +GOF(VR1);
   if (o == GOF(XER_CA) && sz == 1) return 8 +GOF(VR2);
   if (o == GOF(XER_BC) && sz == 1) return 8 +GOF(VR3);

   if (o == GOF(CR0_321) && sz == 1) return 8 +GOF(VR4);
   if (o == GOF(CR0_0)   && sz == 1) return 8 +GOF(VR5);
   if (o == GOF(CR1_321) && sz == 1) return 8 +GOF(VR6);
   if (o == GOF(CR1_0)   && sz == 1) return 8 +GOF(VR7);
   if (o == GOF(CR2_321) && sz == 1) return 8 +GOF(VR8);
   if (o == GOF(CR2_0)   && sz == 1) return 8 +GOF(VR9);
   if (o == GOF(CR3_321) && sz == 1) return 8 +GOF(VR10);
   if (o == GOF(CR3_0)   && sz == 1) return 8 +GOF(VR11);
   if (o == GOF(CR4_321) && sz == 1) return 8 +GOF(VR12);
   if (o == GOF(CR4_0)   && sz == 1) return 8 +GOF(VR13);
   if (o == GOF(CR5_321) && sz == 1) return 8 +GOF(VR14);
   if (o == GOF(CR5_0)   && sz == 1) return 8 +GOF(VR15);
   if (o == GOF(CR6_321) && sz == 1) return 8 +GOF(VR16);
   if (o == GOF(CR6_0)   && sz == 1) return 8 +GOF(VR17);
   if (o == GOF(CR7_321) && sz == 1) return 8 +GOF(VR18);
   if (o == GOF(CR7_0)   && sz == 1) return 8 +GOF(VR19);

   /* Vector registers .. use offset 0 in VR0 .. VR31. */
   if (o >= GOF(VR0)  && o+sz <= GOF(VR0) +SZB(VR0))  return 0+ GOF(VR0);
   if (o >= GOF(VR1)  && o+sz <= GOF(VR1) +SZB(VR1))  return 0+ GOF(VR1);
   if (o >= GOF(VR2)  && o+sz <= GOF(VR2) +SZB(VR2))  return 0+ GOF(VR2);
   if (o >= GOF(VR3)  && o+sz <= GOF(VR3) +SZB(VR3))  return 0+ GOF(VR3);
   if (o >= GOF(VR4)  && o+sz <= GOF(VR4) +SZB(VR4))  return 0+ GOF(VR4);
   if (o >= GOF(VR5)  && o+sz <= GOF(VR5) +SZB(VR5))  return 0+ GOF(VR5);
   if (o >= GOF(VR6)  && o+sz <= GOF(VR6) +SZB(VR6))  return 0+ GOF(VR6);
   if (o >= GOF(VR7)  && o+sz <= GOF(VR7) +SZB(VR7))  return 0+ GOF(VR7);
   if (o >= GOF(VR8)  && o+sz <= GOF(VR8) +SZB(VR8))  return 0+ GOF(VR8);
   if (o >= GOF(VR9)  && o+sz <= GOF(VR9) +SZB(VR9))  return 0+ GOF(VR9);
   if (o >= GOF(VR10) && o+sz <= GOF(VR10)+SZB(VR10)) return 0+ GOF(VR10);
   if (o >= GOF(VR11) && o+sz <= GOF(VR11)+SZB(VR11)) return 0+ GOF(VR11);
   if (o >= GOF(VR12) && o+sz <= GOF(VR12)+SZB(VR12)) return 0+ GOF(VR12);
   if (o >= GOF(VR13) && o+sz <= GOF(VR13)+SZB(VR13)) return 0+ GOF(VR13);
   if (o >= GOF(VR14) && o+sz <= GOF(VR14)+SZB(VR14)) return 0+ GOF(VR14);
   if (o >= GOF(VR15) && o+sz <= GOF(VR15)+SZB(VR15)) return 0+ GOF(VR15);
   if (o >= GOF(VR16) && o+sz <= GOF(VR16)+SZB(VR16)) return 0+ GOF(VR16);
   if (o >= GOF(VR17) && o+sz <= GOF(VR17)+SZB(VR17)) return 0+ GOF(VR17);
   if (o >= GOF(VR18) && o+sz <= GOF(VR18)+SZB(VR18)) return 0+ GOF(VR18);
   if (o >= GOF(VR19) && o+sz <= GOF(VR19)+SZB(VR19)) return 0+ GOF(VR19);
   if (o >= GOF(VR20) && o+sz <= GOF(VR20)+SZB(VR20)) return 0+ GOF(VR20);
   if (o >= GOF(VR21) && o+sz <= GOF(VR21)+SZB(VR21)) return 0+ GOF(VR21);
   if (o >= GOF(VR22) && o+sz <= GOF(VR22)+SZB(VR22)) return 0+ GOF(VR22);
   if (o >= GOF(VR23) && o+sz <= GOF(VR23)+SZB(VR23)) return 0+ GOF(VR23);
   if (o >= GOF(VR24) && o+sz <= GOF(VR24)+SZB(VR24)) return 0+ GOF(VR24);
   if (o >= GOF(VR25) && o+sz <= GOF(VR25)+SZB(VR25)) return 0+ GOF(VR25);
   if (o >= GOF(VR26) && o+sz <= GOF(VR26)+SZB(VR26)) return 0+ GOF(VR26);
   if (o >= GOF(VR27) && o+sz <= GOF(VR27)+SZB(VR27)) return 0+ GOF(VR27);
   if (o >= GOF(VR28) && o+sz <= GOF(VR28)+SZB(VR28)) return 0+ GOF(VR28);
   if (o >= GOF(VR29) && o+sz <= GOF(VR29)+SZB(VR29)) return 0+ GOF(VR29);
   if (o >= GOF(VR30) && o+sz <= GOF(VR30)+SZB(VR30)) return 0+ GOF(VR30);
   if (o >= GOF(VR31) && o+sz <= GOF(VR31)+SZB(VR31)) return 0+ GOF(VR31);

   VG_(printf)("MC_(get_otrack_shadow_offset)(ppc64)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* -------------------- ppc32 -------------------- */

#  elif defined(VGA_ppc32)

#  define GOF(_fieldname) \
      (offsetof(VexGuestPPC32State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestPPC32State*)0)->guest_##_fieldname))
   Int  o  = offset;
   Int  sz = szB;
   tl_assert(sz > 0);
   tl_assert(host_is_big_endian());

   if (o == GOF(GPR0) && sz == 4) return o;
   if (o == GOF(GPR1) && sz == 4) return o;
   if (o == GOF(GPR2) && sz == 4) return o;
   if (o == GOF(GPR3) && sz == 4) return o;
   if (o == GOF(GPR4) && sz == 4) return o;
   if (o == GOF(GPR5) && sz == 4) return o;
   if (o == GOF(GPR6) && sz == 4) return o;
   if (o == GOF(GPR7) && sz == 4) return o;
   if (o == GOF(GPR8) && sz == 4) return o;
   if (o == GOF(GPR9) && sz == 4) return o;
   if (o == GOF(GPR10) && sz == 4) return o;
   if (o == GOF(GPR11) && sz == 4) return o;
   if (o == GOF(GPR12) && sz == 4) return o;
   if (o == GOF(GPR13) && sz == 4) return o;
   if (o == GOF(GPR14) && sz == 4) return o;
   if (o == GOF(GPR15) && sz == 4) return o;
   if (o == GOF(GPR16) && sz == 4) return o;
   if (o == GOF(GPR17) && sz == 4) return o;
   if (o == GOF(GPR18) && sz == 4) return o;
   if (o == GOF(GPR19) && sz == 4) return o;
   if (o == GOF(GPR20) && sz == 4) return o;
   if (o == GOF(GPR21) && sz == 4) return o;
   if (o == GOF(GPR22) && sz == 4) return o;
   if (o == GOF(GPR23) && sz == 4) return o;
   if (o == GOF(GPR24) && sz == 4) return o;
   if (o == GOF(GPR25) && sz == 4) return o;
   if (o == GOF(GPR26) && sz == 4) return o;
   if (o == GOF(GPR27) && sz == 4) return o;
   if (o == GOF(GPR28) && sz == 4) return o;
   if (o == GOF(GPR29) && sz == 4) return o;
   if (o == GOF(GPR30) && sz == 4) return o;
   if (o == GOF(GPR31) && sz == 4) return o;

   if (o == GOF(LR)  && sz == 4) return o;
   if (o == GOF(CTR) && sz == 4) return o;

   if (o == GOF(CIA)       && sz == 4) return -1;
   if (o == GOF(IP_AT_SYSCALL) && sz == 4) return -1; /* slot unused */
   if (o == GOF(FPROUND)   && sz == 4) return -1;
   if (o == GOF(VRSAVE)    && sz == 4) return -1;
   if (o == GOF(EMWARN)    && sz == 4) return -1;
   if (o == GOF(TISTART)   && sz == 4) return -1;
   if (o == GOF(TILEN)     && sz == 4) return -1;
   if (o == GOF(VSCR)      && sz == 4) return -1;
   if (o == GOF(REDIR_SP)  && sz == 4) return -1;
   if (o == GOF(SPRG3_RO)  && sz == 4) return -1;

   tl_assert(SZB(FPR0) == 8);
   if (o == GOF(FPR0) && sz == 8) return o;
   if (o == GOF(FPR1) && sz == 8) return o;
   if (o == GOF(FPR2) && sz == 8) return o;
   if (o == GOF(FPR3) && sz == 8) return o;
   if (o == GOF(FPR4) && sz == 8) return o;
   if (o == GOF(FPR5) && sz == 8) return o;
   if (o == GOF(FPR6) && sz == 8) return o;
   if (o == GOF(FPR7) && sz == 8) return o;
   if (o == GOF(FPR8) && sz == 8) return o;
   if (o == GOF(FPR9) && sz == 8) return o;
   if (o == GOF(FPR10) && sz == 8) return o;
   if (o == GOF(FPR11) && sz == 8) return o;
   if (o == GOF(FPR12) && sz == 8) return o;
   if (o == GOF(FPR13) && sz == 8) return o;
   if (o == GOF(FPR14) && sz == 8) return o;
   if (o == GOF(FPR15) && sz == 8) return o;
   if (o == GOF(FPR16) && sz == 8) return o;
   if (o == GOF(FPR17) && sz == 8) return o;
   if (o == GOF(FPR18) && sz == 8) return o;
   if (o == GOF(FPR19) && sz == 8) return o;
   if (o == GOF(FPR20) && sz == 8) return o;
   if (o == GOF(FPR21) && sz == 8) return o;
   if (o == GOF(FPR22) && sz == 8) return o;
   if (o == GOF(FPR23) && sz == 8) return o;
   if (o == GOF(FPR24) && sz == 8) return o;
   if (o == GOF(FPR25) && sz == 8) return o;
   if (o == GOF(FPR26) && sz == 8) return o;
   if (o == GOF(FPR27) && sz == 8) return o;
   if (o == GOF(FPR28) && sz == 8) return o;
   if (o == GOF(FPR29) && sz == 8) return o;
   if (o == GOF(FPR30) && sz == 8) return o;
   if (o == GOF(FPR31) && sz == 8) return o;

   /* For the various byte sized XER/CR pieces, use offset 8
      in VR0 .. VR31. */
   tl_assert(SZB(VR0) == 16);
   if (o == GOF(XER_SO) && sz == 1) return 8 +GOF(VR0);
   if (o == GOF(XER_OV) && sz == 1) return 8 +GOF(VR1);
   if (o == GOF(XER_CA) && sz == 1) return 8 +GOF(VR2);
   if (o == GOF(XER_BC) && sz == 1) return 8 +GOF(VR3);

   if (o == GOF(CR0_321) && sz == 1) return 8 +GOF(VR4);
   if (o == GOF(CR0_0)   && sz == 1) return 8 +GOF(VR5);
   if (o == GOF(CR1_321) && sz == 1) return 8 +GOF(VR6);
   if (o == GOF(CR1_0)   && sz == 1) return 8 +GOF(VR7);
   if (o == GOF(CR2_321) && sz == 1) return 8 +GOF(VR8);
   if (o == GOF(CR2_0)   && sz == 1) return 8 +GOF(VR9);
   if (o == GOF(CR3_321) && sz == 1) return 8 +GOF(VR10);
   if (o == GOF(CR3_0)   && sz == 1) return 8 +GOF(VR11);
   if (o == GOF(CR4_321) && sz == 1) return 8 +GOF(VR12);
   if (o == GOF(CR4_0)   && sz == 1) return 8 +GOF(VR13);
   if (o == GOF(CR5_321) && sz == 1) return 8 +GOF(VR14);
   if (o == GOF(CR5_0)   && sz == 1) return 8 +GOF(VR15);
   if (o == GOF(CR6_321) && sz == 1) return 8 +GOF(VR16);
   if (o == GOF(CR6_0)   && sz == 1) return 8 +GOF(VR17);
   if (o == GOF(CR7_321) && sz == 1) return 8 +GOF(VR18);
   if (o == GOF(CR7_0)   && sz == 1) return 8 +GOF(VR19);

   /* Vector registers .. use offset 0 in VR0 .. VR31. */
   if (o >= GOF(VR0)  && o+sz <= GOF(VR0) +SZB(VR0))  return 0+ GOF(VR0);
   if (o >= GOF(VR1)  && o+sz <= GOF(VR1) +SZB(VR1))  return 0+ GOF(VR1);
   if (o >= GOF(VR2)  && o+sz <= GOF(VR2) +SZB(VR2))  return 0+ GOF(VR2);
   if (o >= GOF(VR3)  && o+sz <= GOF(VR3) +SZB(VR3))  return 0+ GOF(VR3);
   if (o >= GOF(VR4)  && o+sz <= GOF(VR4) +SZB(VR4))  return 0+ GOF(VR4);
   if (o >= GOF(VR5)  && o+sz <= GOF(VR5) +SZB(VR5))  return 0+ GOF(VR5);
   if (o >= GOF(VR6)  && o+sz <= GOF(VR6) +SZB(VR6))  return 0+ GOF(VR6);
   if (o >= GOF(VR7)  && o+sz <= GOF(VR7) +SZB(VR7))  return 0+ GOF(VR7);
   if (o >= GOF(VR8)  && o+sz <= GOF(VR8) +SZB(VR8))  return 0+ GOF(VR8);
   if (o >= GOF(VR9)  && o+sz <= GOF(VR9) +SZB(VR9))  return 0+ GOF(VR9);
   if (o >= GOF(VR10) && o+sz <= GOF(VR10)+SZB(VR10)) return 0+ GOF(VR10);
   if (o >= GOF(VR11) && o+sz <= GOF(VR11)+SZB(VR11)) return 0+ GOF(VR11);
   if (o >= GOF(VR12) && o+sz <= GOF(VR12)+SZB(VR12)) return 0+ GOF(VR12);
   if (o >= GOF(VR13) && o+sz <= GOF(VR13)+SZB(VR13)) return 0+ GOF(VR13);
   if (o >= GOF(VR14) && o+sz <= GOF(VR14)+SZB(VR14)) return 0+ GOF(VR14);
   if (o >= GOF(VR15) && o+sz <= GOF(VR15)+SZB(VR15)) return 0+ GOF(VR15);
   if (o >= GOF(VR16) && o+sz <= GOF(VR16)+SZB(VR16)) return 0+ GOF(VR16);
   if (o >= GOF(VR17) && o+sz <= GOF(VR17)+SZB(VR17)) return 0+ GOF(VR17);
   if (o >= GOF(VR18) && o+sz <= GOF(VR18)+SZB(VR18)) return 0+ GOF(VR18);
   if (o >= GOF(VR19) && o+sz <= GOF(VR19)+SZB(VR19)) return 0+ GOF(VR19);
   if (o >= GOF(VR20) && o+sz <= GOF(VR20)+SZB(VR20)) return 0+ GOF(VR20);
   if (o >= GOF(VR21) && o+sz <= GOF(VR21)+SZB(VR21)) return 0+ GOF(VR21);
   if (o >= GOF(VR22) && o+sz <= GOF(VR22)+SZB(VR22)) return 0+ GOF(VR22);
   if (o >= GOF(VR23) && o+sz <= GOF(VR23)+SZB(VR23)) return 0+ GOF(VR23);
   if (o >= GOF(VR24) && o+sz <= GOF(VR24)+SZB(VR24)) return 0+ GOF(VR24);
   if (o >= GOF(VR25) && o+sz <= GOF(VR25)+SZB(VR25)) return 0+ GOF(VR25);
   if (o >= GOF(VR26) && o+sz <= GOF(VR26)+SZB(VR26)) return 0+ GOF(VR26);
   if (o >= GOF(VR27) && o+sz <= GOF(VR27)+SZB(VR27)) return 0+ GOF(VR27);
   if (o >= GOF(VR28) && o+sz <= GOF(VR28)+SZB(VR28)) return 0+ GOF(VR28);
   if (o >= GOF(VR29) && o+sz <= GOF(VR29)+SZB(VR29)) return 0+ GOF(VR29);
   if (o >= GOF(VR30) && o+sz <= GOF(VR30)+SZB(VR30)) return 0+ GOF(VR30);
   if (o >= GOF(VR31) && o+sz <= GOF(VR31)+SZB(VR31)) return 0+ GOF(VR31);

   VG_(printf)("MC_(get_otrack_shadow_offset)(ppc32)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* -------------------- amd64 -------------------- */

#  elif defined(VGA_amd64)

#  define GOF(_fieldname) \
      (offsetof(VexGuestAMD64State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestAMD64State*)0)->guest_##_fieldname))
   Int  o      = offset;
   Int  sz     = szB;
   Bool is1248 = sz == 8 || sz == 4 || sz == 2 || sz == 1;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(RAX) && is1248) return o;
   if (o == GOF(RCX) && is1248) return o;
   if (o == GOF(RDX) && is1248) return o;
   if (o == GOF(RBX) && is1248) return o;
   if (o == GOF(RSP) && is1248) return o;
   if (o == GOF(RBP) && is1248) return o;
   if (o == GOF(RSI) && is1248) return o;
   if (o == GOF(RDI) && is1248) return o;
   if (o == GOF(R8)  && is1248) return o;
   if (o == GOF(R9)  && is1248) return o;
   if (o == GOF(R10) && is1248) return o;
   if (o == GOF(R11) && is1248) return o;
   if (o == GOF(R12) && is1248) return o;
   if (o == GOF(R13) && is1248) return o;
   if (o == GOF(R14) && is1248) return o;
   if (o == GOF(R15) && is1248) return o;

   if (o == GOF(CC_DEP1) && sz == 8) return o;
   if (o == GOF(CC_DEP2) && sz == 8) return o;

   if (o == GOF(CC_OP)   && sz == 8) return -1; /* slot used for %AH */
   if (o == GOF(CC_NDEP) && sz == 8) return -1; /* slot used for %BH */
   if (o == GOF(DFLAG)   && sz == 8) return -1; /* slot used for %CH */
   if (o == GOF(RIP)     && sz == 8) return -1; /* slot unused */
   if (o == GOF(IP_AT_SYSCALL) && sz == 8) return -1; /* slot unused */
   if (o == GOF(IDFLAG)  && sz == 8) return -1; /* slot used for %DH */
   if (o == GOF(FS_ZERO) && sz == 8) return -1; /* slot unused */
   if (o == GOF(GS_0x60) && sz == 8) return -1; /* slot unused */
   if (o == GOF(TISTART) && sz == 8) return -1; /* slot unused */
   if (o == GOF(TILEN)   && sz == 8) return -1; /* slot unused */

   /* Treat %AH, %BH, %CH, %DH as independent registers.  To do this
      requires finding 4 unused 32-bit slots in the second-shadow
      guest state, respectively: CC_OP CC_NDEP DFLAG IDFLAG, since
      none of those are tracked. */
   tl_assert(SZB(CC_OP)   == 8);
   tl_assert(SZB(CC_NDEP) == 8);
   tl_assert(SZB(IDFLAG)  == 8);
   tl_assert(SZB(DFLAG)   == 8);

   if (o == 1+ GOF(RAX) && szB == 1) return GOF(CC_OP);
   if (o == 1+ GOF(RBX) && szB == 1) return GOF(CC_NDEP);
   if (o == 1+ GOF(RCX) && szB == 1) return GOF(DFLAG);
   if (o == 1+ GOF(RDX) && szB == 1) return GOF(IDFLAG);

   /* skip XMM and FP admin stuff */
   if (o == GOF(SSEROUND) && szB == 8) return -1;
   if (o == GOF(FTOP)     && szB == 4) return -1;
   if (o == GOF(FPROUND)  && szB == 8) return -1;
   if (o == GOF(EMWARN)   && szB == 4) return -1;
   if (o == GOF(FC3210)   && szB == 8) return -1;

   /* XMM registers */
   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0) +SZB(XMM0))  return GOF(XMM0);
   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1) +SZB(XMM1))  return GOF(XMM1);
   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2) +SZB(XMM2))  return GOF(XMM2);
   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3) +SZB(XMM3))  return GOF(XMM3);
   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4) +SZB(XMM4))  return GOF(XMM4);
   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5) +SZB(XMM5))  return GOF(XMM5);
   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6) +SZB(XMM6))  return GOF(XMM6);
   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7) +SZB(XMM7))  return GOF(XMM7);
   if (o >= GOF(XMM8)  && o+sz <= GOF(XMM8) +SZB(XMM8))  return GOF(XMM8);
   if (o >= GOF(XMM9)  && o+sz <= GOF(XMM9) +SZB(XMM9))  return GOF(XMM9);
   if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+SZB(XMM10)) return GOF(XMM10);
   if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+SZB(XMM11)) return GOF(XMM11);
   if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+SZB(XMM12)) return GOF(XMM12);
   if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+SZB(XMM13)) return GOF(XMM13);
   if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+SZB(XMM14)) return GOF(XMM14);
   if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+SZB(XMM15)) return GOF(XMM15);
   if (o >= GOF(XMM16) && o+sz <= GOF(XMM16)+SZB(XMM16)) return GOF(XMM16);

   /* MMX accesses to FP regs.  Need to allow for 32-bit references
      due to dirty helpers for frstor etc, which reference the entire
      64-byte block in one go. */
   if (o >= GOF(FPREG[0])
       && o+sz <= GOF(FPREG[0])+SZB(FPREG[0])) return GOF(FPREG[0]);
   if (o >= GOF(FPREG[1])
       && o+sz <= GOF(FPREG[1])+SZB(FPREG[1])) return GOF(FPREG[1]);
   if (o >= GOF(FPREG[2])
       && o+sz <= GOF(FPREG[2])+SZB(FPREG[2])) return GOF(FPREG[2]);
   if (o >= GOF(FPREG[3])
       && o+sz <= GOF(FPREG[3])+SZB(FPREG[3])) return GOF(FPREG[3]);
   if (o >= GOF(FPREG[4])
       && o+sz <= GOF(FPREG[4])+SZB(FPREG[4])) return GOF(FPREG[4]);
   if (o >= GOF(FPREG[5])
       && o+sz <= GOF(FPREG[5])+SZB(FPREG[5])) return GOF(FPREG[5]);
   if (o >= GOF(FPREG[6])
       && o+sz <= GOF(FPREG[6])+SZB(FPREG[6])) return GOF(FPREG[6]);
   if (o >= GOF(FPREG[7])
       && o+sz <= GOF(FPREG[7])+SZB(FPREG[7])) return GOF(FPREG[7]);

   /* Map high halves of %RAX,%RCX,%RDX,%RBX to the whole register.
      This is needed because the general handling of dirty helper
      calls is done in 4 byte chunks.  Hence we will see these.
      Currently we only expect to see artefacts from CPUID. */
   if (o == 4+ GOF(RAX) && sz == 4) return GOF(RAX);
   if (o == 4+ GOF(RCX) && sz == 4) return GOF(RCX);
   if (o == 4+ GOF(RDX) && sz == 4) return GOF(RDX);
   if (o == 4+ GOF(RBX) && sz == 4) return GOF(RBX);

   VG_(printf)("MC_(get_otrack_shadow_offset)(amd64)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* --------------------- x86 --------------------- */

#  elif defined(VGA_x86)

#  define GOF(_fieldname) \
      (offsetof(VexGuestX86State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestX86State*)0)->guest_##_fieldname))

   Int  o     = offset;
   Int  sz    = szB;
   Bool is124 = sz == 4 || sz == 2 || sz == 1;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(EAX) && is124) return o;
   if (o == GOF(ECX) && is124) return o;
   if (o == GOF(EDX) && is124) return o;
   if (o == GOF(EBX) && is124) return o;
   if (o == GOF(ESP) && is124) return o;
   if (o == GOF(EBP) && is124) return o;
   if (o == GOF(ESI) && is124) return o;
   if (o == GOF(EDI) && is124) return o;

   if (o == GOF(CC_DEP1) && sz == 4) return o;
   if (o == GOF(CC_DEP2) && sz == 4) return o;

   if (o == GOF(CC_OP)   && sz == 4) return -1; /* slot used for %AH */
   if (o == GOF(CC_NDEP) && sz == 4) return -1; /* slot used for %BH */
   if (o == GOF(DFLAG)   && sz == 4) return -1; /* slot used for %CH */
   if (o == GOF(EIP)     && sz == 4) return -1; /* slot unused */
   if (o == GOF(IP_AT_SYSCALL) && sz == 4) return -1; /* slot unused */
   if (o == GOF(IDFLAG)  && sz == 4) return -1; /* slot used for %DH */
   if (o == GOF(ACFLAG)  && sz == 4) return -1; /* slot unused */
   if (o == GOF(TISTART) && sz == 4) return -1; /* slot unused */
   if (o == GOF(TILEN)   && sz == 4) return -1; /* slot unused */

   /* Treat %AH, %BH, %CH, %DH as independent registers.  To do this
      requires finding 4 unused 32-bit slots in the second-shadow
      guest state, respectively: CC_OP CC_NDEP DFLAG IDFLAG since none
      of those are tracked. */
   tl_assert(SZB(CC_OP)   == 4);
   tl_assert(SZB(CC_NDEP) == 4);
   tl_assert(SZB(DFLAG)   == 4);
   tl_assert(SZB(IDFLAG)  == 4);
   if (o == 1+ GOF(EAX) && szB == 1) return GOF(CC_OP);
   if (o == 1+ GOF(EBX) && szB == 1) return GOF(CC_NDEP);
   if (o == 1+ GOF(ECX) && szB == 1) return GOF(DFLAG);
   if (o == 1+ GOF(EDX) && szB == 1) return GOF(IDFLAG);

   /* skip XMM and FP admin stuff */
   if (o == GOF(SSEROUND) && szB == 4) return -1;
   if (o == GOF(FTOP)     && szB == 4) return -1;
   if (o == GOF(FPROUND)  && szB == 4) return -1;
   if (o == GOF(EMWARN)   && szB == 4) return -1;
   if (o == GOF(FC3210)   && szB == 4) return -1;

   /* XMM registers */
   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0)+SZB(XMM0)) return GOF(XMM0);
   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1)+SZB(XMM1)) return GOF(XMM1);
   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2)+SZB(XMM2)) return GOF(XMM2);
   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3)+SZB(XMM3)) return GOF(XMM3);
   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4)+SZB(XMM4)) return GOF(XMM4);
   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5)+SZB(XMM5)) return GOF(XMM5);
   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6)+SZB(XMM6)) return GOF(XMM6);
   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7)+SZB(XMM7)) return GOF(XMM7);

   /* MMX accesses to FP regs.  Need to allow for 32-bit references
      due to dirty helpers for frstor etc, which reference the entire
      64-byte block in one go. */
   if (o >= GOF(FPREG[0])
       && o+sz <= GOF(FPREG[0])+SZB(FPREG[0])) return GOF(FPREG[0]);
   if (o >= GOF(FPREG[1])
       && o+sz <= GOF(FPREG[1])+SZB(FPREG[1])) return GOF(FPREG[1]);
   if (o >= GOF(FPREG[2])
       && o+sz <= GOF(FPREG[2])+SZB(FPREG[2])) return GOF(FPREG[2]);
   if (o >= GOF(FPREG[3])
       && o+sz <= GOF(FPREG[3])+SZB(FPREG[3])) return GOF(FPREG[3]);
   if (o >= GOF(FPREG[4])
       && o+sz <= GOF(FPREG[4])+SZB(FPREG[4])) return GOF(FPREG[4]);
   if (o >= GOF(FPREG[5])
       && o+sz <= GOF(FPREG[5])+SZB(FPREG[5])) return GOF(FPREG[5]);
   if (o >= GOF(FPREG[6])
       && o+sz <= GOF(FPREG[6])+SZB(FPREG[6])) return GOF(FPREG[6]);
   if (o >= GOF(FPREG[7])
       && o+sz <= GOF(FPREG[7])+SZB(FPREG[7])) return GOF(FPREG[7]);

   /* skip %GS and other segment related stuff.  We could shadow
      guest_LDT and guest_GDT, although it seems pointless.
      guest_CS .. guest_SS are too small to shadow directly and it
      also seems pointless to shadow them indirectly (that is, in 
      the style of %AH .. %DH). */
   if (o == GOF(CS) && sz == 2) return -1;
   if (o == GOF(DS) && sz == 2) return -1;
   if (o == GOF(ES) && sz == 2) return -1;
   if (o == GOF(FS) && sz == 2) return -1;
   if (o == GOF(GS) && sz == 2) return -1;
   if (o == GOF(SS) && sz == 2) return -1;
   if (o == GOF(LDT) && sz == 4) return -1;
   if (o == GOF(GDT) && sz == 4) return -1;

   VG_(printf)("MC_(get_otrack_shadow_offset)(x86)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* --------------------- arm --------------------- */

#  elif defined(VGA_arm)

#  define GOF(_fieldname) \
      (offsetof(VexGuestARMState,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestARMState*)0)->guest_##_fieldname))

   Int  o     = offset;
   Int  sz    = szB;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(R0)  && sz == 4) return o;
   if (o == GOF(R1)  && sz == 4) return o;
   if (o == GOF(R2)  && sz == 4) return o;
   if (o == GOF(R3)  && sz == 4) return o;
   if (o == GOF(R4)  && sz == 4) return o;
   if (o == GOF(R5)  && sz == 4) return o;
   if (o == GOF(R6)  && sz == 4) return o;
   if (o == GOF(R7)  && sz == 4) return o;
   if (o == GOF(R8)  && sz == 4) return o;
   if (o == GOF(R9)  && sz == 4) return o;
   if (o == GOF(R10) && sz == 4) return o;
   if (o == GOF(R11) && sz == 4) return o;
   if (o == GOF(R12) && sz == 4) return o;
   if (o == GOF(R13) && sz == 4) return o;
   if (o == GOF(R14) && sz == 4) return o;

   /* EAZG: These may be completely wrong. */
   if (o == GOF(R15)   && sz == 4) return -1; /* slot unused */
   if (o == GOF(CC_OP) && sz == 4) return -1; /* slot unused */

   if (o == GOF(CC_DEP1) && sz == 4) return o;
   if (o == GOF(CC_DEP2) && sz == 4) return o;

   if (o == GOF(CC_NDEP) && sz == 4) return -1; /* slot unused */

   //if (o == GOF(SYSCALLNO)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(CC)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(EMWARN)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(TISTART)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(NRADDR)     && sz == 4) return -1; /* slot unused */

   if (o == GOF(FPSCR)    && sz == 4) return -1;
   if (o == GOF(TPIDRURO) && sz == 4) return -1;

   if (o >= GOF(D0)  && o+sz <= GOF(D0) +SZB(D0))  return GOF(D0);
   if (o >= GOF(D1)  && o+sz <= GOF(D1) +SZB(D1))  return GOF(D1);
   if (o >= GOF(D2)  && o+sz <= GOF(D2) +SZB(D2))  return GOF(D2);
   if (o >= GOF(D3)  && o+sz <= GOF(D3) +SZB(D3))  return GOF(D3);
   if (o >= GOF(D4)  && o+sz <= GOF(D4) +SZB(D4))  return GOF(D4);
   if (o >= GOF(D5)  && o+sz <= GOF(D5) +SZB(D5))  return GOF(D5);
   if (o >= GOF(D6)  && o+sz <= GOF(D6) +SZB(D6))  return GOF(D6);
   if (o >= GOF(D7)  && o+sz <= GOF(D7) +SZB(D7))  return GOF(D7);
   if (o >= GOF(D8)  && o+sz <= GOF(D8) +SZB(D8))  return GOF(D8);
   if (o >= GOF(D9)  && o+sz <= GOF(D9) +SZB(D9))  return GOF(D9);
   if (o >= GOF(D10) && o+sz <= GOF(D10)+SZB(D10)) return GOF(D10);
   if (o >= GOF(D11) && o+sz <= GOF(D11)+SZB(D11)) return GOF(D11);
   if (o >= GOF(D12) && o+sz <= GOF(D12)+SZB(D12)) return GOF(D12);
   if (o >= GOF(D13) && o+sz <= GOF(D13)+SZB(D13)) return GOF(D13);
   if (o >= GOF(D14) && o+sz <= GOF(D14)+SZB(D14)) return GOF(D14);
   if (o >= GOF(D15) && o+sz <= GOF(D15)+SZB(D15)) return GOF(D15);

   VG_(printf)("MC_(get_otrack_shadow_offset)(arm)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

#  else
#    error "FIXME: not implemented for this architecture"
#  endif
}
Exemplo n.º 2
0
static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB )
{
   /* -------------------- ppc64 -------------------- */

#  if defined(VGA_ppc64)

#  define GOF(_fieldname) \
      (offsetof(VexGuestPPC64State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestPPC64State*)0)->guest_##_fieldname))

   Int  sz   = szB;
   Int  o    = offset;
   tl_assert(sz > 0);
   tl_assert(host_is_big_endian());

   if (sz == 8 || sz == 4) {
      /* The point of this is to achieve
         if ((o == GOF(GPRn) && sz == 8) || (o == 4+GOF(GPRn) && sz == 4))
            return GOF(GPRn);
         by testing ox instead of o, and setting ox back 4 bytes when sz == 4.
      */
      Int ox = sz == 8 ? o : (o - 4);
      if (ox == GOF(GPR0)) return ox;
      if (ox == GOF(GPR1)) return ox;
      if (ox == GOF(GPR2)) return ox;
      if (ox == GOF(GPR3)) return ox;
      if (ox == GOF(GPR4)) return ox;
      if (ox == GOF(GPR5)) return ox;
      if (ox == GOF(GPR6)) return ox;
      if (ox == GOF(GPR7)) return ox;
      if (ox == GOF(GPR8)) return ox;
      if (ox == GOF(GPR9)) return ox;
      if (ox == GOF(GPR10)) return ox;
      if (ox == GOF(GPR11)) return ox;
      if (ox == GOF(GPR12)) return ox;
      if (ox == GOF(GPR13)) return ox;
      if (ox == GOF(GPR14)) return ox;
      if (ox == GOF(GPR15)) return ox;
      if (ox == GOF(GPR16)) return ox;
      if (ox == GOF(GPR17)) return ox;
      if (ox == GOF(GPR18)) return ox;
      if (ox == GOF(GPR19)) return ox;
      if (ox == GOF(GPR20)) return ox;
      if (ox == GOF(GPR21)) return ox;
      if (ox == GOF(GPR22)) return ox;
      if (ox == GOF(GPR23)) return ox;
      if (ox == GOF(GPR24)) return ox;
      if (ox == GOF(GPR25)) return ox;
      if (ox == GOF(GPR26)) return ox;
      if (ox == GOF(GPR27)) return ox;
      if (ox == GOF(GPR28)) return ox;
      if (ox == GOF(GPR29)) return ox;
      if (ox == GOF(GPR30)) return ox;
      if (ox == GOF(GPR31)) return ox;
   }

   if (o == GOF(LR)  && sz == 8) return o;
   if (o == GOF(CTR) && sz == 8) return o;

   if (o == GOF(CIA)       && sz == 8) return -1;
   if (o == GOF(IP_AT_SYSCALL) && sz == 8) return -1; /* slot unused */
   if (o == GOF(FPROUND)   && sz == 4) return -1;
   if (o == GOF(EMWARN)    && sz == 4) return -1;
   if (o == GOF(TISTART)   && sz == 8) return -1;
   if (o == GOF(TILEN)     && sz == 8) return -1;
   if (o == GOF(VSCR)      && sz == 4) return -1;
   if (o == GOF(VRSAVE)    && sz == 4) return -1;
   if (o == GOF(REDIR_SP)  && sz == 8) return -1;

   // With ISA 2.06, the "Vector-Scalar Floating-point" category
   // provides facilities to support vector and scalar binary floating-
   // point operations.  A unified register file is an integral part
   // of this new facility, combining floating point and vector registers
   // using a 64x128-bit vector.  These are referred to as VSR[0..63].
   // The floating point registers are now mapped into double word element 0
   // of VSR[0..31]. The 32x128-bit vector registers defined by the "Vector
   // Facility [Category: Vector]" are now mapped to VSR[32..63].

   //  Floating point registers . . .
   if (o == GOF(VSR0) && sz == 8) return o;
   if (o == GOF(VSR1) && sz == 8) return o;
   if (o == GOF(VSR2) && sz == 8) return o;
   if (o == GOF(VSR3) && sz == 8) return o;
   if (o == GOF(VSR4) && sz == 8) return o;
   if (o == GOF(VSR5) && sz == 8) return o;
   if (o == GOF(VSR6) && sz == 8) return o;
   if (o == GOF(VSR7) && sz == 8) return o;
   if (o == GOF(VSR8) && sz == 8) return o;
   if (o == GOF(VSR9) && sz == 8) return o;
   if (o == GOF(VSR10) && sz == 8) return o;
   if (o == GOF(VSR11) && sz == 8) return o;
   if (o == GOF(VSR12) && sz == 8) return o;
   if (o == GOF(VSR13) && sz == 8) return o;
   if (o == GOF(VSR14) && sz == 8) return o;
   if (o == GOF(VSR15) && sz == 8) return o;
   if (o == GOF(VSR16) && sz == 8) return o;
   if (o == GOF(VSR17) && sz == 8) return o;
   if (o == GOF(VSR18) && sz == 8) return o;
   if (o == GOF(VSR19) && sz == 8) return o;
   if (o == GOF(VSR20) && sz == 8) return o;
   if (o == GOF(VSR21) && sz == 8) return o;
   if (o == GOF(VSR22) && sz == 8) return o;
   if (o == GOF(VSR23) && sz == 8) return o;
   if (o == GOF(VSR24) && sz == 8) return o;
   if (o == GOF(VSR25) && sz == 8) return o;
   if (o == GOF(VSR26) && sz == 8) return o;
   if (o == GOF(VSR27) && sz == 8) return o;
   if (o == GOF(VSR28) && sz == 8) return o;
   if (o == GOF(VSR29) && sz == 8) return o;
   if (o == GOF(VSR30) && sz == 8) return o;
   if (o == GOF(VSR31) && sz == 8) return o;

   /* For the various byte sized XER/CR pieces, use offset 8
      in VSR0 .. VSR19. */
   tl_assert(SZB(VSR0) == 16);
   if (o == GOF(XER_SO) && sz == 1) return 8 +GOF(VSR0);
   if (o == GOF(XER_OV) && sz == 1) return 8 +GOF(VSR1);
   if (o == GOF(XER_CA) && sz == 1) return 8 +GOF(VSR2);
   if (o == GOF(XER_BC) && sz == 1) return 8 +GOF(VSR3);

   if (o == GOF(CR0_321) && sz == 1) return 8 +GOF(VSR4);
   if (o == GOF(CR0_0)   && sz == 1) return 8 +GOF(VSR5);
   if (o == GOF(CR1_321) && sz == 1) return 8 +GOF(VSR6);
   if (o == GOF(CR1_0)   && sz == 1) return 8 +GOF(VSR7);
   if (o == GOF(CR2_321) && sz == 1) return 8 +GOF(VSR8);
   if (o == GOF(CR2_0)   && sz == 1) return 8 +GOF(VSR9);
   if (o == GOF(CR3_321) && sz == 1) return 8 +GOF(VSR10);
   if (o == GOF(CR3_0)   && sz == 1) return 8 +GOF(VSR11);
   if (o == GOF(CR4_321) && sz == 1) return 8 +GOF(VSR12);
   if (o == GOF(CR4_0)   && sz == 1) return 8 +GOF(VSR13);
   if (o == GOF(CR5_321) && sz == 1) return 8 +GOF(VSR14);
   if (o == GOF(CR5_0)   && sz == 1) return 8 +GOF(VSR15);
   if (o == GOF(CR6_321) && sz == 1) return 8 +GOF(VSR16);
   if (o == GOF(CR6_0)   && sz == 1) return 8 +GOF(VSR17);
   if (o == GOF(CR7_321) && sz == 1) return 8 +GOF(VSR18);
   if (o == GOF(CR7_0)   && sz == 1) return 8 +GOF(VSR19);

   /* Vector registers .. use offset 0 in VSR0 .. VSR63. */
   if (o >= GOF(VSR0)  && o+sz <= GOF(VSR0) +SZB(VSR0))  return 0+ GOF(VSR0);
   if (o >= GOF(VSR1)  && o+sz <= GOF(VSR1) +SZB(VSR1))  return 0+ GOF(VSR1);
   if (o >= GOF(VSR2)  && o+sz <= GOF(VSR2) +SZB(VSR2))  return 0+ GOF(VSR2);
   if (o >= GOF(VSR3)  && o+sz <= GOF(VSR3) +SZB(VSR3))  return 0+ GOF(VSR3);
   if (o >= GOF(VSR4)  && o+sz <= GOF(VSR4) +SZB(VSR4))  return 0+ GOF(VSR4);
   if (o >= GOF(VSR5)  && o+sz <= GOF(VSR5) +SZB(VSR5))  return 0+ GOF(VSR5);
   if (o >= GOF(VSR6)  && o+sz <= GOF(VSR6) +SZB(VSR6))  return 0+ GOF(VSR6);
   if (o >= GOF(VSR7)  && o+sz <= GOF(VSR7) +SZB(VSR7))  return 0+ GOF(VSR7);
   if (o >= GOF(VSR8)  && o+sz <= GOF(VSR8) +SZB(VSR8))  return 0+ GOF(VSR8);
   if (o >= GOF(VSR9)  && o+sz <= GOF(VSR9) +SZB(VSR9))  return 0+ GOF(VSR9);
   if (o >= GOF(VSR10) && o+sz <= GOF(VSR10)+SZB(VSR10)) return 0+ GOF(VSR10);
   if (o >= GOF(VSR11) && o+sz <= GOF(VSR11)+SZB(VSR11)) return 0+ GOF(VSR11);
   if (o >= GOF(VSR12) && o+sz <= GOF(VSR12)+SZB(VSR12)) return 0+ GOF(VSR12);
   if (o >= GOF(VSR13) && o+sz <= GOF(VSR13)+SZB(VSR13)) return 0+ GOF(VSR13);
   if (o >= GOF(VSR14) && o+sz <= GOF(VSR14)+SZB(VSR14)) return 0+ GOF(VSR14);
   if (o >= GOF(VSR15) && o+sz <= GOF(VSR15)+SZB(VSR15)) return 0+ GOF(VSR15);
   if (o >= GOF(VSR16) && o+sz <= GOF(VSR16)+SZB(VSR16)) return 0+ GOF(VSR16);
   if (o >= GOF(VSR17) && o+sz <= GOF(VSR17)+SZB(VSR17)) return 0+ GOF(VSR17);
   if (o >= GOF(VSR18) && o+sz <= GOF(VSR18)+SZB(VSR18)) return 0+ GOF(VSR18);
   if (o >= GOF(VSR19) && o+sz <= GOF(VSR19)+SZB(VSR19)) return 0+ GOF(VSR19);
   if (o >= GOF(VSR20) && o+sz <= GOF(VSR20)+SZB(VSR20)) return 0+ GOF(VSR20);
   if (o >= GOF(VSR21) && o+sz <= GOF(VSR21)+SZB(VSR21)) return 0+ GOF(VSR21);
   if (o >= GOF(VSR22) && o+sz <= GOF(VSR22)+SZB(VSR22)) return 0+ GOF(VSR22);
   if (o >= GOF(VSR23) && o+sz <= GOF(VSR23)+SZB(VSR23)) return 0+ GOF(VSR23);
   if (o >= GOF(VSR24) && o+sz <= GOF(VSR24)+SZB(VSR24)) return 0+ GOF(VSR24);
   if (o >= GOF(VSR25) && o+sz <= GOF(VSR25)+SZB(VSR25)) return 0+ GOF(VSR25);
   if (o >= GOF(VSR26) && o+sz <= GOF(VSR26)+SZB(VSR26)) return 0+ GOF(VSR26);
   if (o >= GOF(VSR27) && o+sz <= GOF(VSR27)+SZB(VSR27)) return 0+ GOF(VSR27);
   if (o >= GOF(VSR28) && o+sz <= GOF(VSR28)+SZB(VSR28)) return 0+ GOF(VSR28);
   if (o >= GOF(VSR29) && o+sz <= GOF(VSR29)+SZB(VSR29)) return 0+ GOF(VSR29);
   if (o >= GOF(VSR30) && o+sz <= GOF(VSR30)+SZB(VSR30)) return 0+ GOF(VSR30);
   if (o >= GOF(VSR31) && o+sz <= GOF(VSR31)+SZB(VSR31)) return 0+ GOF(VSR31);
   if (o >= GOF(VSR32) && o+sz <= GOF(VSR32)+SZB(VSR32)) return 0+ GOF(VSR32);
   if (o >= GOF(VSR33) && o+sz <= GOF(VSR33)+SZB(VSR33)) return 0+ GOF(VSR33);
   if (o >= GOF(VSR34) && o+sz <= GOF(VSR34)+SZB(VSR34)) return 0+ GOF(VSR34);
   if (o >= GOF(VSR35) && o+sz <= GOF(VSR35)+SZB(VSR35)) return 0+ GOF(VSR35);
   if (o >= GOF(VSR36) && o+sz <= GOF(VSR36)+SZB(VSR36)) return 0+ GOF(VSR36);
   if (o >= GOF(VSR37) && o+sz <= GOF(VSR37)+SZB(VSR37)) return 0+ GOF(VSR37);
   if (o >= GOF(VSR38) && o+sz <= GOF(VSR38)+SZB(VSR38)) return 0+ GOF(VSR38);
   if (o >= GOF(VSR39) && o+sz <= GOF(VSR39)+SZB(VSR39)) return 0+ GOF(VSR39);
   if (o >= GOF(VSR40) && o+sz <= GOF(VSR40)+SZB(VSR40)) return 0+ GOF(VSR40);
   if (o >= GOF(VSR41) && o+sz <= GOF(VSR41)+SZB(VSR41)) return 0+ GOF(VSR41);
   if (o >= GOF(VSR42) && o+sz <= GOF(VSR42)+SZB(VSR42)) return 0+ GOF(VSR42);
   if (o >= GOF(VSR43) && o+sz <= GOF(VSR43)+SZB(VSR43)) return 0+ GOF(VSR43);
   if (o >= GOF(VSR44) && o+sz <= GOF(VSR44)+SZB(VSR44)) return 0+ GOF(VSR44);
   if (o >= GOF(VSR45) && o+sz <= GOF(VSR45)+SZB(VSR45)) return 0+ GOF(VSR45);
   if (o >= GOF(VSR46) && o+sz <= GOF(VSR46)+SZB(VSR46)) return 0+ GOF(VSR46);
   if (o >= GOF(VSR47) && o+sz <= GOF(VSR47)+SZB(VSR47)) return 0+ GOF(VSR47);
   if (o >= GOF(VSR48) && o+sz <= GOF(VSR48)+SZB(VSR48)) return 0+ GOF(VSR48);
   if (o >= GOF(VSR49) && o+sz <= GOF(VSR49)+SZB(VSR49)) return 0+ GOF(VSR49);
   if (o >= GOF(VSR50) && o+sz <= GOF(VSR50)+SZB(VSR50)) return 0+ GOF(VSR50);
   if (o >= GOF(VSR51) && o+sz <= GOF(VSR51)+SZB(VSR51)) return 0+ GOF(VSR51);
   if (o >= GOF(VSR52) && o+sz <= GOF(VSR52)+SZB(VSR52)) return 0+ GOF(VSR52);
   if (o >= GOF(VSR53) && o+sz <= GOF(VSR53)+SZB(VSR53)) return 0+ GOF(VSR53);
   if (o >= GOF(VSR54) && o+sz <= GOF(VSR54)+SZB(VSR54)) return 0+ GOF(VSR54);
   if (o >= GOF(VSR55) && o+sz <= GOF(VSR55)+SZB(VSR55)) return 0+ GOF(VSR55);
   if (o >= GOF(VSR56) && o+sz <= GOF(VSR56)+SZB(VSR56)) return 0+ GOF(VSR56);
   if (o >= GOF(VSR57) && o+sz <= GOF(VSR57)+SZB(VSR57)) return 0+ GOF(VSR57);
   if (o >= GOF(VSR58) && o+sz <= GOF(VSR58)+SZB(VSR58)) return 0+ GOF(VSR58);
   if (o >= GOF(VSR59) && o+sz <= GOF(VSR59)+SZB(VSR59)) return 0+ GOF(VSR59);
   if (o >= GOF(VSR60) && o+sz <= GOF(VSR60)+SZB(VSR60)) return 0+ GOF(VSR60);
   if (o >= GOF(VSR61) && o+sz <= GOF(VSR61)+SZB(VSR61)) return 0+ GOF(VSR61);
   if (o >= GOF(VSR62) && o+sz <= GOF(VSR62)+SZB(VSR62)) return 0+ GOF(VSR62);
   if (o >= GOF(VSR63) && o+sz <= GOF(VSR63)+SZB(VSR63)) return 0+ GOF(VSR63);

   VG_(printf)("MC_(get_otrack_shadow_offset)(ppc64)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* -------------------- ppc32 -------------------- */

#  elif defined(VGA_ppc32)

#  define GOF(_fieldname) \
      (offsetof(VexGuestPPC32State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestPPC32State*)0)->guest_##_fieldname))
   Int  o  = offset;
   Int  sz = szB;
   tl_assert(sz > 0);
   tl_assert(host_is_big_endian());

   if (o == GOF(GPR0) && sz == 4) return o;
   if (o == GOF(GPR1) && sz == 4) return o;
   if (o == GOF(GPR2) && sz == 4) return o;
   if (o == GOF(GPR3) && sz == 4) return o;
   if (o == GOF(GPR4) && sz == 4) return o;
   if (o == GOF(GPR5) && sz == 4) return o;
   if (o == GOF(GPR6) && sz == 4) return o;
   if (o == GOF(GPR7) && sz == 4) return o;
   if (o == GOF(GPR8) && sz == 4) return o;
   if (o == GOF(GPR9) && sz == 4) return o;
   if (o == GOF(GPR10) && sz == 4) return o;
   if (o == GOF(GPR11) && sz == 4) return o;
   if (o == GOF(GPR12) && sz == 4) return o;
   if (o == GOF(GPR13) && sz == 4) return o;
   if (o == GOF(GPR14) && sz == 4) return o;
   if (o == GOF(GPR15) && sz == 4) return o;
   if (o == GOF(GPR16) && sz == 4) return o;
   if (o == GOF(GPR17) && sz == 4) return o;
   if (o == GOF(GPR18) && sz == 4) return o;
   if (o == GOF(GPR19) && sz == 4) return o;
   if (o == GOF(GPR20) && sz == 4) return o;
   if (o == GOF(GPR21) && sz == 4) return o;
   if (o == GOF(GPR22) && sz == 4) return o;
   if (o == GOF(GPR23) && sz == 4) return o;
   if (o == GOF(GPR24) && sz == 4) return o;
   if (o == GOF(GPR25) && sz == 4) return o;
   if (o == GOF(GPR26) && sz == 4) return o;
   if (o == GOF(GPR27) && sz == 4) return o;
   if (o == GOF(GPR28) && sz == 4) return o;
   if (o == GOF(GPR29) && sz == 4) return o;
   if (o == GOF(GPR30) && sz == 4) return o;
   if (o == GOF(GPR31) && sz == 4) return o;

   if (o == GOF(LR)  && sz == 4) return o;
   if (o == GOF(CTR) && sz == 4) return o;

   if (o == GOF(CIA)       && sz == 4) return -1;
   if (o == GOF(IP_AT_SYSCALL) && sz == 4) return -1; /* slot unused */
   if (o == GOF(FPROUND)   && sz == 4) return -1;
   if (o == GOF(VRSAVE)    && sz == 4) return -1;
   if (o == GOF(EMWARN)    && sz == 4) return -1;
   if (o == GOF(TISTART)   && sz == 4) return -1;
   if (o == GOF(TILEN)     && sz == 4) return -1;
   if (o == GOF(VSCR)      && sz == 4) return -1;
   if (o == GOF(REDIR_SP)  && sz == 4) return -1;
   if (o == GOF(SPRG3_RO)  && sz == 4) return -1;

   // With ISA 2.06, the "Vector-Scalar Floating-point" category
   // provides facilities to support vector and scalar binary floating-
   // point operations.  A unified register file is an integral part
   // of this new facility, combining floating point and vector registers
   // using a 64x128-bit vector.  These are referred to as VSR[0..63].
   // The floating point registers are now mapped into double word element 0
   // of VSR[0..31]. The 32x128-bit vector registers defined by the "Vector
   // Facility [Category: Vector]" are now mapped to VSR[32..63].

   //  Floating point registers . . .
   if (o == GOF(VSR0) && sz == 8) return o;
   if (o == GOF(VSR1) && sz == 8) return o;
   if (o == GOF(VSR2) && sz == 8) return o;
   if (o == GOF(VSR3) && sz == 8) return o;
   if (o == GOF(VSR4) && sz == 8) return o;
   if (o == GOF(VSR5) && sz == 8) return o;
   if (o == GOF(VSR6) && sz == 8) return o;
   if (o == GOF(VSR7) && sz == 8) return o;
   if (o == GOF(VSR8) && sz == 8) return o;
   if (o == GOF(VSR9) && sz == 8) return o;
   if (o == GOF(VSR10) && sz == 8) return o;
   if (o == GOF(VSR11) && sz == 8) return o;
   if (o == GOF(VSR12) && sz == 8) return o;
   if (o == GOF(VSR13) && sz == 8) return o;
   if (o == GOF(VSR14) && sz == 8) return o;
   if (o == GOF(VSR15) && sz == 8) return o;
   if (o == GOF(VSR16) && sz == 8) return o;
   if (o == GOF(VSR17) && sz == 8) return o;
   if (o == GOF(VSR18) && sz == 8) return o;
   if (o == GOF(VSR19) && sz == 8) return o;
   if (o == GOF(VSR20) && sz == 8) return o;
   if (o == GOF(VSR21) && sz == 8) return o;
   if (o == GOF(VSR22) && sz == 8) return o;
   if (o == GOF(VSR23) && sz == 8) return o;
   if (o == GOF(VSR24) && sz == 8) return o;
   if (o == GOF(VSR25) && sz == 8) return o;
   if (o == GOF(VSR26) && sz == 8) return o;
   if (o == GOF(VSR27) && sz == 8) return o;
   if (o == GOF(VSR28) && sz == 8) return o;
   if (o == GOF(VSR29) && sz == 8) return o;
   if (o == GOF(VSR30) && sz == 8) return o;
   if (o == GOF(VSR31) && sz == 8) return o;

   /* For the various byte sized XER/CR pieces, use offset 8
      in VSR0 .. VSR19. */
   tl_assert(SZB(VSR0) == 16);
   if (o == GOF(XER_SO) && sz == 1) return 8 +GOF(VSR0);
   if (o == GOF(XER_OV) && sz == 1) return 8 +GOF(VSR1);
   if (o == GOF(XER_CA) && sz == 1) return 8 +GOF(VSR2);
   if (o == GOF(XER_BC) && sz == 1) return 8 +GOF(VSR3);

   if (o == GOF(CR0_321) && sz == 1) return 8 +GOF(VSR4);
   if (o == GOF(CR0_0)   && sz == 1) return 8 +GOF(VSR5);
   if (o == GOF(CR1_321) && sz == 1) return 8 +GOF(VSR6);
   if (o == GOF(CR1_0)   && sz == 1) return 8 +GOF(VSR7);
   if (o == GOF(CR2_321) && sz == 1) return 8 +GOF(VSR8);
   if (o == GOF(CR2_0)   && sz == 1) return 8 +GOF(VSR9);
   if (o == GOF(CR3_321) && sz == 1) return 8 +GOF(VSR10);
   if (o == GOF(CR3_0)   && sz == 1) return 8 +GOF(VSR11);
   if (o == GOF(CR4_321) && sz == 1) return 8 +GOF(VSR12);
   if (o == GOF(CR4_0)   && sz == 1) return 8 +GOF(VSR13);
   if (o == GOF(CR5_321) && sz == 1) return 8 +GOF(VSR14);
   if (o == GOF(CR5_0)   && sz == 1) return 8 +GOF(VSR15);
   if (o == GOF(CR6_321) && sz == 1) return 8 +GOF(VSR16);
   if (o == GOF(CR6_0)   && sz == 1) return 8 +GOF(VSR17);
   if (o == GOF(CR7_321) && sz == 1) return 8 +GOF(VSR18);
   if (o == GOF(CR7_0)   && sz == 1) return 8 +GOF(VSR19);

   /* Vector registers .. use offset 0 in VSR0 .. VSR63. */
   if (o >= GOF(VSR0)  && o+sz <= GOF(VSR0) +SZB(VSR0))  return 0+ GOF(VSR0);
   if (o >= GOF(VSR1)  && o+sz <= GOF(VSR1) +SZB(VSR1))  return 0+ GOF(VSR1);
   if (o >= GOF(VSR2)  && o+sz <= GOF(VSR2) +SZB(VSR2))  return 0+ GOF(VSR2);
   if (o >= GOF(VSR3)  && o+sz <= GOF(VSR3) +SZB(VSR3))  return 0+ GOF(VSR3);
   if (o >= GOF(VSR4)  && o+sz <= GOF(VSR4) +SZB(VSR4))  return 0+ GOF(VSR4);
   if (o >= GOF(VSR5)  && o+sz <= GOF(VSR5) +SZB(VSR5))  return 0+ GOF(VSR5);
   if (o >= GOF(VSR6)  && o+sz <= GOF(VSR6) +SZB(VSR6))  return 0+ GOF(VSR6);
   if (o >= GOF(VSR7)  && o+sz <= GOF(VSR7) +SZB(VSR7))  return 0+ GOF(VSR7);
   if (o >= GOF(VSR8)  && o+sz <= GOF(VSR8) +SZB(VSR8))  return 0+ GOF(VSR8);
   if (o >= GOF(VSR9)  && o+sz <= GOF(VSR9) +SZB(VSR9))  return 0+ GOF(VSR9);
   if (o >= GOF(VSR10) && o+sz <= GOF(VSR10)+SZB(VSR10)) return 0+ GOF(VSR10);
   if (o >= GOF(VSR11) && o+sz <= GOF(VSR11)+SZB(VSR11)) return 0+ GOF(VSR11);
   if (o >= GOF(VSR12) && o+sz <= GOF(VSR12)+SZB(VSR12)) return 0+ GOF(VSR12);
   if (o >= GOF(VSR13) && o+sz <= GOF(VSR13)+SZB(VSR13)) return 0+ GOF(VSR13);
   if (o >= GOF(VSR14) && o+sz <= GOF(VSR14)+SZB(VSR14)) return 0+ GOF(VSR14);
   if (o >= GOF(VSR15) && o+sz <= GOF(VSR15)+SZB(VSR15)) return 0+ GOF(VSR15);
   if (o >= GOF(VSR16) && o+sz <= GOF(VSR16)+SZB(VSR16)) return 0+ GOF(VSR16);
   if (o >= GOF(VSR17) && o+sz <= GOF(VSR17)+SZB(VSR17)) return 0+ GOF(VSR17);
   if (o >= GOF(VSR18) && o+sz <= GOF(VSR18)+SZB(VSR18)) return 0+ GOF(VSR18);
   if (o >= GOF(VSR19) && o+sz <= GOF(VSR19)+SZB(VSR19)) return 0+ GOF(VSR19);
   if (o >= GOF(VSR20) && o+sz <= GOF(VSR20)+SZB(VSR20)) return 0+ GOF(VSR20);
   if (o >= GOF(VSR21) && o+sz <= GOF(VSR21)+SZB(VSR21)) return 0+ GOF(VSR21);
   if (o >= GOF(VSR22) && o+sz <= GOF(VSR22)+SZB(VSR22)) return 0+ GOF(VSR22);
   if (o >= GOF(VSR23) && o+sz <= GOF(VSR23)+SZB(VSR23)) return 0+ GOF(VSR23);
   if (o >= GOF(VSR24) && o+sz <= GOF(VSR24)+SZB(VSR24)) return 0+ GOF(VSR24);
   if (o >= GOF(VSR25) && o+sz <= GOF(VSR25)+SZB(VSR25)) return 0+ GOF(VSR25);
   if (o >= GOF(VSR26) && o+sz <= GOF(VSR26)+SZB(VSR26)) return 0+ GOF(VSR26);
   if (o >= GOF(VSR27) && o+sz <= GOF(VSR27)+SZB(VSR27)) return 0+ GOF(VSR27);
   if (o >= GOF(VSR28) && o+sz <= GOF(VSR28)+SZB(VSR28)) return 0+ GOF(VSR28);
   if (o >= GOF(VSR29) && o+sz <= GOF(VSR29)+SZB(VSR29)) return 0+ GOF(VSR29);
   if (o >= GOF(VSR30) && o+sz <= GOF(VSR30)+SZB(VSR30)) return 0+ GOF(VSR30);
   if (o >= GOF(VSR31) && o+sz <= GOF(VSR31)+SZB(VSR31)) return 0+ GOF(VSR31);
   if (o >= GOF(VSR32) && o+sz <= GOF(VSR32)+SZB(VSR32)) return 0+ GOF(VSR32);
   if (o >= GOF(VSR33) && o+sz <= GOF(VSR33)+SZB(VSR33)) return 0+ GOF(VSR33);
   if (o >= GOF(VSR34) && o+sz <= GOF(VSR34)+SZB(VSR34)) return 0+ GOF(VSR34);
   if (o >= GOF(VSR35) && o+sz <= GOF(VSR35)+SZB(VSR35)) return 0+ GOF(VSR35);
   if (o >= GOF(VSR36) && o+sz <= GOF(VSR36)+SZB(VSR36)) return 0+ GOF(VSR36);
   if (o >= GOF(VSR37) && o+sz <= GOF(VSR37)+SZB(VSR37)) return 0+ GOF(VSR37);
   if (o >= GOF(VSR38) && o+sz <= GOF(VSR38)+SZB(VSR38)) return 0+ GOF(VSR38);
   if (o >= GOF(VSR39) && o+sz <= GOF(VSR39)+SZB(VSR39)) return 0+ GOF(VSR39);
   if (o >= GOF(VSR40) && o+sz <= GOF(VSR40)+SZB(VSR40)) return 0+ GOF(VSR40);
   if (o >= GOF(VSR41) && o+sz <= GOF(VSR41)+SZB(VSR41)) return 0+ GOF(VSR41);
   if (o >= GOF(VSR42) && o+sz <= GOF(VSR42)+SZB(VSR42)) return 0+ GOF(VSR42);
   if (o >= GOF(VSR43) && o+sz <= GOF(VSR43)+SZB(VSR43)) return 0+ GOF(VSR43);
   if (o >= GOF(VSR44) && o+sz <= GOF(VSR44)+SZB(VSR44)) return 0+ GOF(VSR44);
   if (o >= GOF(VSR45) && o+sz <= GOF(VSR45)+SZB(VSR45)) return 0+ GOF(VSR45);
   if (o >= GOF(VSR46) && o+sz <= GOF(VSR46)+SZB(VSR46)) return 0+ GOF(VSR46);
   if (o >= GOF(VSR47) && o+sz <= GOF(VSR47)+SZB(VSR47)) return 0+ GOF(VSR47);
   if (o >= GOF(VSR48) && o+sz <= GOF(VSR48)+SZB(VSR48)) return 0+ GOF(VSR48);
   if (o >= GOF(VSR49) && o+sz <= GOF(VSR49)+SZB(VSR49)) return 0+ GOF(VSR49);
   if (o >= GOF(VSR50) && o+sz <= GOF(VSR50)+SZB(VSR50)) return 0+ GOF(VSR50);
   if (o >= GOF(VSR51) && o+sz <= GOF(VSR51)+SZB(VSR51)) return 0+ GOF(VSR51);
   if (o >= GOF(VSR52) && o+sz <= GOF(VSR52)+SZB(VSR52)) return 0+ GOF(VSR52);
   if (o >= GOF(VSR53) && o+sz <= GOF(VSR53)+SZB(VSR53)) return 0+ GOF(VSR53);
   if (o >= GOF(VSR54) && o+sz <= GOF(VSR54)+SZB(VSR54)) return 0+ GOF(VSR54);
   if (o >= GOF(VSR55) && o+sz <= GOF(VSR55)+SZB(VSR55)) return 0+ GOF(VSR55);
   if (o >= GOF(VSR56) && o+sz <= GOF(VSR56)+SZB(VSR56)) return 0+ GOF(VSR56);
   if (o >= GOF(VSR57) && o+sz <= GOF(VSR57)+SZB(VSR57)) return 0+ GOF(VSR57);
   if (o >= GOF(VSR58) && o+sz <= GOF(VSR58)+SZB(VSR58)) return 0+ GOF(VSR58);
   if (o >= GOF(VSR59) && o+sz <= GOF(VSR59)+SZB(VSR59)) return 0+ GOF(VSR59);
   if (o >= GOF(VSR60) && o+sz <= GOF(VSR60)+SZB(VSR60)) return 0+ GOF(VSR60);
   if (o >= GOF(VSR61) && o+sz <= GOF(VSR61)+SZB(VSR61)) return 0+ GOF(VSR61);
   if (o >= GOF(VSR62) && o+sz <= GOF(VSR62)+SZB(VSR62)) return 0+ GOF(VSR62);
   if (o >= GOF(VSR63) && o+sz <= GOF(VSR63)+SZB(VSR63)) return 0+ GOF(VSR63);

   VG_(printf)("MC_(get_otrack_shadow_offset)(ppc32)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* -------------------- amd64 -------------------- */

#  elif defined(VGA_amd64)

#  define GOF(_fieldname) \
      (offsetof(VexGuestAMD64State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestAMD64State*)0)->guest_##_fieldname))
   Int  o      = offset;
   Int  sz     = szB;
   Bool is1248 = sz == 8 || sz == 4 || sz == 2 || sz == 1;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(RAX) && is1248) return o;
   if (o == GOF(RCX) && is1248) return o;
   if (o == GOF(RDX) && is1248) return o;
   if (o == GOF(RBX) && is1248) return o;
   if (o == GOF(RSP) && is1248) return o;
   if (o == GOF(RBP) && is1248) return o;
   if (o == GOF(RSI) && is1248) return o;
   if (o == GOF(RDI) && is1248) return o;
   if (o == GOF(R8)  && is1248) return o;
   if (o == GOF(R9)  && is1248) return o;
   if (o == GOF(R10) && is1248) return o;
   if (o == GOF(R11) && is1248) return o;
   if (o == GOF(R12) && is1248) return o;
   if (o == GOF(R13) && is1248) return o;
   if (o == GOF(R14) && is1248) return o;
   if (o == GOF(R15) && is1248) return o;

   if (o == GOF(CC_DEP1) && sz == 8) return o;
   if (o == GOF(CC_DEP2) && sz == 8) return o;

   if (o == GOF(CC_OP)   && sz == 8) return -1; /* slot used for %AH */
   if (o == GOF(CC_NDEP) && sz == 8) return -1; /* slot used for %BH */
   if (o == GOF(DFLAG)   && sz == 8) return -1; /* slot used for %CH */
   if (o == GOF(RIP)     && sz == 8) return -1; /* slot unused */
   if (o == GOF(IP_AT_SYSCALL) && sz == 8) return -1; /* slot unused */
   if (o == GOF(IDFLAG)  && sz == 8) return -1; /* slot used for %DH */
   if (o == GOF(ACFLAG)  && sz == 8) return -1; /* slot unused */
   if (o == GOF(FS_ZERO) && sz == 8) return -1; /* slot unused */
   if (o == GOF(GS_0x60) && sz == 8) return -1; /* slot unused */
   if (o == GOF(TISTART) && sz == 8) return -1; /* slot unused */
   if (o == GOF(TILEN)   && sz == 8) return -1; /* slot unused */

   /* Treat %AH, %BH, %CH, %DH as independent registers.  To do this
      requires finding 4 unused 32-bit slots in the second-shadow
      guest state, respectively: CC_OP CC_NDEP DFLAG IDFLAG, since
      none of those are tracked. */
   tl_assert(SZB(CC_OP)   == 8);
   tl_assert(SZB(CC_NDEP) == 8);
   tl_assert(SZB(IDFLAG)  == 8);
   tl_assert(SZB(DFLAG)   == 8);

   if (o == 1+ GOF(RAX) && szB == 1) return GOF(CC_OP);
   if (o == 1+ GOF(RBX) && szB == 1) return GOF(CC_NDEP);
   if (o == 1+ GOF(RCX) && szB == 1) return GOF(DFLAG);
   if (o == 1+ GOF(RDX) && szB == 1) return GOF(IDFLAG);

   /* skip XMM and FP admin stuff */
   if (o == GOF(SSEROUND) && szB == 8) return -1;
   if (o == GOF(FTOP)     && szB == 4) return -1;
   if (o == GOF(FPROUND)  && szB == 8) return -1;
   if (o == GOF(EMWARN)   && szB == 4) return -1;
   if (o == GOF(FC3210)   && szB == 8) return -1;

   /* XMM registers */
   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0) +SZB(XMM0))  return GOF(XMM0);
   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1) +SZB(XMM1))  return GOF(XMM1);
   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2) +SZB(XMM2))  return GOF(XMM2);
   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3) +SZB(XMM3))  return GOF(XMM3);
   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4) +SZB(XMM4))  return GOF(XMM4);
   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5) +SZB(XMM5))  return GOF(XMM5);
   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6) +SZB(XMM6))  return GOF(XMM6);
   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7) +SZB(XMM7))  return GOF(XMM7);
   if (o >= GOF(XMM8)  && o+sz <= GOF(XMM8) +SZB(XMM8))  return GOF(XMM8);
   if (o >= GOF(XMM9)  && o+sz <= GOF(XMM9) +SZB(XMM9))  return GOF(XMM9);
   if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+SZB(XMM10)) return GOF(XMM10);
   if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+SZB(XMM11)) return GOF(XMM11);
   if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+SZB(XMM12)) return GOF(XMM12);
   if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+SZB(XMM13)) return GOF(XMM13);
   if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+SZB(XMM14)) return GOF(XMM14);
   if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+SZB(XMM15)) return GOF(XMM15);
   if (o >= GOF(XMM16) && o+sz <= GOF(XMM16)+SZB(XMM16)) return GOF(XMM16);

   /* MMX accesses to FP regs.  Need to allow for 32-bit references
      due to dirty helpers for frstor etc, which reference the entire
      64-byte block in one go. */
   if (o >= GOF(FPREG[0])
       && o+sz <= GOF(FPREG[0])+SZB(FPREG[0])) return GOF(FPREG[0]);
   if (o >= GOF(FPREG[1])
       && o+sz <= GOF(FPREG[1])+SZB(FPREG[1])) return GOF(FPREG[1]);
   if (o >= GOF(FPREG[2])
       && o+sz <= GOF(FPREG[2])+SZB(FPREG[2])) return GOF(FPREG[2]);
   if (o >= GOF(FPREG[3])
       && o+sz <= GOF(FPREG[3])+SZB(FPREG[3])) return GOF(FPREG[3]);
   if (o >= GOF(FPREG[4])
       && o+sz <= GOF(FPREG[4])+SZB(FPREG[4])) return GOF(FPREG[4]);
   if (o >= GOF(FPREG[5])
       && o+sz <= GOF(FPREG[5])+SZB(FPREG[5])) return GOF(FPREG[5]);
   if (o >= GOF(FPREG[6])
       && o+sz <= GOF(FPREG[6])+SZB(FPREG[6])) return GOF(FPREG[6]);
   if (o >= GOF(FPREG[7])
       && o+sz <= GOF(FPREG[7])+SZB(FPREG[7])) return GOF(FPREG[7]);

   /* Map high halves of %RAX,%RCX,%RDX,%RBX to the whole register.
      This is needed because the general handling of dirty helper
      calls is done in 4 byte chunks.  Hence we will see these.
      Currently we only expect to see artefacts from CPUID. */
   if (o == 4+ GOF(RAX) && sz == 4) return GOF(RAX);
   if (o == 4+ GOF(RCX) && sz == 4) return GOF(RCX);
   if (o == 4+ GOF(RDX) && sz == 4) return GOF(RDX);
   if (o == 4+ GOF(RBX) && sz == 4) return GOF(RBX);

   VG_(printf)("MC_(get_otrack_shadow_offset)(amd64)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* --------------------- x86 --------------------- */

#  elif defined(VGA_x86)

#  define GOF(_fieldname) \
      (offsetof(VexGuestX86State,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestX86State*)0)->guest_##_fieldname))

   Int  o     = offset;
   Int  sz    = szB;
   Bool is124 = sz == 4 || sz == 2 || sz == 1;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(EAX) && is124) return o;
   if (o == GOF(ECX) && is124) return o;
   if (o == GOF(EDX) && is124) return o;
   if (o == GOF(EBX) && is124) return o;
   if (o == GOF(ESP) && is124) return o;
   if (o == GOF(EBP) && is124) return o;
   if (o == GOF(ESI) && is124) return o;
   if (o == GOF(EDI) && is124) return o;

   if (o == GOF(CC_DEP1) && sz == 4) return o;
   if (o == GOF(CC_DEP2) && sz == 4) return o;

   if (o == GOF(CC_OP)   && sz == 4) return -1; /* slot used for %AH */
   if (o == GOF(CC_NDEP) && sz == 4) return -1; /* slot used for %BH */
   if (o == GOF(DFLAG)   && sz == 4) return -1; /* slot used for %CH */
   if (o == GOF(EIP)     && sz == 4) return -1; /* slot unused */
   if (o == GOF(IP_AT_SYSCALL) && sz == 4) return -1; /* slot unused */
   if (o == GOF(IDFLAG)  && sz == 4) return -1; /* slot used for %DH */
   if (o == GOF(ACFLAG)  && sz == 4) return -1; /* slot unused */
   if (o == GOF(TISTART) && sz == 4) return -1; /* slot unused */
   if (o == GOF(TILEN)   && sz == 4) return -1; /* slot unused */
   if (o == GOF(NRADDR)  && sz == 4) return -1; /* slot unused */

   /* Treat %AH, %BH, %CH, %DH as independent registers.  To do this
      requires finding 4 unused 32-bit slots in the second-shadow
      guest state, respectively: CC_OP CC_NDEP DFLAG IDFLAG since none
      of those are tracked. */
   tl_assert(SZB(CC_OP)   == 4);
   tl_assert(SZB(CC_NDEP) == 4);
   tl_assert(SZB(DFLAG)   == 4);
   tl_assert(SZB(IDFLAG)  == 4);
   if (o == 1+ GOF(EAX) && szB == 1) return GOF(CC_OP);
   if (o == 1+ GOF(EBX) && szB == 1) return GOF(CC_NDEP);
   if (o == 1+ GOF(ECX) && szB == 1) return GOF(DFLAG);
   if (o == 1+ GOF(EDX) && szB == 1) return GOF(IDFLAG);

   /* skip XMM and FP admin stuff */
   if (o == GOF(SSEROUND) && szB == 4) return -1;
   if (o == GOF(FTOP)     && szB == 4) return -1;
   if (o == GOF(FPROUND)  && szB == 4) return -1;
   if (o == GOF(EMWARN)   && szB == 4) return -1;
   if (o == GOF(FC3210)   && szB == 4) return -1;

   /* XMM registers */
   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0)+SZB(XMM0)) return GOF(XMM0);
   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1)+SZB(XMM1)) return GOF(XMM1);
   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2)+SZB(XMM2)) return GOF(XMM2);
   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3)+SZB(XMM3)) return GOF(XMM3);
   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4)+SZB(XMM4)) return GOF(XMM4);
   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5)+SZB(XMM5)) return GOF(XMM5);
   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6)+SZB(XMM6)) return GOF(XMM6);
   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7)+SZB(XMM7)) return GOF(XMM7);

   /* MMX accesses to FP regs.  Need to allow for 32-bit references
      due to dirty helpers for frstor etc, which reference the entire
      64-byte block in one go. */
   if (o >= GOF(FPREG[0])
       && o+sz <= GOF(FPREG[0])+SZB(FPREG[0])) return GOF(FPREG[0]);
   if (o >= GOF(FPREG[1])
       && o+sz <= GOF(FPREG[1])+SZB(FPREG[1])) return GOF(FPREG[1]);
   if (o >= GOF(FPREG[2])
       && o+sz <= GOF(FPREG[2])+SZB(FPREG[2])) return GOF(FPREG[2]);
   if (o >= GOF(FPREG[3])
       && o+sz <= GOF(FPREG[3])+SZB(FPREG[3])) return GOF(FPREG[3]);
   if (o >= GOF(FPREG[4])
       && o+sz <= GOF(FPREG[4])+SZB(FPREG[4])) return GOF(FPREG[4]);
   if (o >= GOF(FPREG[5])
       && o+sz <= GOF(FPREG[5])+SZB(FPREG[5])) return GOF(FPREG[5]);
   if (o >= GOF(FPREG[6])
       && o+sz <= GOF(FPREG[6])+SZB(FPREG[6])) return GOF(FPREG[6]);
   if (o >= GOF(FPREG[7])
       && o+sz <= GOF(FPREG[7])+SZB(FPREG[7])) return GOF(FPREG[7]);

   /* skip %GS and other segment related stuff.  We could shadow
      guest_LDT and guest_GDT, although it seems pointless.
      guest_CS .. guest_SS are too small to shadow directly and it
      also seems pointless to shadow them indirectly (that is, in 
      the style of %AH .. %DH). */
   if (o == GOF(CS) && sz == 2) return -1;
   if (o == GOF(DS) && sz == 2) return -1;
   if (o == GOF(ES) && sz == 2) return -1;
   if (o == GOF(FS) && sz == 2) return -1;
   if (o == GOF(GS) && sz == 2) return -1;
   if (o == GOF(SS) && sz == 2) return -1;
   if (o == GOF(LDT) && sz == 4) return -1;
   if (o == GOF(GDT) && sz == 4) return -1;

   VG_(printf)("MC_(get_otrack_shadow_offset)(x86)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

   /* -------------------- s390x -------------------- */

#  elif defined(VGA_s390x)
#  define GOF(_fieldname) \
      (offsetof(VexGuestS390XState,guest_##_fieldname))
   Int  o      = offset;
   Int  sz     = szB;
   tl_assert(sz > 0);
   tl_assert(host_is_big_endian());

   /* no matter what byte(s) we change, we have changed the full 8 byte value
      and need to track this change for the whole register */
   if (o >= GOF(r0) && sz <= 8 && o <= (GOF(r15) + 8 - sz))
      return GOF(r0) + ((o-GOF(r0)) & -8) ;


   /* fprs are accessed 4 or 8 byte at once. Again, we track that change for
      the full register */
   if ((sz == 8 || sz == 4) && o >= GOF(f0) && o <= GOF(f15)+8-sz)
      return GOF(f0) + ((o-GOF(f0)) & -8) ;

   /* access registers are accessed 4 bytes at once */
   if (sz == 4 && o >= GOF(a0) && o <= GOF(a15))
         return o;

   /* we access the guest counter either fully or one of the 4byte words */
   if (o == GOF(counter) && (sz == 8 || sz ==4))
      return o;
   if (o == GOF(counter) + 4 && sz == 4)
      return o;

   if (o == GOF(CC_OP)) return -1;
   if (o == GOF(CC_DEP1)) return o;
   if (o == GOF(CC_DEP2)) return o;
   if (o == GOF(CC_NDEP)) return -1;
   if (o == GOF(TISTART)) return -1;
   if (o == GOF(TILEN)) return -1;
   if (o == GOF(NRADDR)) return -1;
   if (o == GOF(IP_AT_SYSCALL)) return -1;
   if (o == GOF(fpc)) return -1;
   if (o == GOF(IA)) return -1;
   if (o == GOF(SYSNO)) return -1;
   VG_(printf)("MC_(get_otrack_shadow_offset)(s390x)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF


   /* --------------------- arm --------------------- */

#  elif defined(VGA_arm)

#  define GOF(_fieldname) \
      (offsetof(VexGuestARMState,guest_##_fieldname))
#  define SZB(_fieldname) \
      (sizeof(((VexGuestARMState*)0)->guest_##_fieldname))

   Int  o     = offset;
   Int  sz    = szB;
   tl_assert(sz > 0);
   tl_assert(host_is_little_endian());

   if (o == GOF(R0)  && sz == 4) return o;
   if (o == GOF(R1)  && sz == 4) return o;
   if (o == GOF(R2)  && sz == 4) return o;
   if (o == GOF(R3)  && sz == 4) return o;
   if (o == GOF(R4)  && sz == 4) return o;
   if (o == GOF(R5)  && sz == 4) return o;
   if (o == GOF(R6)  && sz == 4) return o;
   if (o == GOF(R7)  && sz == 4) return o;
   if (o == GOF(R8)  && sz == 4) return o;
   if (o == GOF(R9)  && sz == 4) return o;
   if (o == GOF(R10) && sz == 4) return o;
   if (o == GOF(R11) && sz == 4) return o;
   if (o == GOF(R12) && sz == 4) return o;
   if (o == GOF(R13) && sz == 4) return o;
   if (o == GOF(R14) && sz == 4) return o;

   /* EAZG: These may be completely wrong. */
   if (o == GOF(R15T)  && sz == 4) return -1; /* slot unused */
   if (o == GOF(CC_OP) && sz == 4) return -1; /* slot unused */

   if (o == GOF(CC_DEP1) && sz == 4) return o;
   if (o == GOF(CC_DEP2) && sz == 4) return o;

   if (o == GOF(CC_NDEP) && sz == 4) return -1; /* slot unused */

   if (o == GOF(QFLAG32) && sz == 4) return o;

   if (o == GOF(GEFLAG0) && sz == 4) return o;
   if (o == GOF(GEFLAG1) && sz == 4) return o;
   if (o == GOF(GEFLAG2) && sz == 4) return o;
   if (o == GOF(GEFLAG3) && sz == 4) return o;

   //if (o == GOF(SYSCALLNO)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(CC)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(EMWARN)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(TISTART)     && sz == 4) return -1; /* slot unused */
   //if (o == GOF(NRADDR)     && sz == 4) return -1; /* slot unused */

   if (o == GOF(FPSCR)    && sz == 4) return -1;
   if (o == GOF(TPIDRURO) && sz == 4) return -1;
   if (o == GOF(ITSTATE)  && sz == 4) return -1;

   /* Accesses to F or D registers */
   if (sz == 4 || sz == 8) {
      if (o >= GOF(D0)  && o+sz <= GOF(D0) +SZB(D0))  return GOF(D0);
      if (o >= GOF(D1)  && o+sz <= GOF(D1) +SZB(D1))  return GOF(D1);
      if (o >= GOF(D2)  && o+sz <= GOF(D2) +SZB(D2))  return GOF(D2);
      if (o >= GOF(D3)  && o+sz <= GOF(D3) +SZB(D3))  return GOF(D3);
      if (o >= GOF(D4)  && o+sz <= GOF(D4) +SZB(D4))  return GOF(D4);
      if (o >= GOF(D5)  && o+sz <= GOF(D5) +SZB(D5))  return GOF(D5);
      if (o >= GOF(D6)  && o+sz <= GOF(D6) +SZB(D6))  return GOF(D6);
      if (o >= GOF(D7)  && o+sz <= GOF(D7) +SZB(D7))  return GOF(D7);
      if (o >= GOF(D8)  && o+sz <= GOF(D8) +SZB(D8))  return GOF(D8);
      if (o >= GOF(D9)  && o+sz <= GOF(D9) +SZB(D9))  return GOF(D9);
      if (o >= GOF(D10) && o+sz <= GOF(D10)+SZB(D10)) return GOF(D10);
      if (o >= GOF(D11) && o+sz <= GOF(D11)+SZB(D11)) return GOF(D11);
      if (o >= GOF(D12) && o+sz <= GOF(D12)+SZB(D12)) return GOF(D12);
      if (o >= GOF(D13) && o+sz <= GOF(D13)+SZB(D13)) return GOF(D13);
      if (o >= GOF(D14) && o+sz <= GOF(D14)+SZB(D14)) return GOF(D14);
      if (o >= GOF(D15) && o+sz <= GOF(D15)+SZB(D15)) return GOF(D15);
      if (o >= GOF(D16) && o+sz <= GOF(D16)+SZB(D16)) return GOF(D16);
      if (o >= GOF(D17) && o+sz <= GOF(D17)+SZB(D17)) return GOF(D17);
      if (o >= GOF(D18) && o+sz <= GOF(D18)+SZB(D18)) return GOF(D18);
      if (o >= GOF(D19) && o+sz <= GOF(D19)+SZB(D19)) return GOF(D19);
      if (o >= GOF(D20) && o+sz <= GOF(D20)+SZB(D20)) return GOF(D20);
      if (o >= GOF(D21) && o+sz <= GOF(D21)+SZB(D21)) return GOF(D21);
      if (o >= GOF(D22) && o+sz <= GOF(D22)+SZB(D22)) return GOF(D22);
      if (o >= GOF(D23) && o+sz <= GOF(D23)+SZB(D23)) return GOF(D23);
      if (o >= GOF(D24) && o+sz <= GOF(D24)+SZB(D24)) return GOF(D24);
      if (o >= GOF(D25) && o+sz <= GOF(D25)+SZB(D25)) return GOF(D25);
      if (o >= GOF(D26) && o+sz <= GOF(D26)+SZB(D26)) return GOF(D26);
      if (o >= GOF(D27) && o+sz <= GOF(D27)+SZB(D27)) return GOF(D27);
      if (o >= GOF(D28) && o+sz <= GOF(D28)+SZB(D28)) return GOF(D28);
      if (o >= GOF(D29) && o+sz <= GOF(D29)+SZB(D29)) return GOF(D29);
      if (o >= GOF(D30) && o+sz <= GOF(D30)+SZB(D30)) return GOF(D30);
      if (o >= GOF(D31) && o+sz <= GOF(D31)+SZB(D31)) return GOF(D31);
   }

   /* Accesses to Q registers */
   if (sz == 16) {
      if (o >= GOF(D0)  && o+sz <= GOF(D0) +2*SZB(D0))  return GOF(D0);  // Q0
      if (o >= GOF(D2)  && o+sz <= GOF(D2) +2*SZB(D2))  return GOF(D2);  // Q1
      if (o >= GOF(D4)  && o+sz <= GOF(D4) +2*SZB(D4))  return GOF(D4);  // Q2
      if (o >= GOF(D6)  && o+sz <= GOF(D6) +2*SZB(D6))  return GOF(D6);  // Q3
      if (o >= GOF(D8)  && o+sz <= GOF(D8) +2*SZB(D8))  return GOF(D8);  // Q4
      if (o >= GOF(D10) && o+sz <= GOF(D10)+2*SZB(D10)) return GOF(D10); // Q5
      if (o >= GOF(D12) && o+sz <= GOF(D12)+2*SZB(D12)) return GOF(D12); // Q6
      if (o >= GOF(D14) && o+sz <= GOF(D14)+2*SZB(D14)) return GOF(D14); // Q7
      if (o >= GOF(D16) && o+sz <= GOF(D16)+2*SZB(D16)) return GOF(D16); // Q8
      if (o >= GOF(D18) && o+sz <= GOF(D18)+2*SZB(D18)) return GOF(D18); // Q9
      if (o >= GOF(D20) && o+sz <= GOF(D20)+2*SZB(D20)) return GOF(D20); // Q10
      if (o >= GOF(D22) && o+sz <= GOF(D22)+2*SZB(D22)) return GOF(D22); // Q11
      if (o >= GOF(D24) && o+sz <= GOF(D24)+2*SZB(D24)) return GOF(D24); // Q12
      if (o >= GOF(D26) && o+sz <= GOF(D26)+2*SZB(D26)) return GOF(D26); // Q13
      if (o >= GOF(D28) && o+sz <= GOF(D28)+2*SZB(D28)) return GOF(D28); // Q14
      if (o >= GOF(D30) && o+sz <= GOF(D30)+2*SZB(D30)) return GOF(D30); // Q15
   }

   VG_(printf)("MC_(get_otrack_shadow_offset)(arm)(off=%d,sz=%d)\n",
               offset,szB);
   tl_assert(0);
#  undef GOF
#  undef SZB

#  else
#    error "FIXME: not implemented for this architecture"
#  endif
}
Exemplo n.º 3
0
static int calc_shading(struct gl843_device *dev,
			struct calibration_info *cal)
{
	int ret, i;
	struct gl843_image *light_img = NULL, *dark_img = NULL;
	uint16_t *Ln, *Dn, *p, *p_end;
	const int target = 0xffff;
	int div_by_zero = 0;
	int gain_overflow = 0;

	DBG(DBG_msg, "Calculating shading correction.\n");

	CHK_MEM(light_img = create_image(cal->width, cal->height, PXFMT_RGB16));
	CHK_MEM(dark_img = create_image(cal->width, cal->height, PXFMT_RGB16));

	/* Scan light (white) pixels */

	/* Assume lamp is on */
	CHK(scan_img(dev, light_img, 10000));
	get_vertical_average(light_img);

	/* Scan dark (black) pixels */

	CHK(set_lamp(dev, LAMP_OFF, 0));
	CHK(scan_img(dev, dark_img, 10000));
	get_vertical_average(dark_img);

	/* Calculate shading
	 * Ref: shading & correction in GL843 datasheet. */

	p = cal->sc;
	p_end = p + cal->sc_len;
	Ln = (uint16_t *) light_img->data;
	Dn = (uint16_t *) dark_img->data;

	for (i = 0; i < cal->width * 3; i++) {
		int diff, gain;

		diff = *Ln++ - *Dn;
		if (diff == 0) {
			div_by_zero = 1;
			diff = target;
		}
		gain = (cal->A * target) / diff;
		if (gain > 0xffff) {
			gain_overflow = 1;
			gain = 0xffff;
		}

		*p++ = *Dn++;
		*p++ = gain;

		if (p > p_end) {
			DBG(DBG_error, "internal error: buffer overrun.");
			break;
		}
	}

	if (host_is_big_endian())
		swap_buffer_endianness(cal->sc, cal->sc, cal->sc_len / 2);

	if (div_by_zero)
		DBG(DBG_warn, "division by zero detected.\n");
	if (gain_overflow)
		DBG(DBG_warn, "gain overflow detected.\n");

	ret = 0;
chk_failed:
	free(light_img);
	free(dark_img);
	return ret;
chk_mem_failed:
	ret = LIBUSB_ERROR_NO_MEM;
	goto chk_failed;
}
namespace occupancy_map_monitor
{

DepthImageOccupancyMapUpdater::DepthImageOccupancyMapUpdater(OccupancyMapMonitor *monitor) :
  OccupancyMapUpdater(monitor, "DepthImageUpdater"),
  nh_("~"),
  tf_(monitor->getTFClient()),
  input_depth_transport_(nh_),
  model_depth_transport_(nh_),
  filtered_depth_transport_(nh_),
  image_topic_("depth"),
  queue_size_(5),
  near_clipping_plane_distance_(0.3),
  far_clipping_plane_distance_(5.0),
  shadow_threshold_(0.5),
  padding_scale_(3.0),
  padding_offset_(0.02),
  skip_vertical_pixels_(4),
  skip_horizontal_pixels_(6)
{
}

DepthImageOccupancyMapUpdater::~DepthImageOccupancyMapUpdater()
{
  stopHelper();
}

static void readXmlParam(XmlRpc::XmlRpcValue &params, const std::string &param_name, double *value)
{
  if (params.hasMember(param_name))
  {
    if (params[param_name].getType() == XmlRpc::XmlRpcValue::TypeInt)
      *value = (int) params[param_name];
    else
      *value = (double) params[param_name];
  }
}
static void readXmlParam(XmlRpc::XmlRpcValue &params, const std::string &param_name, unsigned int *value)
{
  if (params.hasMember(param_name))
    *value = (int) params[param_name];
}

bool DepthImageOccupancyMapUpdater::setParams(XmlRpc::XmlRpcValue &params)
{
  try
  {
    sensor_type_ = (std::string) params["sensor_type"];
    if (params.hasMember("image_topic"))
      image_topic_ = (std::string) params["image_topic"];
    if (params.hasMember("queue_size"))
      queue_size_ = (int)params["queue_size"];
    
    readXmlParam(params, "near_clipping_plane_distance", &near_clipping_plane_distance_);
    readXmlParam(params, "far_clipping_plane_distance", &far_clipping_plane_distance_);
    readXmlParam(params, "shadow_threshold", &shadow_threshold_);
    readXmlParam(params, "padding_scale", &padding_scale_);
    readXmlParam(params, "padding_offset", &padding_offset_);
    readXmlParam(params, "skip_vertical_pixels", &skip_vertical_pixels_);
    readXmlParam(params, "skip_horizontal_pixels", &skip_horizontal_pixels_);
  }
  catch (XmlRpc::XmlRpcException &ex)
  {
    ROS_ERROR("XmlRpc Exception: %s", ex.getMessage().c_str());
    return false;
  }
  
  return true;
}

bool DepthImageOccupancyMapUpdater::initialize()
{
  // create our mesh filter
  mesh_filter_.reset(new mesh_filter::MeshFilter<mesh_filter::StereoCameraModel>(mesh_filter::MeshFilterBase::TransformCallback(),
                                                                                 mesh_filter::StereoCameraModel::RegisteredPSDKParams));
  mesh_filter_->parameters().setDepthRange(near_clipping_plane_distance_, far_clipping_plane_distance_);
  mesh_filter_->setShadowThreshold(shadow_threshold_);
  mesh_filter_->setPaddingOffset(padding_offset_);
  mesh_filter_->setPaddingScale(padding_scale_);
  mesh_filter_->setTransformCallback(boost::bind(&DepthImageOccupancyMapUpdater::getShapeTransform, this, _1, _2));
  
  return true;
}

void DepthImageOccupancyMapUpdater::start()
{
  image_transport::TransportHints hints("raw", ros::TransportHints(), nh_);
  sub_depth_image_ = input_depth_transport_.subscribeCamera(image_topic_, queue_size_, &DepthImageOccupancyMapUpdater::depthImageCallback, this, hints);
  pub_model_depth_image_ = model_depth_transport_.advertiseCamera("model_depth", 10);
  pub_filtered_depth_image_ = filtered_depth_transport_.advertiseCamera("filtered_depth", 10);
}

void DepthImageOccupancyMapUpdater::stop()
{ 
  stopHelper();
}

void DepthImageOccupancyMapUpdater::stopHelper()
{   
  sub_depth_image_.shutdown();
}

mesh_filter::MeshHandle DepthImageOccupancyMapUpdater::excludeShape(const shapes::ShapeConstPtr &shape)
{
  mesh_filter::MeshHandle h = 0;
  if (mesh_filter_)
  {
    if (shape->type == shapes::MESH)
      h = mesh_filter_->addMesh(static_cast<const shapes::Mesh&>(*shape));
  }
  else
    ROS_ERROR("Mesh filter not yet initialized!");  
  return h;
}

void DepthImageOccupancyMapUpdater::forgetShape(mesh_filter::MeshHandle handle)
{
  mesh_filter_->removeMesh(handle);
}

bool DepthImageOccupancyMapUpdater::getShapeTransform(mesh_filter::MeshHandle h, Eigen::Affine3d &transform) const
{
  ShapeTransformCache::const_iterator it = transform_cache_.find(h);
  if (it == transform_cache_.end())
  {
    ROS_ERROR("Internal error. Mesh filter handle %u not found", h);
    return false;
  }
  transform = it->second;
  return true;
}

namespace
{
bool host_is_big_endian(void)
{
  union {
    uint32_t i;
    char c[sizeof(uint32_t)];
  } bint = {0x01020304};
  return bint.c[0] == 1; 
}
}

static const bool HOST_IS_BIG_ENDIAN = host_is_big_endian();

void DepthImageOccupancyMapUpdater::depthImageCallback(const sensor_msgs::ImageConstPtr& depth_msg, const sensor_msgs::CameraInfoConstPtr& info_msg)
{
  ROS_DEBUG("Received a new depth image message");
  ros::WallTime start = ros::WallTime::now();
 
  if (monitor_->getMapFrame().empty())
    monitor_->setMapFrame(depth_msg->header.frame_id);
  
  /* get transform for cloud into map frame */
  tf::StampedTransform map_H_sensor;
  if (monitor_->getMapFrame() == depth_msg->header.frame_id)
    map_H_sensor.setIdentity();
  else
  {
    if (tf_)
    {
      try
      {
        tf_->lookupTransform(monitor_->getMapFrame(), depth_msg->header.frame_id, depth_msg->header.stamp, map_H_sensor);
      }
      catch (tf::TransformException& ex)
      {
        ROS_ERROR_STREAM("Transform error of sensor data: " << ex.what() << "; quitting callback");
        return;
      }
    }
    else
      return;
  } 
  
  if (!updateTransformCache(depth_msg->header.frame_id, depth_msg->header.stamp))
    ROS_ERROR_THROTTLE(1, "Transform cache was not updated. Self-filtering may fail.");
  
  if (depth_msg->is_bigendian && !HOST_IS_BIG_ENDIAN)
    ROS_ERROR_THROTTLE(1, "endian problem: received image data does not match host");
  
  const int w = depth_msg->width;
  const int h = depth_msg->height;
  
  // call the mesh filter
  mesh_filter::StereoCameraModel::Parameters& params = mesh_filter_->parameters();
  params.setCameraParameters (info_msg->K[0], info_msg->K[4], info_msg->K[2], info_msg->K[5]);
  params.setImageSize(w, h);
  
  const bool is_u_short = depth_msg->encoding == sensor_msgs::image_encodings::TYPE_16UC1;
  if (is_u_short)
    mesh_filter_->filter(&depth_msg->data[0], GL_UNSIGNED_SHORT);
  else
    mesh_filter_->filter(&depth_msg->data[0], GL_FLOAT);
  
  // Use correct principal point from calibration
  const double px = info_msg->K[2];
  const double py = info_msg->K[5];
  
  const double inv_fx = 1.0 / info_msg->K[0];
  const double inv_fy = 1.0 / info_msg->K[4];
  
  // Pre-compute some constants
  if (x_cache_.size() < w)
    x_cache_.resize(w);
  if (y_cache_.size() < h)
    y_cache_.resize(h);
  
  for (int x = 0; x < w; ++x)
    x_cache_[x] = (x - px) * inv_fx;
  
  for (int y = 0; y < h; ++y)
    y_cache_[y] = (y - py) * inv_fy;
  
  octomap::point3d sensor_origin(map_H_sensor.getOrigin().getX(), map_H_sensor.getOrigin().getY(), map_H_sensor.getOrigin().getZ());
  
  OccMapTreePtr tree = monitor_->getOcTreePtr();
  octomap::KeySet free_cells, occupied_cells, model_cells;
  
  // allocate memory if needed
  std::size_t img_size = h * w;
  if (filtered_data_.size() < img_size)
    filtered_data_.resize(img_size);
  const float* filtered_row = reinterpret_cast<const float*>(&filtered_data_[0]);
  
  mesh_filter_->getFilteredDepth(&filtered_data_[0]);
  
  if (debug_info_)
  {
    sensor_msgs::Image debug_msg;
    debug_msg.header = depth_msg->header;
    debug_msg.height = depth_msg->height;
    debug_msg.width = depth_msg->width;
    debug_msg.encoding = sensor_msgs::image_encodings::TYPE_32FC1;
    debug_msg.is_bigendian = depth_msg->is_bigendian;
    debug_msg.step = depth_msg->step;
    debug_msg.data.resize(img_size * sizeof(float));
    mesh_filter_->getModelDepth(reinterpret_cast<float*>(&debug_msg.data[0]));
    pub_model_depth_image_.publish(debug_msg, *info_msg);
    memcpy(&debug_msg.data[0], &filtered_data_[0], sizeof(float) * img_size);
    pub_filtered_depth_image_.publish(debug_msg, *info_msg);
  }
  
  tree->lockRead();
  
  try
  {
    const int h_bound = h - skip_vertical_pixels_;
    const int w_bound = w - skip_horizontal_pixels_;
    
    if (is_u_short)
    {
      const uint16_t *input_row = reinterpret_cast<const uint16_t*>(&depth_msg->data[0]);
      
      for (int y = skip_vertical_pixels_ ; y < h_bound ; ++y, filtered_row += w, input_row += w)
	if (y_cache_[y] == y_cache_[y]) // if not NaN
	  for (int x = skip_horizontal_pixels_ ; x < w_bound ; ++x)
          {
            float zz = filtered_row[x];
            uint16_t zz0 = input_row[x];
            
            if (zz0 != 0)
            {
              if (zz == 0.0)
              {
                float zz1 = (float)zz0 * 1e-3; // scale from mm to m
                float yy = y_cache_[y] * zz1;
                float xx = x_cache_[x] * zz1;
                /* transform to map frame */
                tf::Vector3 point_tf = map_H_sensor * tf::Vector3(xx, yy, zz1);
                // add to the list of model cells
                model_cells.insert(tree->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
              }
              else
              {
                if (zz == zz)
                {
                  float yy = y_cache_[y] * zz;
                  float xx = x_cache_[x] * zz;
                  /* transform to map frame */
                  tf::Vector3 point_tf = map_H_sensor * tf::Vector3(xx, yy, zz);
                  
                  // add to the list of occupied cells
                  occupied_cells.insert(tree->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
                }
              }
            }
          }
    }
    else
    {
      const float *input_row = reinterpret_cast<const float*>(&depth_msg->data[0]);
      
      for (int y = skip_vertical_pixels_ ; y < h_bound ; ++y, filtered_row += w, input_row += w)
	if (y_cache_[y] == y_cache_[y]) // if not NaN
	  for (int x = skip_horizontal_pixels_ ; x < w_bound ; ++x)
          {
            float zz = filtered_row[x];
            float zz0 = input_row[x];
            if (zz0 == zz0 && zz == zz) // check for NaN
            {
              float yy = y_cache_[y] * zz0;
              float xx = x_cache_[x] * zz0;
              if (xx == xx)
              {
                /* transform to map frame */
                tf::Vector3 point_tf = map_H_sensor * tf::Vector3(xx, yy, zz0);
                if (zz == 0.0)
                  // add to the list of model cells
                  model_cells.insert(tree->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
                else
                  // add to the list of occupied cells
                  occupied_cells.insert(tree->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
              }
            }
          }
    }
    
    /* compute the free cells along each ray that ends at an occupied cell */
    for (octomap::KeySet::iterator it = occupied_cells.begin(), end = occupied_cells.end(); it != end; ++it)
      if (tree->computeRayKeys(sensor_origin, tree->keyToCoord(*it), key_ray_))
        free_cells.insert(key_ray_.begin(), key_ray_.end());
    
    /* compute the free cells along each ray that ends at a model cell */
    for (octomap::KeySet::iterator it = model_cells.begin(), end = model_cells.end(); it != end; ++it)
      if (tree->computeRayKeys(sensor_origin, tree->keyToCoord(*it), key_ray_))
        free_cells.insert(key_ray_.begin(), key_ray_.end());
  }
  catch (...)
  { 
    tree->unlockRead();
    return;
  }
  
  tree->unlockRead();
  
  /* cells that overlap with the model are not occupied */
  for (octomap::KeySet::iterator it = model_cells.begin(), end = model_cells.end(); it != end; ++it)
    occupied_cells.erase(*it);
  
  /* occupied cells are not free */
  for (octomap::KeySet::iterator it = occupied_cells.begin(), end = occupied_cells.end(); it != end; ++it)
    free_cells.erase(*it);
  
  tree->lockWrite();
  
  try
  {    
    /* mark free cells only if not seen occupied in this cloud */
    for (octomap::KeySet::iterator it = free_cells.begin(), end = free_cells.end(); it != end; ++it)
      tree->updateNode(*it, false);
    
    /* now mark all occupied cells */
    for (octomap::KeySet::iterator it = occupied_cells.begin(), end = occupied_cells.end(); it != end; ++it)
      tree->updateNode(*it, true);
    
    // set the logodds to the minimum for the cells that are part of the model
    const float lg = tree->getClampingThresMinLog() - tree->getClampingThresMaxLog();
    for (octomap::KeySet::iterator it = model_cells.begin(), end = model_cells.end(); it != end; ++it)
      tree->updateNode(*it, lg);
  }
  catch (...)
  {
    ROS_ERROR("Internal error while updating octree");
  }
  tree->unlockWrite();
  ROS_DEBUG("Processed depth image in %lf ms", (ros::WallTime::now() - start).toSec() * 1000.0);
  triggerUpdateCallback();
}

}