]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
On a PPC32Instr_Call, don't merely record how many integer registers
authorJulian Seward <jseward@acm.org>
Sun, 21 Aug 2005 00:48:37 +0000 (00:48 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 21 Aug 2005 00:48:37 +0000 (00:48 +0000)
carry parameters.  Instead record the actual identities of such
registers in a bitmask.  This is necessary because the PPC calling
conventions have "holes" in the register ranges.  For example, a
routine taking an UInt(32-bit) first param and an ULong(64-bit) second
param passes the first arg in r3 but the second one in r5 and r6, and
r4 is not used.

git-svn-id: svn://svn.valgrind.org/vex/trunk@1340

VEX/priv/host-ppc32/hdefs.c
VEX/priv/host-ppc32/hdefs.h
VEX/priv/host-ppc32/isel.c

index 03a78199a63791552a51bff623e4bb76933f286e..adbe2387280719d8f117e8aa11582539f4b497dc 100644 (file)
@@ -706,13 +706,16 @@ PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
    return i;
 }
 PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, 
-                              Addr32 target, Int regparms ) {
+                              Addr32 target, UInt argiregs ) {
+   UInt mask;
    PPC32Instr* i        = LibVEX_Alloc(sizeof(PPC32Instr));
    i->tag               = Pin_Call;
    i->Pin.Call.cond     = cond;
    i->Pin.Call.target   = target;
-   i->Pin.Call.regparms = regparms;
-   vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
+   i->Pin.Call.argiregs = argiregs;
+   /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
+   mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
+   vassert(0 == (argiregs & ~mask));
    return i;
 }
 PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, 
@@ -1054,15 +1057,25 @@ void ppPPC32Instr ( PPC32Instr* i )
       vex_printf(",");
       ppHRegPPC32(i->Pin.Div.srcR);
       return;
-   case Pin_Call:
+   case Pin_Call: {
+      Int n;
       vex_printf("call: ");
       if (i->Pin.Call.cond.test != Pct_ALWAYS) {
          vex_printf("if (%s) ", showPPC32CondCode(i->Pin.Call.cond));
       }
       vex_printf("{ ");
       ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target);
-      vex_printf(" ; mtctr r12 ; bctrl [regparms=%d] }",i->Pin.Call.regparms);
+      vex_printf(" ; mtctr r12 ; bctrl [");
+      for (n = 0; n < 32; n++) {
+         if (i->Pin.Call.argiregs & (1<<n)) {
+            vex_printf("r%d", n);
+            if ((i->Pin.Call.argiregs >> n) > 1)
+               vex_printf(",");
+         }
+      }
+      vex_printf("] }");
       break;
+   }
    case Pin_Goto:
       vex_printf("goto: ");
       if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
@@ -1438,19 +1451,20 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
       addHRegUse(u, HRmWrite, hregPPC32_GPR12());
       
       /* Now we have to state any parameter-carrying registers
-         which might be read.  This depends on the regparmness. */
-      switch (i->Pin.Call.regparms) {
-      case  8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
-      case  7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
-      case  6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
-      case  5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
-      case  4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
-      case  3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
-      case  2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
-      case  1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
-      case  0: break;
-      default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
-      }
+         which might be read.  This depends on the argiregs field. */
+      if (i->Pin.Call.argiregs & (1<<10)) addHRegUse(u, HRmRead, hregPPC32_GPR10());
+      if (i->Pin.Call.argiregs & (1<<9)) addHRegUse(u, HRmRead, hregPPC32_GPR9());
+      if (i->Pin.Call.argiregs & (1<<8)) addHRegUse(u, HRmRead, hregPPC32_GPR8());
+      if (i->Pin.Call.argiregs & (1<<7)) addHRegUse(u, HRmRead, hregPPC32_GPR7());
+      if (i->Pin.Call.argiregs & (1<<6)) addHRegUse(u, HRmRead, hregPPC32_GPR6());
+      if (i->Pin.Call.argiregs & (1<<5)) addHRegUse(u, HRmRead, hregPPC32_GPR5());
+      if (i->Pin.Call.argiregs & (1<<4)) addHRegUse(u, HRmRead, hregPPC32_GPR4());
+      if (i->Pin.Call.argiregs & (1<<3)) addHRegUse(u, HRmRead, hregPPC32_GPR3());
+
+      vassert(0 == (i->Pin.Call.argiregs
+                    & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
+                        |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
+
       /* Finally, there is the issue that the insn trashes a
          register because the literal target address has to be
          loaded into a register.  %r12 seems a suitable victim.
index bdc88f0cab62f0a03bc476276fdf458cc295787b..d8f1148bd345fb4eb30d41064e6a2ce78ec0e522 100644 (file)
@@ -494,11 +494,14 @@ typedef
             HReg srcR;
          } Div;
          /* Pseudo-insn.  Call target (an absolute address), on given
-            condition (which could be Pct_ALWAYS). */
+            condition (which could be Pct_ALWAYS).  argiregs indicates
+            which of r3 .. r10 carries argument values for this call,
+            using a bit mask (1<<N is set if rN holds an arg, for N in
+            3 .. 10 inclusive). */
          struct {
             PPC32CondCode cond;
             Addr32        target;
-            Int           regparms; /* 0 .. 9 */
+            UInt          argiregs;
          } Call;
          /* Pseudo-insn.  Goto dst, on given condition (which could be
             Pct_ALWAYS). */
@@ -685,7 +688,7 @@ extern PPC32Instr* PPC32Instr_Cmp32      ( Bool,       UInt, HReg, PPC32RH* );
 extern PPC32Instr* PPC32Instr_Unary32    ( PPC32UnaryOp op, HReg dst, HReg src );
 extern PPC32Instr* PPC32Instr_MulL       ( Bool syned, Bool hi32, HReg, HReg, HReg );
 extern PPC32Instr* PPC32Instr_Div        ( Bool syned, HReg dst, HReg srcL, HReg srcR );
-extern PPC32Instr* PPC32Instr_Call       ( PPC32CondCode, Addr32, Int );
+extern PPC32Instr* PPC32Instr_Call       ( PPC32CondCode, Addr32, UInt );
 extern PPC32Instr* PPC32Instr_Goto       ( IRJumpKind, PPC32CondCode cond, PPC32RI* dst );
 extern PPC32Instr* PPC32Instr_CMov32     ( PPC32CondCode, HReg dst, PPC32RI* src );
 extern PPC32Instr* PPC32Instr_Load       ( UChar sz, Bool syned,
index bb81624708a5f760d61fdea8a6242089a8fa6c1b..56b33e6994ee99d1572b3e34511e92257cb0643c 100644 (file)
@@ -411,6 +411,7 @@ void doHelperCall ( ISelEnv* env,
    HReg          tmpregs[PPC32_N_REGPARMS];
    Bool          go_fast;
    Int           n_args, i, argreg;
+   UInt          argiregs;
 
    /* Marshal args for a call and do the call.
 
@@ -479,6 +480,7 @@ void doHelperCall ( ISelEnv* env,
    argregs[5] = hregPPC32_GPR8();
    argregs[6] = hregPPC32_GPR9();
    argregs[7] = hregPPC32_GPR10();
+   argiregs = 0;
 
    tmpregs[0] = tmpregs[1] = tmpregs[2] =
    tmpregs[3] = tmpregs[4] = tmpregs[5] =
@@ -518,6 +520,7 @@ void doHelperCall ( ISelEnv* env,
       /* FAST SCHEME */
       argreg = 0;
       if (passBBP) {
+         argiregs |= (1 << (argreg+3));
          addInstr(env, mk_iMOVds_RR( argregs[argreg], GuestStatePtr ));
          argreg++;
       }
@@ -527,6 +530,7 @@ void doHelperCall ( ISelEnv* env,
          vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||
                  typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
          if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) { 
+            argiregs |= (1 << (argreg+3));
             addInstr(env, mk_iMOVds_RR( argregs[argreg],
                                         iselIntExpr_R(env, args[i]) ));
          } else { // Ity_I64
@@ -535,7 +539,9 @@ void doHelperCall ( ISelEnv* env,
                argreg++;       // XXX: odd argreg => even rN
             vassert(argreg < PPC32_N_REGPARMS-1);
             iselInt64Expr(&rHi,&rLo, env, args[i]);
+            argiregs |= (1 << (argreg+3));
             addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
+            argiregs |= (1 << (argreg+3));
             addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
          }
          argreg++;
@@ -596,6 +602,7 @@ void doHelperCall ( ISelEnv* env,
             continue;
          /* None of these insns, including any spill code that might
             be generated, may alter the condition codes. */
+         argiregs |= (1 << (i+3));
          addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
       }
 
@@ -604,7 +611,7 @@ void doHelperCall ( ISelEnv* env,
    /* Finally, the call itself. */
    addInstr(env, PPC32Instr_Call( cc,
                                   (Addr32)toUInt(Ptr_to_ULong(cee->addr)),
-                                  n_args + (passBBP ? 1 : 0) ));
+                                  argiregs ));
 }