]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fixes to host_ppc32:
authorCerion Armour-Brown <cerion@valgrind.org>
Mon, 21 Feb 2005 15:09:19 +0000 (15:09 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Mon, 21 Feb 2005 15:09:19 +0000 (15:09 +0000)
 - correct assembly printouts for goto, load
 - emit_instrn
   - cmp: 7-crfD (f'ing ibm)
   - added mkLoadImm(), mkMoveReg()
   - call: 'target >> 2'
   - call,goto,cmov: fixed conditional jumps
   - goto: return correctly
   - set32: fix src,dst regs for flag rotate

 - isel:
   mk_iMOVds_RRI(): ORi, not ANDi

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

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

index 1372a2cd0853b8057ed21475737f4b4e7dc9d037..55d0effb44e18c64eaeec1d25f2e331466a5c63b 100644 (file)
@@ -778,17 +778,35 @@ void ppPPC32Instr ( PPC32Instr* i )
    case Pin_Goto:
       vex_printf("goto: ");
       if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
-         vex_printf("if (%%CR.%s) { ", 
+         vex_printf("if (%%crf0.%s) { ", 
                     showPPC32CondCode(i->Pin.Goto.cond));
       }
       if (i->Pin.Goto.jk != Ijk_Boring) {
-         vex_printf("la %%r31, $");
+         vex_printf("li %%r31, $");
          ppIRJumpKind(i->Pin.Goto.jk);
          vex_printf(" ; ");
       }
-      vex_printf("bca %s,%%r3, ", showPPC32CondCode(i->Pin.Goto.cond));
-      ppPPC32RI(i->Pin.Goto.dst);
-      vex_printf(" ; ret");
+      if (i->Pin.Goto.dst->tag == Pri_Imm) {
+         if (i->Pin.Goto.dst->Pri.Imm.imm32 < 0x10000) {
+            vex_printf("li %%r3, ");
+            ppPPC32RI(i->Pin.Goto.dst);
+            vex_printf(" ; ");
+         } else {
+            vex_printf("lis %%r3,0x%x ; ",
+                       i->Pin.Goto.dst->Pri.Imm.imm32 >> 16);
+            vex_printf("la %%r3,0x%x(%%r3) ; ",
+                       i->Pin.Goto.dst->Pri.Imm.imm32 & 0xFFFF);
+         }
+      } else {
+         vex_printf("if (%%r3 != ");
+         ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
+         vex_printf(") { mr %%r3,");
+         ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
+         vex_printf(" } ; ");
+      }
+      vex_printf("blr");
+      //      vex_printf("mtctr %%r_dst ; ");
+      //      vex_printf("bctr");
       if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
          vex_printf(" }");
       }
@@ -804,7 +822,7 @@ void ppPPC32Instr ( PPC32Instr* i )
    case Pin_Load: {
       UChar sz = i->Pin.Load.sz;
       Bool syned = i->Pin.Load.syned;
-      Bool idxd = (i->Pin.Load.src->tag == Pam_IR) ? True : False;
+      Bool idxd = (i->Pin.Load.src->tag == Pam_RR) ? True : False;
       vex_printf("l%c%c%s ",
                  (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
                  syned ? 'a' : 'z',
@@ -816,7 +834,7 @@ void ppPPC32Instr ( PPC32Instr* i )
    }
    case Pin_Store: {
       UChar sz = i->Pin.Store.sz;
-      Bool idxd = (i->Pin.Store.dst->tag == Pam_IR) ? True : False;
+      Bool idxd = (i->Pin.Store.dst->tag == Pam_RR) ? True : False;
       vex_printf("st%c%s ",
                  (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
                  idxd ? "x" : "" );
@@ -1827,6 +1845,38 @@ static UChar* doAMode_RR ( UChar* p, UInt op1, UInt op2,
    return p;
 }
 
+/* Load imm to r_dst */
+static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
+{
+   vassert(r_dst < 0x20);
+
+   if (imm < 0x10000) {
+      // CAB: Sign extends immediate...
+      // addi r_dst,0,imm  => li r_dst,imm
+      p = mkFormD(p, 14, r_dst, 0, imm);
+   } else {
+      // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
+      p = mkFormD(p, 15, r_dst, 0, (imm>>16));
+      // ori r_dst, r_dst, (imm & 0xFFFF)
+      p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
+   }
+   return p;
+}
+
+
+/* Move r_dst to r_src */
+static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
+{
+   vassert(r_dst < 0x20);
+   vassert(r_src < 0x20);
+
+   if (r_dst != r_src) {
+      /* or r_dst, r_src, r_src */
+      p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
+   }
+   return p;
+}
+
 
 /* Emit an instruction into buf and return the number of bytes used.
    Note that buf is not the insn's final place, and therefore it is
@@ -1948,7 +1998,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
    case Pin_Cmp32: {
       UInt opc1, opc2=0;
       UInt op = i->Pin.Cmp32.op;
-      UInt fld1 = i->Pin.Cmp32.crfD << 2;
+      UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
       UInt r1 = iregNo(i->Pin.Cmp32.src1);
       UInt r2, imm;
 
@@ -2079,7 +2129,6 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..       }
 
    case Pin_Call: {
-      Addr32 target;
       PPC32CondCode cond = i->Pin.Call.cond;
       UInt r_dst = 12;
       /* As per detailed comment for Pin_Call in
@@ -2088,17 +2137,15 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 
       /* jump over the following two insns if the condition does not
          hold */
-      if (i->Pin.Call.cond.test != Pct_ALWAYS) {
-         target = 16; /* num bytes in next insts */
-         /* bca ct,cf,target */
-         p = mkFormB(p, invertCondTest(cond.test), cond.flag, target, 1, 0);
+      if (cond.test != Pct_ALWAYS) {
+         /* don't know how many bytes to jump over yet...
+            make space for a jump instruction and fill in later. */
+         ptmp = p; /* fill in this bit later */
+         p += 4;
       }
 
-      /* addi r_dst,0,(target & 0xFFFF)
-         addis r_dst,r_dst,((target >> 16) & 0xFFFF) => load target to r_dst */
-      target = i->Pin.Call.target;
-      p = mkFormD(p, 14, r_dst, 0, (target & 0xFFFF));
-      p = mkFormD(p, 15, r_dst, r_dst, ((target>>16) & 0xFFFF) );
+      /* load target to r_dst */
+      p = mkLoadImm(p, r_dst, i->Pin.Call.target);
 
       /* mtspr 9,r_dst => move r_dst to count register */
       p = mkFormXFX(p, r_dst, 9, 467);
@@ -2106,6 +2153,15 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       /* bcctrl 20,0 => branch w. link to count register */
       p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
 
+      /* Fix up the conditional jump, if there was one. */
+      if (cond.test != Pct_ALWAYS) {
+         Int delta = p - ptmp;
+         vassert(delta >= 8 && delta <= 16);
+
+         /* bca !ct,cf,jump */
+         mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 1, 0);
+      }
+
 /* CAB: Hmm...
    "When possible, independent instructions should separate the load
    of the Count Register from the branch to prevent pipeline stalls." */
@@ -2115,7 +2171,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 
    case Pin_Goto: {
       UInt magic_num = 0;
-      UChar r_dst = 3;    /* Put target addr into %r3 */
+      UChar r_return = 3;    /* Put target addr into %r3 */
       PPC32CondCode cond = i->Pin.Goto.cond;
       UInt imm;
       
@@ -2123,15 +2179,15 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
          jump over the rest of it. */
       if (cond.test != Pct_ALWAYS) {
          /* jmp fwds if !condition */
-         imm = 8; /* num bytes in next insts */
-         /* bca ct,cf,imm */
-         p = mkFormB(p, invertCondTest(cond.test), cond.flag, imm, 1, 0);
+         /* don't know how many bytes to jump over yet...
+            make space for a jump instruction and fill in later. */
          ptmp = p; /* fill in this bit later */
-         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
+         p += 4;
       }
 
+      // cond succeeds...
+      
       /* If a non-boring, set GuestStatePtr appropriately. */
-      /* addi r31,0,magic_num */
       switch (i->Pin.Goto.jk) {
       case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
       case Ijk_Syscall:   magic_num = VEX_TRC_JMP_SYSCALL;   break;
@@ -2149,38 +2205,29 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       }
       if (magic_num !=0) {
          vassert(magic_num < 0x10000);
+         /* addi r31,0,magic_num */
          p = mkFormD(p, 14, 31, 0, magic_num);
       }
 
-      /* Get the destination address into %r3 */
+      /* Get the destination address into %r_return */
       if (i->Pin.Goto.dst->tag == Pri_Imm) {
          imm = i->Pin.Goto.dst->Pri.Imm.imm32;
-         if (imm < 0x10000) {
-            // addi r_dst,0,(imm & 0xFFFF)
-            p = mkFormD(p, 14, r_dst, 0, imm);
-         } else {
-            // addi r_dst,0,(imm & 0xFFFF)
-            // addis r_dst,r_dst,((imm >> 16) & 0xFFFF)
-            p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF));
-            p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF));
-         }
+         p = mkLoadImm(p, r_return, imm);
       } else {
          vassert(i->Pin.Goto.dst->tag == Pri_Reg);
-         UChar r_src = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
-         if (r_dst != r_src) {
-            /* add r_dst, 0, r_src */
-            p = mkFormXO(p, 31, r_dst, 0, r_src, 0, 266, 0);
-         }
+         UInt r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
+         p = mkMoveReg(p, r_return, r_dst);
       }
-
-      /* ret => bclr (always),0 */
+      
+      /* blr */
       p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);
 
       /* Fix up the conditional jump, if there was one. */
       if (cond.test != Pct_ALWAYS) {
          Int delta = p - ptmp;
-         vassert(delta > 0 && delta < 20);
-         *ptmp = (UChar)(delta-1);
+         vassert(delta >= 8 && delta <= 16);
+         /* bc !ct,cf,delta */
+         mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
       }
       goto done;
    }
@@ -2191,33 +2238,34 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       PPC32CondCode cond = i->Pin.CMov32.cond;
       UInt imm, r_src;
 
-      // branch (if cond false) over next instr
-      // bc false,cond,8
-      p = mkFormB(p, invertCondTest(cond.test), cond.flag, 8, 0, 0);
+      /* branch (if cond fails) over move instrs */
+      if (cond.test != Pct_ALWAYS) {
+         /* don't know how many bytes to jump over yet...
+            make space for a jump instruction and fill in later. */
+         ptmp = p; /* fill in this bit later */
+         p += 4;
+      }
 
       // cond true: move src => dst
       switch (i->Pin.CMov32.src->tag) {
       case Pri_Imm:
          imm = i->Pin.CMov32.src->Pri.Imm.imm32;
-         if (imm < 0x10000) {
-            // addi r_dst,0,imm
-            p = mkFormD(p, 14, r_dst, 0, imm);
-         } else {
-            // addi r_dst,0,(imm & 0xFFFF)
-            // addis r_dst,r_dst,((imm >> 16) & 0xFFFF)
-            p = mkFormD(p, 14, r_dst, 0, (imm & 0xFFFF));
-            p = mkFormD(p, 15, r_dst, r_dst, ((imm>>16) & 0xFFFF));
-         }
+         p = mkLoadImm(p, r_dst, imm);
          break;
       case Pri_Reg:
          r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
-         if (r_src != r_dst) {
-            /* add r_dst, 0, r_src */
-            p = mkFormXO(p, 31, r_dst, 0, r_src, 0, 266, 0);
-         }
+         p = mkMoveReg(p, r_dst, r_src);
          break;
       default: goto bad;
       }
+
+      /* Fix up the conditional jump, if there was one. */
+      if (cond.test != Pct_ALWAYS) {
+         Int delta = p - ptmp;
+         vassert(delta >= 4 && delta <= 12);
+         /* bc !ct,cf,delta */
+         mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
+      }
       goto done;
    }
 
@@ -2269,7 +2317,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 
          // r_dst = flag (rotate left and mask)
          //  => rlwinm r_dst,r_tmp,rot_imm,31,31
-         p = mkFormM(p, 21, r_dst, r_tmp, rot_imm, 31, 31, 0);
+         p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
 
          if (cond.test == Pct_FALSE) {
             // flip bit  => xori rD,rD,1
index f17047082e98f22e669ad0f5f358b43d751ce804..dacc14d8014067a86175c7469de73f23f6d66879 100644 (file)
@@ -336,7 +336,7 @@ static PPC32Instr* mk_iMOVds_RRI ( ISelEnv* env, HReg dst, PPC32RI* src )
       // CAB: addis (aka lis) would be good...
       addInstr(env, PPC32Instr_Alu32(Palu_ADD, dst, zero, PPC32RI_Imm(imm>>16)));
       addInstr(env, mk_sh32(env, Psh_SHL, dst, dst, PPC32RI_Imm(16)));
-      return PPC32Instr_Alu32(Palu_ADD, dst, dst, PPC32RI_Imm(imm & 0xFFFF));
+      return PPC32Instr_Alu32(Palu_OR, dst, dst, PPC32RI_Imm(imm & 0xFFFF));
    } else {
       return PPC32Instr_Alu32(Palu_ADD, dst, zero, src);
    }
@@ -1299,15 +1299,16 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
    case Iex_Mux0X: {
       if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
           && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
-         PPC32CondCode cond = mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
+         PPC32CondCode cc;
          HReg r8;
          HReg rX     = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
          PPC32RI* r0 = iselIntExpr_RI(env, e->Iex.Mux0X.expr0);
          HReg dst    = newVRegI(env);
          addInstr(env, mk_iMOVds_RR(dst,rX));
          r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
-         addInstr(env, PPC32Instr_Cmp32(Pcmp_U, 0, r8, PPC32RI_Imm(0)));
-         addInstr(env, PPC32Instr_CMov32(cond,dst,r0));
+         addInstr(env, PPC32Instr_Cmp32(Pcmp_U, 7, r8, PPC32RI_Imm(0)));
+         cc = mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
+         addInstr(env, PPC32Instr_CMov32(cc,dst,r0));
          return dst;
       }
       break;
@@ -1506,7 +1507,7 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
    DEFINE_PATTERN(p_32to1, unop(Iop_32to1,bind(0)));
    if (matchIRExpr(&mi,p_32to1,e)) {
       HReg dst = iselIntExpr_R(env, mi.bindee[0]);
-      addInstr(env, PPC32Instr_Cmp32(Pcmp_U, 0, dst, PPC32RI_Imm(1)));
+      addInstr(env, PPC32Instr_Cmp32(Pcmp_U, 7, dst, PPC32RI_Imm(1)));
       return mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
    }
 
@@ -1570,7 +1571,7 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
           e->Iex.Binop.op == Iop_CmpLE32S) {
          cmp_op = Pcmp_S;
       }
-      addInstr(env, PPC32Instr_Cmp32(cmp_op,0,r1,ri2));
+      addInstr(env, PPC32Instr_Cmp32(cmp_op,7,r1,ri2));
 
       switch (e->Iex.Binop.op) {
       case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_EQ );